avans06 commited on
Commit
9bde466
·
1 Parent(s): 8b989ce

Fix: Handle non-ASCII filenames in image processing

Browse files
Files changed (2) hide show
  1. .gitignore +1 -0
  2. app.py +58 -32
.gitignore CHANGED
@@ -27,6 +27,7 @@ share/python-wheels/
27
  .installed.cfg
28
  *.egg
29
  MANIFEST
 
30
 
31
  # PyInstaller
32
  # Usually these files are written by a python script from a template
 
27
  .installed.cfg
28
  *.egg
29
  MANIFEST
30
+ output/
31
 
32
  # PyInstaller
33
  # Usually these files are written by a python script from a template
app.py CHANGED
@@ -10,9 +10,9 @@ import gradio as gr
10
  import os
11
  import cv2
12
  import numpy as np
13
- import tempfile
14
  import shutil
15
  from tqdm import tqdm
 
16
 
17
  from image_processing.panel import generate_panel_blocks, generate_panel_blocks_by_ai
18
  from manga_panel_processor import remove_border
@@ -49,20 +49,31 @@ def process_images(
49
  if not input_files:
50
  raise gr.Error("No images uploaded. Please upload at least one image.")
51
 
52
- # Create a temporary directory to store the processed panels
53
- with tempfile.TemporaryDirectory() as temp_panel_dir:
54
- print(f"Created temporary directory for panels: {temp_panel_dir}")
 
 
 
 
 
 
55
 
 
56
  for image_file in tqdm(input_files, desc="Processing Images"):
57
  try:
58
  # The image_file object from gr.Files has a .name attribute with the temp path
59
  original_filename = os.path.basename(image_file.name)
60
  filename_no_ext, file_ext = os.path.splitext(original_filename)
 
 
 
 
 
 
61
 
62
- # Read the image using OpenCV
63
- image = cv2.imread(image_file.name)
64
  if image is None:
65
- print(f"Warning: Could not read image {original_filename}. Skipping.")
66
  continue
67
 
68
  # Select the processing function based on the chosen method
@@ -85,57 +96,65 @@ def process_images(
85
  # Should not happen with Radio button selection
86
  panel_blocks = []
87
 
 
88
  if not panel_blocks:
89
- print(f"Warning: No panels found in {original_filename}.")
90
- continue
91
 
92
  # Determine the output path for the panels of this image
93
  if separate_folders:
94
  # Create a sub-directory for each image
95
- image_output_folder = os.path.join(temp_panel_dir, filename_no_ext)
96
  os.makedirs(image_output_folder, exist_ok=True)
97
  else:
98
  # Output all panels to the root of the temp directory
99
- image_output_folder = temp_panel_dir
100
 
101
  # Save each panel block
102
  for i, panel in enumerate(panel_blocks):
103
  if remove_borders:
104
  panel = remove_border(panel)
 
 
105
  if separate_folders:
106
- # e.g., /tmp/xyz/image1/panel_0.png
107
- panel_filename = f"panel_{i}{file_ext if file_ext else '.png'}"
108
  else:
109
- # e.g., /tmp/xyz/image1_panel_0.png
110
- panel_filename = f"{filename_no_ext}_panel_{i}{file_ext if file_ext else '.png'}"
111
 
112
  output_path = os.path.join(image_output_folder, panel_filename)
113
- cv2.imwrite(output_path, panel)
 
 
 
 
 
 
 
 
 
114
 
115
  except Exception as e:
116
  print(f"Error processing {original_filename}: {e}")
117
- raise gr.Error(f"Failed to process {original_filename}: {e}")
118
-
 
119
  # After processing all images, check if any panels were generated
120
- if not os.listdir(temp_panel_dir):
121
  raise gr.Error("Processing complete, but no panels were extracted from any of the images.")
122
-
123
- # --- Create a zip file ---
124
-
125
- # Create a separate temporary directory to hold the final zip file.
126
- # Gradio will handle cleaning this up after serving the file to the user.
127
- zip_output_dir = tempfile.mkdtemp()
128
-
129
- # Define the base name for our archive (path + filename without extension)
130
- zip_path_base = os.path.join(zip_output_dir, "adenzu_output")
131
 
132
- # Create the zip file. shutil.make_archive will add the '.zip' extension.
133
- # The first argument is the full path for the output file (minus extension).
134
- # The third argument is the directory to be zipped.
135
  final_zip_path = shutil.make_archive(
136
  base_name=zip_path_base,
137
  format='zip',
138
- root_dir=temp_panel_dir
139
  )
140
 
141
  print(f"Created ZIP file at: {final_zip_path}")
@@ -143,6 +162,13 @@ def process_images(
143
  # Gradio takes this path and provides it as a download link.
144
  return final_zip_path
145
 
 
 
 
 
 
 
 
146
 
147
  def main():
148
  """
 
10
  import os
11
  import cv2
12
  import numpy as np
 
13
  import shutil
14
  from tqdm import tqdm
15
+ from datetime import datetime
16
 
17
  from image_processing.panel import generate_panel_blocks, generate_panel_blocks_by_ai
18
  from manga_panel_processor import remove_border
 
49
  if not input_files:
50
  raise gr.Error("No images uploaded. Please upload at least one image.")
51
 
52
+ # Create a unique, temporary sub-directory inside the 'output' folder for this run.
53
+ main_output_dir = "output"
54
+ os.makedirs(main_output_dir, exist_ok=True)
55
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
56
+
57
+ # All intermediate panel files will be stored here before being zipped.
58
+ # This directory will be created inside 'output' and removed after zipping.
59
+ panel_output_dir = os.path.join(main_output_dir, f"temp_panels_{timestamp}")
60
+ os.makedirs(panel_output_dir)
61
 
62
+ try:
63
  for image_file in tqdm(input_files, desc="Processing Images"):
64
  try:
65
  # The image_file object from gr.Files has a .name attribute with the temp path
66
  original_filename = os.path.basename(image_file.name)
67
  filename_no_ext, file_ext = os.path.splitext(original_filename)
68
+
69
+ # Read image with Unicode path support to handle non-ASCII filenames.
70
+ # Read the file into a numpy array first.
71
+ stream = np.fromfile(image_file.name, np.uint8)
72
+ # Decode the numpy array into an image.
73
+ image = cv2.imdecode(stream, cv2.IMREAD_COLOR)
74
 
 
 
75
  if image is None:
76
+ print(f"Warning: Could not read or decode image {original_filename}. Skipping.")
77
  continue
78
 
79
  # Select the processing function based on the chosen method
 
96
  # Should not happen with Radio button selection
97
  panel_blocks = []
98
 
99
+ # If no panels were detected, use the original image as a single panel.
100
  if not panel_blocks:
101
+ print(f"Warning: No panels found in {original_filename}. Using the original image.")
102
+ panel_blocks = [image]
103
 
104
  # Determine the output path for the panels of this image
105
  if separate_folders:
106
  # Create a sub-directory for each image
107
+ image_output_folder = os.path.join(panel_output_dir, filename_no_ext)
108
  os.makedirs(image_output_folder, exist_ok=True)
109
  else:
110
  # Output all panels to the root of the temp directory
111
+ image_output_folder = panel_output_dir
112
 
113
  # Save each panel block
114
  for i, panel in enumerate(panel_blocks):
115
  if remove_borders:
116
  panel = remove_border(panel)
117
+
118
+ save_ext = file_ext if file_ext else '.png'
119
  if separate_folders:
120
+ # e.g., /tmp/xyz/image_name/panel_0.png
121
+ panel_filename = f"panel_{i}{save_ext}"
122
  else:
123
+ # e.g., /tmp/xyz/image_name_panel_0.png
124
+ panel_filename = f"{filename_no_ext}_panel_{i}{save_ext}"
125
 
126
  output_path = os.path.join(image_output_folder, panel_filename)
127
+
128
+ # Write image with Unicode path support.
129
+ # Encode the image to a memory buffer based on the file extension.
130
+ is_success, buffer = cv2.imencode(save_ext, panel)
131
+ if not is_success:
132
+ print(f"Warning: Could not encode panel {panel_filename}. Skipping.")
133
+ continue
134
+ # Write the buffer to a file using Python's standard I/O.
135
+ with open(output_path, 'wb') as f:
136
+ f.write(buffer)
137
 
138
  except Exception as e:
139
  print(f"Error processing {original_filename}: {e}")
140
+ # Optionally, re-raise as a Gradio error to notify the user.
141
+ # raise gr.Error(f"Failed to process {original_filename}: {e}")
142
+
143
  # After processing all images, check if any panels were generated
144
+ if not os.listdir(panel_output_dir):
145
  raise gr.Error("Processing complete, but no panels were extracted from any of the images.")
146
+
147
+ # --- Create a zip file in the 'output' directory ---
148
+ zip_filename_base = f"adenzu_output_{timestamp}"
149
+
150
+ # Define the full path for our archive (path + filename without extension).
151
+ zip_path_base = os.path.join(main_output_dir, zip_filename_base)
 
 
 
152
 
153
+ # Create the zip file from the temporary panel directory.
 
 
154
  final_zip_path = shutil.make_archive(
155
  base_name=zip_path_base,
156
  format='zip',
157
+ root_dir=panel_output_dir
158
  )
159
 
160
  print(f"Created ZIP file at: {final_zip_path}")
 
162
  # Gradio takes this path and provides it as a download link.
163
  return final_zip_path
164
 
165
+ finally:
166
+ # Clean up the temporary panel directory, leaving only the final ZIP file.
167
+ # This block executes whether the 'try' block succeeds or fails.
168
+ if os.path.exists(panel_output_dir):
169
+ print(f"Cleaning up temporary panel directory: {panel_output_dir}")
170
+ shutil.rmtree(panel_output_dir)
171
+
172
 
173
  def main():
174
  """