Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,135 +1,50 @@
|
|
1 |
import gradio as gr
|
2 |
-
import tempfile
|
3 |
from pdf2image import convert_from_path
|
4 |
-
import
|
5 |
-
import
|
6 |
-
import
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
"""
|
28 |
-
アップロードされたPDFの各ページを画像に変換し
|
29 |
-
- 画像サイズ
|
30 |
-
- 総ピクセル数
|
31 |
-
- ぼけ度
|
32 |
-
- コントラスト
|
33 |
-
- 推定DPI
|
34 |
-
などをもとにAudiverisでの利用適性を判定
|
35 |
-
"""
|
36 |
-
MAX_PIXELS_AUDIVERIS = 20_000_000
|
37 |
-
results = []
|
38 |
-
overall_rating = "OK"
|
39 |
-
|
40 |
-
try:
|
41 |
-
with tempfile.TemporaryDirectory() as tmpdir:
|
42 |
-
# PDF → 画像変換
|
43 |
-
images = convert_from_path(pdf_file.name, dpi=300, output_folder=tmpdir)
|
44 |
-
doc = fitz.open(pdf_file.name)
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
width, height = img.size
|
50 |
-
total_pixels = width * height
|
51 |
-
reasons = []
|
52 |
-
page_rating = "OK"
|
53 |
-
|
54 |
-
# Audiverisのピクセル上限チェック
|
55 |
-
if total_pixels > MAX_PIXELS_AUDIVERIS:
|
56 |
-
page_rating = "非推奨(画像が大きすぎる)"
|
57 |
-
reasons.append(f"総ピクセル数 {total_pixels:,} > 20,000,000")
|
58 |
-
|
59 |
-
# 解像度チェック
|
60 |
-
if width < 1000 or height < 1000 and "非推奨" not in page_rating:
|
61 |
-
page_rating = "非推奨(解像度が小さい)"
|
62 |
-
reasons.append("幅または高さが1000px未満")
|
63 |
-
elif width < 1500 or height < 1500 and page_rating == "OK":
|
64 |
-
page_rating = "注意(やや低め)"
|
65 |
-
|
66 |
-
# ぼけ度チェック
|
67 |
-
blur_score = estimate_blurriness(img)
|
68 |
-
if blur_score < 30 and "非推奨" not in page_rating:
|
69 |
-
page_rating = "非推奨(ぼけている)"
|
70 |
-
reasons.append(f"ぼけ度={blur_score:.1f}")
|
71 |
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
reasons.append(f"コントラスト={contrast_score:.1f}")
|
77 |
|
78 |
-
|
79 |
-
rect = page.rect
|
80 |
-
width_pt = rect.width
|
81 |
-
height_pt = rect.height
|
82 |
-
dpi_x = width / (width_pt / 72)
|
83 |
-
dpi_y = height / (height_pt / 72)
|
84 |
-
dpi_infos.append(f"ページ{i+1}推定DPI: {dpi_x:.1f}x{dpi_y:.1f}")
|
85 |
-
|
86 |
-
# 理由をまとめる
|
87 |
-
reasons_str = "; ".join(reasons) if reasons else "条件クリア"
|
88 |
-
|
89 |
-
# ページ結果
|
90 |
-
results.append(
|
91 |
-
f"ページ{i+1}: {width}x{height}px / ピクセル数={total_pixels:,} / "
|
92 |
-
f"ぼけ度={blur_score:.1f} / コントラスト={contrast_score:.1f} → {page_rating} ({reasons_str})"
|
93 |
-
)
|
94 |
-
|
95 |
-
# 総合評価を更新
|
96 |
-
if "非推奨" in page_rating:
|
97 |
-
overall_rating = "非推奨"
|
98 |
-
elif "注意" in page_rating and overall_rating == "OK":
|
99 |
-
overall_rating = "注意"
|
100 |
-
|
101 |
-
# まとめテキスト
|
102 |
-
result_text = "\n".join(results + [""] + dpi_infos)
|
103 |
-
result_text += f"\n\n総合評価: {overall_rating}"
|
104 |
-
|
105 |
-
# 改善提案
|
106 |
-
if overall_rating == "非推奨":
|
107 |
-
result_text += "\n\n推奨対策: スキャン解像度を下げる・画像を縮小するなどして、ファイルサイズや画質を調整してください。"
|
108 |
-
|
109 |
-
return result_text, overall_rating
|
110 |
-
|
111 |
-
except Exception as e:
|
112 |
-
return f"処理中にエラーが発生しました: {str(e)}", "エラー"
|
113 |
-
|
114 |
-
# ========== Gradio UI部分 ==========
|
115 |
|
116 |
with gr.Blocks() as demo:
|
117 |
-
gr.Markdown("
|
118 |
gr.Markdown(
|
119 |
-
""
|
120 |
-
PDFをアップロードすると、ページごとの画像サイズ、ピクセル数、ぼけ度、コントラストを分析し、
|
121 |
-
Audiverisで使用可能かを「OK / 注意 / 非推奨」で推定します。
|
122 |
-
"""
|
123 |
)
|
124 |
-
|
125 |
with gr.Row():
|
126 |
-
pdf_input = gr.File(label="PDF
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
analyze_button.click(analyze_pdf, inputs=pdf_input, outputs=[result_output, rating_output])
|
133 |
|
134 |
-
|
135 |
-
demo.launch()
|
|
|
1 |
import gradio as gr
|
|
|
2 |
from pdf2image import convert_from_path
|
3 |
+
from PIL import Image
|
4 |
+
import img2pdf
|
5 |
+
import tempfile
|
6 |
+
import os
|
7 |
+
|
8 |
+
def downscale_pdf(pdf_file, max_width=3000, dpi=150):
|
9 |
+
with tempfile.TemporaryDirectory() as tmpdir:
|
10 |
+
# ステップ 1: PDF → 画像
|
11 |
+
images = convert_from_path(pdf_file.name, dpi=300, fmt='jpeg', output_folder=tmpdir)
|
12 |
+
|
13 |
+
downscaled_images = []
|
14 |
+
for i, img in enumerate(images):
|
15 |
+
w, h = img.size
|
16 |
+
total_px = w * h
|
17 |
+
print(f"Original Page {i+1}: {w}x{h} = {total_px}")
|
18 |
+
|
19 |
+
# サイズ制限
|
20 |
+
if w > max_width:
|
21 |
+
ratio = max_width / w
|
22 |
+
new_w = int(w * ratio)
|
23 |
+
new_h = int(h * ratio)
|
24 |
+
img = img.resize((new_w, new_h), Image.LANCZOS)
|
25 |
+
print(f"Downscaled Page {i+1}: {new_w}x{new_h} = {new_w * new_h}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
+
tmp_image_path = os.path.join(tmpdir, f"page_{i+1}.jpg")
|
28 |
+
img.save(tmp_image_path, "JPEG", quality=95)
|
29 |
+
downscaled_images.append(tmp_image_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
+
# ステップ 2: 画像 → PDF
|
32 |
+
output_pdf_path = os.path.join(tmpdir, "downscaled.pdf")
|
33 |
+
with open(output_pdf_path, "wb") as f:
|
34 |
+
f.write(img2pdf.convert(downscaled_images))
|
|
|
35 |
|
36 |
+
return output_pdf_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
with gr.Blocks() as demo:
|
39 |
+
gr.Markdown("## PDFダウンサイザー for Audiveris")
|
40 |
gr.Markdown(
|
41 |
+
"PDFをアップロードすると、ページ画像を縮小してAudiveris向けに最適化したPDFを生成します。"
|
|
|
|
|
|
|
42 |
)
|
|
|
43 |
with gr.Row():
|
44 |
+
pdf_input = gr.File(label="PDFファイルをアップロード")
|
45 |
+
pdf_output = gr.File(label="変換後PDF")
|
46 |
+
|
47 |
+
convert_button = gr.Button("変換してダウンロード")
|
48 |
+
convert_button.click(fn=downscale_pdf, inputs=pdf_input, outputs=pdf_output)
|
|
|
|
|
49 |
|
50 |
+
demo.launch()
|
|