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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -21
app.py CHANGED
@@ -22,18 +22,41 @@ logger = logging.getLogger(__name__)
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)
@@ -52,11 +75,9 @@ class ImageToDxfConverter:
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
@@ -67,10 +88,11 @@ class ImageToDxfConverter:
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
 
@@ -83,6 +105,9 @@ class ImageToDxfConverter:
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")
@@ -91,14 +116,13 @@ class ImageToDxfConverter:
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,
@@ -122,16 +146,14 @@ class ImageToDxfConverter:
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}",
@@ -140,7 +162,6 @@ class ImageToDxfConverter:
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']),
@@ -152,12 +173,18 @@ class ImageToDxfConverter:
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']),
@@ -169,7 +196,6 @@ class ImageToDxfConverter:
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()
@@ -181,7 +207,6 @@ def create_gradio_interface():
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():
@@ -193,11 +218,24 @@ def create_gradio_interface():
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",
@@ -218,7 +256,7 @@ def create_gradio_interface():
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) {
@@ -252,7 +290,7 @@ def create_gradio_interface():
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
  };
@@ -270,14 +308,13 @@ def create_gradio_interface():
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
 
 
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)
 
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
 
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
 
 
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")
 
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,
 
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}",
 
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']),
 
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']),
 
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()
 
207
  Press Ctrl+V to paste image from clipboard.
208
  """)
209
 
 
210
  clipboard_image = gr.State()
211
 
212
  with gr.Row():
 
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",
 
256
  height=300
257
  )
258
 
259
+ # JavaScript for paste handling
260
  demo.load(js="""
261
  function initPasteHandler() {
262
  document.addEventListener('paste', function(e) {
 
290
  setTimeout(() => {
291
  const convertBtn = document.querySelector('#convert_btn');
292
  if (convertBtn) convertBtn.click();
293
+ }, 500);
294
  }
295
  });
296
  };
 
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