ArrcttacsrjksX commited on
Commit
a627896
·
verified ·
1 Parent(s): 734cc36

Upload 2 files

Browse files
Files changed (2) hide show
  1. Backup/app(48).py +302 -0
  2. Backup/app(49).py +339 -0
Backup/app(48).py ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import subprocess
3
+ import os
4
+ import tempfile
5
+ import datetime
6
+ from pathlib import Path
7
+ from huggingface_hub import upload_file
8
+ from typing import Optional, Tuple, List, Union
9
+ import logging
10
+ import shutil
11
+ import base64
12
+ from PIL import Image
13
+ import io
14
+
15
+ # Configure logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(levelname)s - %(message)s'
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ class ImageToDxfConverter:
23
+ def __init__(self):
24
+ """Initialize the converter with configuration."""
25
+ # For Hugging Face Spaces, executable should be in the root directory
26
+ self.executable_path = Path("SimpleImageToDxfHavePass")
27
+ self.hf_token = os.getenv("HF_TOKEN")
28
+ self.repo_id = "ArrcttacsrjksX/ImageToAutocadData"
29
+
30
+ # Make executable file executable (Hugging Face Spaces specific)
31
+ try:
32
+ os.chmod(self.executable_path, 0o755)
33
+ logger.info(f"Set executable permissions for {self.executable_path}")
34
+ except Exception as e:
35
+ logger.error(f"Failed to set executable permissions: {e}")
36
+
37
+ def _ensure_directory(self, path: Union[str, Path]) -> Path:
38
+ """Ensure directory exists and return Path object."""
39
+ path = Path(path)
40
+ path.mkdir(parents=True, exist_ok=True)
41
+ return path
42
+
43
+ def _generate_output_paths(self, output_folder: Path, timestamp: str) -> dict:
44
+ """Generate all required output paths."""
45
+ return {
46
+ 'output_dxf': output_folder / f"{timestamp}_output.dxf",
47
+ 'debug_png': output_folder / f"{timestamp}_debug.png",
48
+ 'temp_dxf': output_folder / "_output.dxf",
49
+ 'temp_debug': output_folder / "_debug.png"
50
+ }
51
+
52
+ def _save_base64_image(self, base64_data: str) -> str:
53
+ """Save base64 image data to temporary file."""
54
+ try:
55
+ # Extract actual base64 data after comma
56
+ img_data = base64_data.split(',')[1]
57
+ img_bytes = base64.b64decode(img_data)
58
+
59
+ # Create temporary file
60
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file:
61
+ temp_file.write(img_bytes)
62
+ return temp_file.name
63
+
64
+ except Exception as e:
65
+ logger.error(f"Failed to save base64 image: {str(e)}")
66
+ return None
67
+
68
+ def convert_image(self,
69
+ image_input: Union[str, None],
70
+ use_lines: bool = False) -> Tuple[Optional[str], Optional[str], List[str]]:
71
+ """Convert image to DXF format."""
72
+ try:
73
+ # Input validation
74
+ if not image_input:
75
+ return None, None, []
76
+
77
+ # Handle base64 data
78
+ if isinstance(image_input, str) and image_input.startswith('data:image'):
79
+ temp_image_path = self._save_base64_image(image_input)
80
+ if not temp_image_path:
81
+ return None, None, []
82
+ image_path = temp_image_path
83
+ else:
84
+ image_path = image_input
85
+
86
+ # Setup output directory
87
+ output_dir = self._ensure_directory("OutputPDF")
88
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
89
+ paths = self._generate_output_paths(output_dir, timestamp)
90
+
91
+ # Prepare conversion command
92
+ command = [
93
+ f"./{self.executable_path}",
94
+ f"--imagePath={image_path}",
95
+ f"--outputPath={paths['temp_dxf']}",
96
+ f"--debug-output={paths['temp_debug']}"
97
+ ]
98
+ if use_lines:
99
+ command.append("--use-lines")
100
+
101
+ # Execute conversion
102
+ try:
103
+ result = subprocess.run(
104
+ command,
105
+ check=True,
106
+ capture_output=True,
107
+ text=True
108
+ )
109
+ logger.info(f"Conversion output: {result.stdout}")
110
+ except subprocess.CalledProcessError as e:
111
+ logger.error(f"Conversion failed: {e.stderr}")
112
+ return None, None, []
113
+
114
+ # Move temporary files to final locations
115
+ shutil.move(paths['temp_dxf'], paths['output_dxf'])
116
+ if use_lines and os.path.exists(paths['temp_debug']):
117
+ shutil.move(paths['temp_debug'], paths['debug_png'])
118
+
119
+ # Upload files to Hugging Face
120
+ uploaded_files = []
121
+ if self.hf_token:
122
+ try:
123
+ date_folder = timestamp
124
+
125
+ # Upload input image
126
+ uploaded_input = upload_file(
127
+ path_or_fileobj=image_path,
128
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{Path(image_path).name}",
129
+ repo_id=self.repo_id,
130
+ token=self.hf_token
131
+ )
132
+ uploaded_files.append(uploaded_input)
133
+
134
+ # Upload DXF output
135
+ uploaded_dxf = upload_file(
136
+ path_or_fileobj=str(paths['output_dxf']),
137
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{paths['output_dxf'].name}",
138
+ repo_id=self.repo_id,
139
+ token=self.hf_token
140
+ )
141
+ uploaded_files.append(uploaded_dxf)
142
+
143
+ # Upload debug image if available
144
+ if use_lines and os.path.exists(paths['debug_png']):
145
+ uploaded_debug = upload_file(
146
+ path_or_fileobj=str(paths['debug_png']),
147
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{paths['debug_png'].name}",
148
+ repo_id=self.repo_id,
149
+ token=self.hf_token
150
+ )
151
+ uploaded_files.append(uploaded_debug)
152
+ except Exception as e:
153
+ logger.error(f"Upload failed: {str(e)}")
154
+
155
+ # Clean up temporary file if it was created from base64
156
+ if isinstance(image_input, str) and image_input.startswith('data:image'):
157
+ try:
158
+ os.unlink(image_path)
159
+ except Exception as e:
160
+ logger.error(f"Failed to clean up temporary file: {str(e)}")
161
+
162
+ return (
163
+ str(paths['output_dxf']),
164
+ str(paths['debug_png']) if use_lines and os.path.exists(paths['debug_png']) else None,
165
+ uploaded_files
166
+ )
167
+
168
+ except Exception as e:
169
+ logger.error(f"Conversion failed: {str(e)}")
170
+ return None, None, []
171
+
172
+
173
+ def create_gradio_interface():
174
+ """Create and configure the Gradio interface."""
175
+ converter = ImageToDxfConverter()
176
+
177
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
178
+ gr.Markdown("""
179
+ # Image to DXF Converter
180
+ Convert your images to DXF format for CAD software.
181
+ Press Ctrl+V to paste image from clipboard.
182
+ """)
183
+
184
+ # Thêm state để lưu base64 data
185
+ clipboard_image = gr.State()
186
+
187
+ with gr.Row():
188
+ with gr.Column(scale=2):
189
+ image_input = gr.Image(
190
+ type="filepath",
191
+ label="Input Image",
192
+ elem_id="image_input",
193
+ height=300
194
+ )
195
+ with gr.Column(scale=1):
196
+ use_lines_checkbox = gr.Checkbox(
197
+ label="Enable line detection",
198
+ value=False,
199
+ elem_id="use_lines"
200
+ )
201
+ convert_btn = gr.Button(
202
+ "Convert to DXF",
203
+ variant="primary",
204
+ elem_id="convert_btn"
205
+ )
206
+
207
+ with gr.Row():
208
+ with gr.Column():
209
+ dxf_output = gr.File(
210
+ label="DXF Output",
211
+ elem_id="dxf_output"
212
+ )
213
+ with gr.Column():
214
+ debug_output = gr.Image(
215
+ type="filepath",
216
+ label="Debug Preview",
217
+ elem_id="debug_output",
218
+ height=300
219
+ )
220
+
221
+ # Cập nhật JavaScript để xử lý paste
222
+ demo.load(js="""
223
+ function initPasteHandler() {
224
+ document.addEventListener('paste', function(e) {
225
+ e.preventDefault();
226
+
227
+ const items = e.clipboardData.items;
228
+
229
+ for (let i = 0; i < items.length; i++) {
230
+ const item = items[i];
231
+
232
+ if (item.type.indexOf('image') !== -1) {
233
+ const file = item.getAsFile();
234
+ const reader = new FileReader();
235
+
236
+ reader.onload = function(event) {
237
+ fetch(event.target.result)
238
+ .then(res => res.blob())
239
+ .then(blob => {
240
+ const file = new File([blob], "pasted_image.png", { type: "image/png" });
241
+
242
+ const dt = new DataTransfer();
243
+ dt.items.add(file);
244
+
245
+ const fileInput = document.querySelector('#image_input input[type="file"]');
246
+ if (fileInput) {
247
+ fileInput.files = dt.files;
248
+
249
+ const event = new Event('change', { 'bubbles': true });
250
+ fileInput.dispatchEvent(event);
251
+
252
+ setTimeout(() => {
253
+ const convertBtn = document.querySelector('#convert_btn');
254
+ if (convertBtn) convertBtn.click();
255
+ }, 500); // Tăng timeout lên 500ms
256
+ }
257
+ });
258
+ };
259
+
260
+ reader.readAsDataURL(file);
261
+ break;
262
+ }
263
+ }
264
+ });
265
+ }
266
+
267
+ if (document.readyState === 'complete') {
268
+ initPasteHandler();
269
+ } else {
270
+ window.addEventListener('load', initPasteHandler);
271
+ }
272
+
273
+ // Thêm handler để debug
274
+ console.log('Paste handler initialized');
275
+ """)
276
+
277
+ # Event handlers
278
+ convert_btn.click(
279
+ fn=converter.convert_image,
280
+ inputs=[image_input, use_lines_checkbox],
281
+ outputs=[dxf_output, debug_output],
282
+ )
283
+
284
+ return demo
285
+
286
+ def main():
287
+ """Main entry point with proper error handling."""
288
+ try:
289
+ demo = create_gradio_interface()
290
+ demo.queue()
291
+ demo.launch(
292
+ server_name="0.0.0.0",
293
+ server_port=7860,
294
+ show_api=False,
295
+ share=False,
296
+ )
297
+ except Exception as e:
298
+ logger.critical(f"Application failed to start: {str(e)}")
299
+ raise
300
+
301
+ if __name__ == "__main__":
302
+ main()
Backup/app(49).py ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import subprocess
3
+ import os
4
+ import tempfile
5
+ import datetime
6
+ from pathlib import Path
7
+ from huggingface_hub import upload_file
8
+ from typing import Optional, Tuple, List, Union
9
+ import logging
10
+ import shutil
11
+ import base64
12
+ from PIL import Image
13
+ import io
14
+
15
+ # Configure logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format='%(asctime)s - %(levelname)s - %(message)s'
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ class ImageToDxfConverter:
23
+ def __init__(self):
24
+ """Initialize the converter with configuration."""
25
+ self.executable_path = Path("SimpleImageToDxfHavePass")
26
+ self.hf_token = os.getenv("HF_TOKEN")
27
+ self.repo_id = "ArrcttacsrjksX/ImageToAutocadData"
28
+
29
+ try:
30
+ os.chmod(self.executable_path, 0o755)
31
+ logger.info(f"Set executable permissions for {self.executable_path}")
32
+ except Exception as e:
33
+ logger.error(f"Failed to set executable permissions: {e}")
34
+
35
+ def _process_image(self, image_path: str, size_multiplier: float, black_white: bool) -> str:
36
+ """Process the image with size multiplier and black/white conversion."""
37
+ try:
38
+ with Image.open(image_path) as img:
39
+ # Calculate new size
40
+ new_width = int(img.width * size_multiplier)
41
+ new_height = int(img.height * size_multiplier)
42
+
43
+ # Resize image
44
+ img = img.resize((new_width, new_height), Image.LANCZOS)
45
+
46
+ # Convert to black and white if option is selected
47
+ if black_white:
48
+ img = img.convert('L') # Convert to grayscale
49
+ img = img.point(lambda x: 0 if x < 128 else 255, '1') # Convert to binary
50
+
51
+ # Save processed image to temporary file
52
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file:
53
+ img.save(temp_file.name, 'PNG')
54
+ return temp_file.name
55
+
56
+ except Exception as e:
57
+ logger.error(f"Failed to process image: {str(e)}")
58
+ return image_path
59
+
60
+ def _ensure_directory(self, path: Union[str, Path]) -> Path:
61
+ """Ensure directory exists and return Path object."""
62
+ path = Path(path)
63
+ path.mkdir(parents=True, exist_ok=True)
64
+ return path
65
+
66
+ def _generate_output_paths(self, output_folder: Path, timestamp: str) -> dict:
67
+ """Generate all required output paths."""
68
+ return {
69
+ 'output_dxf': output_folder / f"{timestamp}_output.dxf",
70
+ 'debug_png': output_folder / f"{timestamp}_debug.png",
71
+ 'temp_dxf': output_folder / "_output.dxf",
72
+ 'temp_debug': output_folder / "_debug.png"
73
+ }
74
+
75
+ def _save_base64_image(self, base64_data: str) -> str:
76
+ """Save base64 image data to temporary file."""
77
+ try:
78
+ img_data = base64_data.split(',')[1]
79
+ img_bytes = base64.b64decode(img_data)
80
+
81
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file:
82
+ temp_file.write(img_bytes)
83
+ return temp_file.name
84
+
85
+ except Exception as e:
86
+ logger.error(f"Failed to save base64 image: {str(e)}")
87
+ return None
88
+
89
+ def convert_image(self,
90
+ image_input: Union[str, None],
91
+ use_lines: bool = False,
92
+ size_multiplier: float = 1.0,
93
+ black_white: bool = False) -> Tuple[Optional[str], Optional[str], List[str]]:
94
+ """Convert image to DXF format with size multiplier and black/white option."""
95
+ try:
96
+ if not image_input:
97
+ return None, None, []
98
+
99
+ # Handle base64 data
100
+ if isinstance(image_input, str) and image_input.startswith('data:image'):
101
+ temp_image_path = self._save_base64_image(image_input)
102
+ if not temp_image_path:
103
+ return None, None, []
104
+ image_path = temp_image_path
105
+ else:
106
+ image_path = image_input
107
+
108
+ # Process image with size multiplier and black/white conversion
109
+ processed_image_path = self._process_image(image_path, size_multiplier, black_white)
110
+
111
+ # Setup output directory
112
+ output_dir = self._ensure_directory("OutputPDF")
113
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
114
+ paths = self._generate_output_paths(output_dir, timestamp)
115
+
116
+ # Prepare conversion command
117
+ command = [
118
+ f"./{self.executable_path}",
119
+ f"--imagePath={processed_image_path}",
120
+ f"--outputPath={paths['temp_dxf']}",
121
+ f"--debug-output={paths['temp_debug']}"
122
+ ]
123
+ if use_lines:
124
+ command.append("--use-lines")
125
+
126
+ try:
127
+ result = subprocess.run(
128
+ command,
129
+ check=True,
130
+ capture_output=True,
131
+ text=True
132
+ )
133
+ logger.info(f"Conversion output: {result.stdout}")
134
+ except subprocess.CalledProcessError as e:
135
+ logger.error(f"Conversion failed: {e.stderr}")
136
+ return None, None, []
137
+
138
+ # Move temporary files to final locations
139
+ shutil.move(paths['temp_dxf'], paths['output_dxf'])
140
+ if use_lines and os.path.exists(paths['temp_debug']):
141
+ shutil.move(paths['temp_debug'], paths['debug_png'])
142
+
143
+ # Upload files to Hugging Face
144
+ uploaded_files = []
145
+ if self.hf_token:
146
+ try:
147
+ date_folder = timestamp
148
+
149
+ uploaded_input = upload_file(
150
+ path_or_fileobj=processed_image_path,
151
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{Path(processed_image_path).name}",
152
+ repo_id=self.repo_id,
153
+ token=self.hf_token
154
+ )
155
+ uploaded_files.append(uploaded_input)
156
+
157
+ uploaded_dxf = upload_file(
158
+ path_or_fileobj=str(paths['output_dxf']),
159
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{paths['output_dxf'].name}",
160
+ repo_id=self.repo_id,
161
+ token=self.hf_token
162
+ )
163
+ uploaded_files.append(uploaded_dxf)
164
+
165
+ if use_lines and os.path.exists(paths['debug_png']):
166
+ uploaded_debug = upload_file(
167
+ path_or_fileobj=str(paths['debug_png']),
168
+ path_in_repo=f"datasets/{self.repo_id}/{date_folder}/{paths['debug_png'].name}",
169
+ repo_id=self.repo_id,
170
+ token=self.hf_token
171
+ )
172
+ uploaded_files.append(uploaded_debug)
173
+ except Exception as e:
174
+ logger.error(f"Upload failed: {str(e)}")
175
+
176
+ # Clean up temporary files
177
+ if isinstance(image_input, str) and image_input.startswith('data:image'):
178
+ try:
179
+ os.unlink(image_path)
180
+ except Exception as e:
181
+ logger.error(f"Failed to clean up temporary file: {str(e)}")
182
+
183
+ if processed_image_path != image_path:
184
+ try:
185
+ os.unlink(processed_image_path)
186
+ except Exception as e:
187
+ logger.error(f"Failed to clean up processed image file: {str(e)}")
188
+
189
+ return (
190
+ str(paths['output_dxf']),
191
+ str(paths['debug_png']) if use_lines and os.path.exists(paths['debug_png']) else None,
192
+ uploaded_files
193
+ )
194
+
195
+ except Exception as e:
196
+ logger.error(f"Conversion failed: {str(e)}")
197
+ return None, None, []
198
+
199
+ def create_gradio_interface():
200
+ """Create and configure the Gradio interface."""
201
+ converter = ImageToDxfConverter()
202
+
203
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
204
+ gr.Markdown("""
205
+ # Image to DXF Converter
206
+ Convert your images to DXF format for CAD software.
207
+ Press Ctrl+V to paste image from clipboard.
208
+ """)
209
+
210
+ clipboard_image = gr.State()
211
+
212
+ with gr.Row():
213
+ with gr.Column(scale=2):
214
+ image_input = gr.Image(
215
+ type="filepath",
216
+ label="Input Image",
217
+ elem_id="image_input",
218
+ height=300
219
+ )
220
+ with gr.Column(scale=1):
221
+ size_multiplier = gr.Number(
222
+ label="Image Size Multiplier",
223
+ value=1.0,
224
+ minimum=0.1,
225
+ maximum=10.0,
226
+ step=0.1,
227
+ elem_id="size_multiplier"
228
+ )
229
+ use_lines_checkbox = gr.Checkbox(
230
+ label="Enable line detection",
231
+ value=False,
232
+ elem_id="use_lines"
233
+ )
234
+ black_white_checkbox = gr.Checkbox(
235
+ label="Convert to Black & White",
236
+ value=False,
237
+ elem_id="black_white"
238
+ )
239
+ convert_btn = gr.Button(
240
+ "Convert to DXF",
241
+ variant="primary",
242
+ elem_id="convert_btn"
243
+ )
244
+
245
+ with gr.Row():
246
+ with gr.Column():
247
+ dxf_output = gr.File(
248
+ label="DXF Output",
249
+ elem_id="dxf_output"
250
+ )
251
+ with gr.Column():
252
+ debug_output = gr.Image(
253
+ type="filepath",
254
+ label="Debug Preview",
255
+ elem_id="debug_output",
256
+ height=300
257
+ )
258
+
259
+ # JavaScript for paste handling
260
+ demo.load(js="""
261
+ function initPasteHandler() {
262
+ document.addEventListener('paste', function(e) {
263
+ e.preventDefault();
264
+
265
+ const items = e.clipboardData.items;
266
+
267
+ for (let i = 0; i < items.length; i++) {
268
+ const item = items[i];
269
+
270
+ if (item.type.indexOf('image') !== -1) {
271
+ const file = item.getAsFile();
272
+ const reader = new FileReader();
273
+
274
+ reader.onload = function(event) {
275
+ fetch(event.target.result)
276
+ .then(res => res.blob())
277
+ .then(blob => {
278
+ const file = new File([blob], "pasted_image.png", { type: "image/png" });
279
+
280
+ const dt = new DataTransfer();
281
+ dt.items.add(file);
282
+
283
+ const fileInput = document.querySelector('#image_input input[type="file"]');
284
+ if (fileInput) {
285
+ fileInput.files = dt.files;
286
+
287
+ const event = new Event('change', { 'bubbles': true });
288
+ fileInput.dispatchEvent(event);
289
+
290
+ setTimeout(() => {
291
+ const convertBtn = document.querySelector('#convert_btn');
292
+ if (convertBtn) convertBtn.click();
293
+ }, 500);
294
+ }
295
+ });
296
+ };
297
+
298
+ reader.readAsDataURL(file);
299
+ break;
300
+ }
301
+ }
302
+ });
303
+ }
304
+
305
+ if (document.readyState === 'complete') {
306
+ initPasteHandler();
307
+ } else {
308
+ window.addEventListener('load', initPasteHandler);
309
+ }
310
+
311
+ console.log('Paste handler initialized');
312
+ """)
313
+
314
+ # Event handlers
315
+ convert_btn.click(
316
+ fn=converter.convert_image,
317
+ inputs=[image_input, use_lines_checkbox, size_multiplier, black_white_checkbox],
318
+ outputs=[dxf_output, debug_output],
319
+ )
320
+
321
+ return demo
322
+
323
+ def main():
324
+ """Main entry point with proper error handling."""
325
+ try:
326
+ demo = create_gradio_interface()
327
+ demo.queue()
328
+ demo.launch(
329
+ server_name="0.0.0.0",
330
+ server_port=7860,
331
+ show_api=False,
332
+ share=False,
333
+ )
334
+ except Exception as e:
335
+ logger.critical(f"Application failed to start: {str(e)}")
336
+ raise
337
+
338
+ if __name__ == "__main__":
339
+ main()