ImageToAutocad / app.py
ArrcttacsrjksX's picture
Update app.py
d9aa302 verified
raw
history blame
7.62 kB
import gradio as gr
import subprocess
import os
import tempfile
import datetime
import ezdxf
import cairosvg
from huggingface_hub import upload_file
def convert_image_to_dxf(image_file, output_folder=None, use_lines=False):
try:
# Validate input image
if image_file is None:
return "No image provided", None, None
# Define output folder, using a temp directory if none is specified
if not output_folder:
output_folder = tempfile.mkdtemp()
else:
os.makedirs(output_folder, exist_ok=True)
# Generate the date-based output file name
current_date = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
image_path = image_file
output_path = os.path.join(output_folder, f"{current_date}_output.dxf")
debug_output_path = os.path.join(output_folder, f"{current_date}_debug.png")
# Prepare the command arguments
command_args = ["./SimpleImageToDxfHavePass"]
# Add --use-lines if the checkbox is checked
if use_lines:
command_args.append("--use-lines")
# Add other arguments
command_args.extend([f"--imagePath={image_path}", f"--outputPath={output_path}", f"--debug-output={debug_output_path}"])
# Execute conversion command
result = subprocess.run(
command_args,
check=True,
capture_output=True
)
# Log stdout for debugging
print(result.stdout.decode('utf-8'))
# Check if conversion was successful
if not os.path.exists(output_path):
return "Conversion failed: DXF file was not created.", None, None
# Convert LWPOLYLINE to POLYLINE if necessary
convert_lwpolylines_to_polylines(output_path)
# Convert DXF to PNG for preview
dxf_image_path = convert_dxf_to_image(output_path)
# Prepare folder structure for upload
date_folder = f"{current_date}"
# Hugging Face token
hf_token = os.getenv("HF_TOKEN")
if not hf_token:
return "Hugging Face token not found", None, None
# Upload input image, output DXF, and optionally debug image to Hugging Face in a date-based folder
uploaded_files = []
# Upload input image
uploaded_input = upload_file(
path_or_fileobj=image_path,
path_in_repo=f"datasets/ArrcttacsrjksX/ImageToAutocadData/{date_folder}/{os.path.basename(image_path)}",
repo_id="ArrcttacsrjksX/ImageToAutocadData",
token=hf_token
)
uploaded_files.append(uploaded_input)
# Upload DXF output
uploaded_dxf = upload_file(
path_or_fileobj=output_path,
path_in_repo=f"datasets/ArrcttacsrjksX/ImageToAutocadData/{date_folder}/{os.path.basename(output_path)}",
repo_id="ArrcttacsrjksX/ImageToAutocadData",
token=hf_token
)
uploaded_files.append(uploaded_dxf)
# If the checkbox is ticked, upload debug image
if use_lines:
uploaded_debug = upload_file(
path_or_fileobj=debug_output_path,
path_in_repo=f"datasets/ArrcttacsrjksX/ImageToAutocadData/{date_folder}/{os.path.basename(debug_output_path)}",
repo_id="ArrcttacsrjksX/ImageToAutocadData",
token=hf_token
)
uploaded_files.append(uploaded_debug)
# Return files directly for download in Gradio interface
return dxf_image_path, uploaded_files
except subprocess.CalledProcessError as e:
error_msg = f"Error converting image to DXF: {e.stderr.decode('utf-8') if e.stderr else e}"
return error_msg, None, None
def convert_lwpolylines_to_polylines(dxf_file):
"""
Convert LWPOLYLINE entities to POLYLINE entities in the given DXF file.
This is to ensure compatibility for rendering and image conversion.
"""
doc = ezdxf.readfile(dxf_file)
# Find all LWPOLYLINE entities and convert them to POLYLINE entities
for lwpline in doc.modelspace().query('LWPOLYLINE'):
# Create a POLYLINE entity from the LWPOLYLINE's vertices
vertices = lwpline.vertices() # Call the method to get vertices
polyline = doc.modelspace().add_polyline2d(vertices)
# Copy attributes from the LWPOLYLINE to the new POLYLINE
polyline.dxf.layer = lwpline.dxf.layer
polyline.dxf.color = lwpline.dxf.color
# Delete the original LWPOLYLINE
lwpline.destroy()
# Save the modified DXF file
doc.saveas(dxf_file)
def convert_dxf_to_image(dxf_file):
"""
Convert DXF to an image (PNG format) for preview purposes.
This function uses ezdxf and cairosvg to render a DXF file.
"""
try:
doc = ezdxf.readfile(dxf_file)
# Check the DXF content and print out basic details for debugging
print(f"DXF content:\n{doc}")
# Inspect DXF entities
for entity in doc.modelspace():
print(f"Entity type: {entity.dxftype()}")
# If the DXF contains basic line entities, we can proceed with rendering
# Create a temporary SVG file to render the DXF content
svg_file = tempfile.mktemp(suffix=".svg")
doc.saveas(svg_file)
# Convert SVG to PNG using cairosvg
png_file = svg_file.replace(".svg", ".png")
cairosvg.svg2png(url=svg_file, write_to=png_file)
return png_file
except Exception as e:
print(f"Error converting DXF to image: {e}")
return None
def main():
with gr.Blocks() as demo:
with gr.Tabs():
# Tab for conversion
with gr.TabItem("Image to DXF"):
gr.Markdown("# SimpleImageToDxfHavePass")
# Input row for image and optional output folder
with gr.Row():
image_input = gr.Image(type="filepath", label="Input Image (PNG/JPG)")
output_folder = gr.Textbox(label="Output Folder (optional)", placeholder="Leave blank to use a temporary folder")
# Checkbox to decide whether to use --use-lines
use_lines_checkbox = gr.Checkbox(label="Use --use-lines for conversion", value=False) # Default is False
# Outputs: DXF image preview and DXF file download link
with gr.Row():
dxf_preview = gr.Image(type="filepath", label="DXF Preview Image")
dxf_output = gr.File(label="DXF File Download")
# Conversion button with event binding
convert_btn = gr.Button("Convert to DXF")
convert_btn.click(
convert_image_to_dxf,
inputs=[image_input, output_folder, use_lines_checkbox],
outputs=[dxf_preview, dxf_output]
)
# About tab
with gr.TabItem("About"):
gr.Markdown("This Gradio app allows users to convert an image to a DXF file using the SimpleImageToDxfHavePass command-line tool.")
demo.launch(share=True)
if __name__ == "__main__":
try:
subprocess.run(['chmod', '+x', './SimpleImageToDxfHavePass'], check=True)
except subprocess.CalledProcessError as e:
print(f"Error setting permissions: {e}")
exit(1)
main()