Spaces:
Sleeping
Sleeping
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() | |