SG2325 commited on
Commit
8a05493
·
verified ·
1 Parent(s): 40d81c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -202
app.py CHANGED
@@ -1,203 +1,251 @@
1
- import os
2
- import zipfile
3
- from datetime import datetime
4
- from pdf2image import convert_from_path
5
- from PIL import Image
6
- import gradio as gr
7
- import tempfile
8
- import shutil
9
-
10
- def pdf_to_jpg_with_gradio(files, quality=95, dpi=200):
11
- """
12
- GradioでアップロードされたPDFファイルをJPGに変換する関数
13
-
14
- Args:
15
- files: Gradioでアップロードされたファイルのリスト
16
- quality (int): JPGの品質 (1-100, デフォルト: 95)
17
- dpi (int): 解像度 (デフォルト: 200)
18
-
19
- Returns:
20
- tuple: (処理結果メッセージ, ZIPファイルパス)
21
- """
22
-
23
- if not files:
24
- return "ファイルが選択されていません。", None
25
-
26
- # 現在の日時でフォルダ名を作成
27
- now = datetime.now()
28
- timestamp_folder = now.strftime("%Y%m%d_%H%M%S")
29
-
30
- # 一時的な作業フォルダを作成
31
- temp_dir = tempfile.mkdtemp()
32
- output_folder = os.path.join(temp_dir, timestamp_folder)
33
- os.makedirs(output_folder, exist_ok=True)
34
-
35
- try:
36
- results = []
37
- processed_files = []
38
-
39
- for file in files:
40
- try:
41
- print(f"処理中: {os.path.basename(file.name)}")
42
-
43
- # PDFを画像に変換(Hugging Face Spacesではpopplerは既にインストール済み)
44
- pages = convert_from_path(file.name, dpi=dpi)
45
-
46
- # ファイル名から拡張子を除去
47
- base_name = os.path.splitext(os.path.basename(file.name))[0]
48
-
49
- # 各ページを保存
50
- for i, page in enumerate(pages):
51
- if len(pages) == 1:
52
- # 単一ページの場合
53
- jpg_filename = f"{base_name}.jpg"
54
- else:
55
- # 複数ページの場合
56
- jpg_filename = f"{base_name}_page_{i+1:03d}.jpg"
57
-
58
- jpg_path = os.path.join(output_folder, jpg_filename)
59
-
60
- # JPGとして保存
61
- page.save(jpg_path, 'JPEG', quality=quality, optimize=True)
62
- processed_files.append(jpg_path)
63
-
64
- results.append(f"{os.path.basename(file.name)} - 変換完了")
65
-
66
- except Exception as e:
67
- results.append(f"{os.path.basename(file.name)} - エラー: {str(e)}")
68
-
69
- # ZIPファイルを作成
70
- zip_path = os.path.join(temp_dir, f"converted_jpg_{timestamp_folder}.zip")
71
- with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
72
- for file_path in processed_files:
73
- arcname = os.path.basename(file_path)
74
- zipf.write(file_path, arcname)
75
-
76
- # 結果メッセージを作成
77
- success_message = f"""
78
- 🎉 PDF to JPG 変換完了!
79
-
80
- 📊 処理結果:
81
- {chr(10).join(results)}
82
-
83
- 📝 変換されたファイル数: {len(processed_files)}
84
- 処理完了時刻: {now.strftime('%Y年%m月%d日 %H:%M:%S')}
85
-
86
- 💾 ZIPファイルをダウンロードしてご利用ください。
87
- """
88
-
89
- return success_message, zip_path
90
-
91
- except Exception as e:
92
- error_message = f"❌ 処理中にエラーが発生しました: {str(e)}"
93
- return error_message, None
94
-
95
- def create_gradio_interface():
96
- """
97
- Gradioインターフェースを作成
98
- """
99
-
100
- with gr.Blocks(title="PDF to JPG Converter", theme=gr.themes.Soft()) as demo:
101
- gr.Markdown("# 📄➡️🖼️ PDF to JPG 変換ツール")
102
- gr.Markdown("PDFファイルをアップロードして、JPG形式に変換します。変換完了後、ZIPファイルとしてダウンロードできます。")
103
-
104
- with gr.Row():
105
- with gr.Column(scale=2):
106
- file_input = gr.File(
107
- label="📁 PDFファイルを選択",
108
- file_count="multiple",
109
- file_types=[".pdf"],
110
- height=200
111
- )
112
-
113
- with gr.Row():
114
- quality_slider = gr.Slider(
115
- minimum=1,
116
- maximum=100,
117
- value=95,
118
- step=1,
119
- label="🎨 JPG品質",
120
- info="1-100範囲で指定(高いほど高品質)"
121
- )
122
-
123
- dpi_slider = gr.Slider(
124
- minimum=72,
125
- maximum=300,
126
- value=200,
127
- step=1,
128
- label="📐 解像度 (DPI)",
129
- info="72-300の範囲で指定(高いほど高解像度)"
130
- )
131
-
132
- convert_btn = gr.Button("🔄 変換開始", variant="primary", size="lg")
133
-
134
- with gr.Column(scale=1):
135
- gr.Markdown("### 📋 使用方法")
136
- gr.Markdown("""
137
- 1. **PDFファイルを選択** - 複数選択可能
138
- 2. **品質・解像度を調整** - 必要に応じて
139
- 3. **変換開始ボタンをクリック**
140
- 4. **ZIPファイルをダウンロード**
141
-
142
- ### 📁 ダウンロード
143
- - 変換されたJPGファイルはZIP形式でダウンロードされます
144
- - ファイル名には作業日時が含まれます
145
- """)
146
-
147
- with gr.Row():
148
- with gr.Column(scale=2):
149
- output_text = gr.Textbox(
150
- label="📊 処理結果",
151
- lines=10,
152
- max_lines=15,
153
- show_copy_button=True,
154
- interactive=False
155
- )
156
-
157
- with gr.Column(scale=1):
158
- download_file = gr.File(
159
- label="📥 変換済みファイル(ZIP)",
160
- interactive=False
161
- )
162
-
163
- # イベントハンドラー
164
- convert_btn.click(
165
- fn=pdf_to_jpg_with_gradio,
166
- inputs=[file_input, quality_slider, dpi_slider],
167
- outputs=[output_text, download_file]
168
- )
169
-
170
- # 使用例
171
- gr.Markdown("### 💡 Tips")
172
- gr.Markdown("""
173
- - **品質95**: 通常の用途に最適
174
- - **解像度200**: 文書用途に適した解像度
175
- - **複数ページPDF**: 自動的に分割されます
176
- - **大きなファイル**: 処理に時間がかかる場合があります
177
- """)
178
-
179
- gr.Markdown("### 🔒 プライバシー")
180
- gr.Markdown("""
181
- アップロードされたファイルは処理後に自動的に削除されます。
182
- セキュリティを重視し、機密情報を含むファイルの取り扱いにご注意ください。
183
- """)
184
-
185
- return demo
186
-
187
- def main():
188
- """
189
- メイン関数 - Gradioアプリケーションを起動
190
- """
191
-
192
- print("🚀 PDF to JPG Converter を起動中...")
193
-
194
- # Gradioインターフェースを作成・起動
195
- demo = create_gradio_interface()
196
-
197
- demo.launch(
198
- share=False,
199
- show_error=True
200
- )
201
-
202
- if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  main()
 
1
+ import os
2
+ import zipfile
3
+ from datetime import datetime
4
+ from pdf2image import convert_from_path
5
+ from PIL import Image
6
+ import gradio as gr
7
+ import tempfile
8
+ import shutil
9
+
10
+ def pdf_to_jpg_with_gradio(files, quality=95, dpi=200):
11
+ """
12
+ GradioでアップロードされたPDFファイルをJPGに変換する関数
13
+
14
+ Args:
15
+ files: Gradioでアップロードされたファイルのリスト
16
+ quality (int): JPGの品質 (1-100, デフォルト: 95)
17
+ dpi (int): 解像度 (デフォルト: 200)
18
+
19
+ Returns:
20
+ tuple: (処理結果メッセージ, ZIPファイルパス)
21
+ """
22
+
23
+ if not files:
24
+ return "ファイルが選択されていません。", None
25
+
26
+ # 現在の日時でフォルダ名を作成
27
+ now = datetime.now()
28
+ timestamp_folder = now.strftime("%Y%m%d_%H%M%S")
29
+
30
+ # 一時的な作業フォルダを作成
31
+ temp_dir = tempfile.mkdtemp()
32
+ output_folder = os.path.join(temp_dir, timestamp_folder)
33
+ os.makedirs(output_folder, exist_ok=True)
34
+
35
+ print(f"🔧 Debug: temp_dir = {temp_dir}")
36
+ print(f"🔧 Debug: output_folder = {output_folder}")
37
+
38
+ try:
39
+ results = []
40
+ processed_files = []
41
+
42
+ for file_idx, file in enumerate(files):
43
+ try:
44
+ print(f"📄 処理中 ({file_idx + 1}/{len(files)}): {os.path.basename(file.name)}")
45
+ print(f"🔧 Debug: file.name = {file.name}")
46
+
47
+ # ファイルの存在確認
48
+ if not os.path.exists(file.name):
49
+ results.append(f"✗ {os.path.basename(file.name)} - ファイルが見つかりません")
50
+ continue
51
+
52
+ # PDFを画像に変換
53
+ pages = convert_from_path(file.name, dpi=dpi)
54
+ print(f"🔧 Debug: {len(pages)} pages found")
55
+
56
+ # ファイル名から拡張子を除去
57
+ base_name = os.path.splitext(os.path.basename(file.name))[0]
58
+ print(f"🔧 Debug: base_name = {base_name}")
59
+
60
+ # 各ページを保存
61
+ for i, page in enumerate(pages):
62
+ if len(pages) == 1:
63
+ # 単一ページの場合
64
+ jpg_filename = f"{base_name}.jpg"
65
+ else:
66
+ # 複数ページの場合
67
+ jpg_filename = f"{base_name}_page_{i+1:03d}.jpg"
68
+
69
+ jpg_path = os.path.join(output_folder, jpg_filename)
70
+ print(f"🔧 Debug: saving to {jpg_path}")
71
+
72
+ # JPGとして保存
73
+ page.save(jpg_path, 'JPEG', quality=quality, optimize=True)
74
+
75
+ # ファイルが実際に作成されたか確認
76
+ if os.path.exists(jpg_path):
77
+ processed_files.append(jpg_path)
78
+ print(f"✅ 保存成功: {jpg_filename} ({os.path.getsize(jpg_path)} bytes)")
79
+ else:
80
+ print(f"❌ 保存失敗: {jpg_filename}")
81
+
82
+ results.append(f"✓ {os.path.basename(file.name)} - 変換完了 ({len(pages)} pages)")
83
+
84
+ except Exception as e:
85
+ error_msg = f"✗ {os.path.basename(file.name)} - エラー: {str(e)}"
86
+ results.append(error_msg)
87
+ print(f"❌ {error_msg}")
88
+
89
+ print(f"🔧 Debug: processed_files count = {len(processed_files)}")
90
+ print(f"🔧 Debug: processed_files = {processed_files}")
91
+
92
+ if not processed_files:
93
+ error_message = "❌ 変換できたファイルがありません。エラーログを確認してください。"
94
+ return error_message, None
95
+
96
+ # ZIPファイルを作成
97
+ zip_path = os.path.join(temp_dir, f"converted_jpg_{timestamp_folder}.zip")
98
+ print(f"🔧 Debug: creating ZIP at {zip_path}")
99
+
100
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
101
+ for file_path in processed_files:
102
+ if os.path.exists(file_path):
103
+ arcname = os.path.basename(file_path)
104
+ zipf.write(file_path, arcname)
105
+ print(f"✅ ZIP追加: {arcname}")
106
+ else:
107
+ print(f" ファイル見つからず: {file_path}")
108
+
109
+ # ZIPファイルの確認
110
+ if os.path.exists(zip_path):
111
+ zip_size = os.path.getsize(zip_path)
112
+ print(f"🔧 Debug: ZIP file created, size = {zip_size} bytes")
113
+
114
+ # ZIP内容の確認
115
+ with zipfile.ZipFile(zip_path, 'r') as zipf:
116
+ zip_contents = zipf.namelist()
117
+ print(f"🔧 Debug: ZIP contents = {zip_contents}")
118
+ else:
119
+ print(f" ZIP file not created at {zip_path}")
120
+ return "❌ ZIPファイル作成に失敗しました。", None
121
+
122
+ # 結果メッセージを作成
123
+ success_message = f"""
124
+ 🎉 PDF to JPG 変換完了!
125
+
126
+ 📊 処理結果:
127
+ {chr(10).join(results)}
128
+
129
+ 📝 変換されたファイル数: {len(processed_files)}
130
+ ⏰ 処理完了時刻: {now.strftime('%Y年%m月%d日 %H:%M:%S')}
131
+ 📦 ZIPファイルサイズ: {zip_size / 1024:.1f} KB
132
+
133
+ 💾 ZIPファイルをダウンロードしてご利用ください。
134
+ """
135
+
136
+ return success_message, zip_path
137
+
138
+ except Exception as e:
139
+ error_message = f"❌ 処理中にエラーが発生しました: {str(e)}"
140
+ print(f"❌ Main error: {str(e)}")
141
+ return error_message, None
142
+
143
+ def create_gradio_interface():
144
+ """
145
+ Gradioインターフェースを作成
146
+ """
147
+
148
+ with gr.Blocks(title="PDF to JPG Converter", theme=gr.themes.Soft()) as demo:
149
+ gr.Markdown("# 📄➡️🖼️ PDF to JPG 変換ツール")
150
+ gr.Markdown("PDFファイルをアップロードして、JPG形式に変換します。変換完了後、ZIPファイルとしてダウンロードできます。")
151
+
152
+ with gr.Row():
153
+ with gr.Column(scale=2):
154
+ file_input = gr.File(
155
+ label="📁 PDFファイルを選択",
156
+ file_count="multiple",
157
+ file_types=[".pdf"],
158
+ height=200
159
+ )
160
+
161
+ with gr.Row():
162
+ quality_slider = gr.Slider(
163
+ minimum=1,
164
+ maximum=100,
165
+ value=95,
166
+ step=1,
167
+ label="🎨 JPG品質",
168
+ info="1-100の範囲で指定(高いほど高品質)"
169
+ )
170
+
171
+ dpi_slider = gr.Slider(
172
+ minimum=72,
173
+ maximum=300,
174
+ value=200,
175
+ step=1,
176
+ label="📐 解像度 (DPI)",
177
+ info="72-300の範囲で指定(高いほど高解像度)"
178
+ )
179
+
180
+ convert_btn = gr.Button("��� 変換開始", variant="primary", size="lg")
181
+
182
+ with gr.Column(scale=1):
183
+ gr.Markdown("### 📋 使用方法")
184
+ gr.Markdown("""
185
+ 1. **PDFファイルを選択** - 複数選択可能
186
+ 2. **品質・解像度を調整** - 必要に応じて
187
+ 3. **変換開始ボタンをクリック**
188
+ 4. **ZIPファイルをダウンロード**
189
+
190
+ ### 📁 ダウンロード
191
+ - 変換されたJPGファイルはZIP形式でダウンロードされます
192
+ - ファイル名には作業日時が含まれます
193
+ """)
194
+
195
+ with gr.Row():
196
+ with gr.Column(scale=2):
197
+ output_text = gr.Textbox(
198
+ label="📊 処理結果",
199
+ lines=10,
200
+ max_lines=15,
201
+ show_copy_button=True,
202
+ interactive=False
203
+ )
204
+
205
+ with gr.Column(scale=1):
206
+ download_file = gr.File(
207
+ label="📥 変換済みファイル(ZIP)",
208
+ interactive=False
209
+ )
210
+
211
+ # イベントハンドラー
212
+ convert_btn.click(
213
+ fn=pdf_to_jpg_with_gradio,
214
+ inputs=[file_input, quality_slider, dpi_slider],
215
+ outputs=[output_text, download_file]
216
+ )
217
+
218
+ # 使用例
219
+ gr.Markdown("### 💡 Tips")
220
+ gr.Markdown("""
221
+ - **品質95**: 通常の用途に最適
222
+ - **解像度200**: 文書用途に適した解像度
223
+ - **複数ページPDF**: 自動的に分割されます
224
+ - **大きなファイル**: 処理に時間がかかる場合があります
225
+ """)
226
+
227
+ gr.Markdown("### 🔒 プライバシー")
228
+ gr.Markdown("""
229
+ アップロードされたファイルは処理後に自動的に削除されます。
230
+ セキュリティを重視し、機密情報を含むファイルの取り扱いにご注意ください。
231
+ """)
232
+
233
+ return demo
234
+
235
+ def main():
236
+ """
237
+ メイン関数 - Gradioアプリケーションを起動
238
+ """
239
+
240
+ print("🚀 PDF to JPG Converter を起動中...")
241
+
242
+ # Gradioインターフェースを作成・起動
243
+ demo = create_gradio_interface()
244
+
245
+ demo.launch(
246
+ share=False,
247
+ show_error=True
248
+ )
249
+
250
+ if __name__ == "__main__":
251
  main()