Zatimm commited on
Commit
86a1d4a
·
verified ·
1 Parent(s): 8d682e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -43
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import fitz # PyMuPDF kütüphanesi
3
  from PIL import Image
4
  import os
 
5
 
6
  # Geçici dosyaları saklamak için bir dizin oluşturalım.
7
  # Hugging Face Spaces ortamında bu gereklidir.
@@ -9,26 +10,25 @@ TEMP_DIR = "temp_files"
9
  if not os.path.exists(TEMP_DIR):
10
  os.makedirs(TEMP_DIR)
11
 
12
- def create_preview_image(pdf_path):
13
  """
14
  Yüklenen PDF'in ilk 10 sayfasını şeffaf bir şekilde üst üste bindirerek
15
  tek bir önizleme görüntüsü oluşturur. Bu, Briss'teki gibi ortak bir
16
  kırpma alanı bulmayı kolaylaştırır.
17
  """
18
  if not pdf_path:
19
- return None, None, "Lütfen bir PDF dosyası yükleyin."
20
 
21
  try:
22
  doc = fitz.open(pdf_path)
23
  if len(doc) == 0:
24
- return None, None, "Yüklenen PDF dosyası boş."
25
 
26
  # İlk sayfanın boyutlarını temel alalım.
27
  base_page = doc.load_page(0)
28
  width, height = int(base_page.rect.width), int(base_page.rect.height)
29
 
30
  # Üst üste bindirilecek sayfalar için boş bir tuval (RGBA formatında).
31
- # RGBA, şeffaflığı (alpha kanalı) destekler.
32
  composite_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
33
 
34
  # Performans için en fazla ilk 10 sayfayı işleyelim.
@@ -36,67 +36,49 @@ def create_preview_image(pdf_path):
36
 
37
  for i in range(page_count_to_process):
38
  page = doc.load_page(i)
39
- # Sayfayı şeffaf arka planlı bir resme dönüştür.
40
  pix = page.get_pixmap(alpha=True)
41
  page_image = Image.frombytes("RGBA", [pix.width, pix.height], pix.samples)
42
 
43
- # Gerekirse resmi ana tuval boyutuna yeniden boyutlandır.
44
  if page_image.size != (width, height):
45
  page_image = page_image.resize((width, height), Image.LANCZOS)
46
 
47
- # Sayfaları hafif şeffaf yaparak üst üste ekle.
48
- # Her sayfanın altındaki sayfaları da gösterebilmek için bir maske kullanıyoruz.
49
- alpha_value = int(255 / (i * 0.5 + 2)) # Giderek soluklaşan bir etki için
50
  mask = Image.new("L", page_image.size, alpha_value)
51
  composite_image.paste(page_image, (0, 0), mask)
52
 
53
  preview_image_path = os.path.join(TEMP_DIR, "preview.png")
54
  composite_image.save(preview_image_path)
55
 
56
- # Orijinal PDF yolu ve önizleme boyutlarını bir sonraki adım için sakla.
57
- # Ayrıca kullanıcıya bilgi mesajı göster.
58
  return pdf_path, (width, height), preview_image_path
59
  except Exception as e:
60
- return None, None, f"Bir hata oluştu: {str(e)}"
61
 
62
- def crop_pdf(original_pdf_path, preview_dims, crop_box_coords):
63
  """
64
  Kullanıcının seçtiği alana göre PDF'in tüm sayfalarını kırpar ve
65
  sonucu yeni bir PDF dosyası olarak döndürür.
66
  """
67
- if not all([original_pdf_path, preview_dims, crop_box_coords]):
68
- raise gr.Error("PDF yüklenmemiş veya kırpma alanı seçilmemiş. Lütfen adımları takip edin.")
 
 
69
 
70
  try:
71
  doc = fitz.open(original_pdf_path)
72
- if len(doc) == 0:
73
- raise gr.Error("PDF dosyası işlenemiyor.")
74
-
75
- # Gradio'dan gelen seçili alanın piksel koordinatları.
76
  x1, y1, x2, y2 = crop_box_coords
77
-
78
- # Önizleme resmi ve orijinal PDF sayfası boyutları.
79
  preview_width, preview_height = preview_dims
80
  pdf_page_rect = doc.load_page(0).rect
81
  pdf_width, pdf_height = pdf_page_rect.width, pdf_page_rect.height
82
 
83
- # Piksel koordinatlarını PDF'in 'point' birimine ölçekle.
84
  scale_x = pdf_width / preview_width
85
  scale_y = pdf_height / preview_height
86
 
87
- # Yeni kırpma kutusunu (crop box) oluştur.
88
- crop_rect = fitz.Rect(
89
- x1 * scale_x,
90
- y1 * scale_y,
91
- x2 * scale_x,
92
- y2 * scale_y
93
- )
94
 
95
- # PDF'in her sayfası için kırpma kutusunu ayarla.
96
  for page in doc:
97
  page.set_cropbox(crop_rect)
98
 
99
- # Kırpılmış dosyayı geçici dizine kaydet.
100
  output_pdf_path = os.path.join(TEMP_DIR, "cropped_output.pdf")
101
  doc.save(output_pdf_path, garbage=4, deflate=True, clean=True)
102
  doc.close()
@@ -113,43 +95,56 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="teal", secondary_hue="orange"))
113
  **Bu araç, bir PDF'in tüm sayfalarını aynı anda, tek bir seçimle kırpmanızı sağlar.**
114
  1. **PDF Yükle:** Kırpmak istediğiniz PDF dosyasını yükleyin. İlk 10 sayfanın üst üste bindirilmiş bir önizlemesi oluşturulacaktır.
115
  2. **Alan Seç:** Fare ile sürükleyerek resim üzerinde kalmasını istediğiniz alanı seçin.
116
- 3. **Kırp & İndir:** "PDF'i Kırp ve İndir" düğmesine tıklayın. İşlem tamamlandığında kırpılmış dosyanız hazır olacaktır.
117
  """
118
  )
119
 
120
  # Arka planda veri tutmak için State'ler (durumlar)
121
  original_pdf_path_state = gr.State()
122
  preview_dims_state = gr.State()
123
-
 
124
  with gr.Row():
125
  with gr.Column(scale=1):
126
  pdf_upload_input = gr.File(label="1. PDF Dosyasını Yükle", file_types=[".pdf"])
127
- crop_button = gr.Button("✂️ PDF'i Kırp ve İndir", variant="primary", scale=2)
128
  pdf_download_output = gr.File(label="Sonuç (İndirmeye Hazır)", interactive=False)
129
 
130
  with gr.Column(scale=3):
131
- # 'select' aracı ile kullanıcı bir kutu çizebilir.
132
  image_preview_output = gr.Image(
133
  label="2. Kırpma Alanını Seçin",
134
- tool="select",
135
  interactive=True
136
  )
137
-
138
  # Event Listeners (Olay Zinciri)
139
 
140
- # 1. PDF yüklendiğinde -> create_preview_image fonksiyonunu çalıştır.
141
  pdf_upload_input.upload(
142
  fn=create_preview_image,
143
  inputs=[pdf_upload_input],
144
- outputs=[original_pdf_path_state, preview_dims_state, image_preview_output]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  )
146
 
147
- # 2. Kırpma butonuna tıklandığında -> crop_pdf fonksiyonunu çalıştır.
148
- # image_preview_output.select event'inden gelen koordinatları doğrudan kullan.
149
  crop_button.click(
150
  fn=crop_pdf,
151
- inputs=[original_pdf_path_state, preview_dims_state, image_preview_output.select_data],
152
  outputs=[pdf_download_output]
153
  )
154
 
155
- app.launch(debug=True)
 
2
  import fitz # PyMuPDF kütüphanesi
3
  from PIL import Image
4
  import os
5
+ import typing
6
 
7
  # Geçici dosyaları saklamak için bir dizin oluşturalım.
8
  # Hugging Face Spaces ortamında bu gereklidir.
 
10
  if not os.path.exists(TEMP_DIR):
11
  os.makedirs(TEMP_DIR)
12
 
13
+ def create_preview_image(pdf_path: str) -> tuple[typing.Optional[str], typing.Optional[tuple], typing.Optional[str]]:
14
  """
15
  Yüklenen PDF'in ilk 10 sayfasını şeffaf bir şekilde üst üste bindirerek
16
  tek bir önizleme görüntüsü oluşturur. Bu, Briss'teki gibi ortak bir
17
  kırpma alanı bulmayı kolaylaştırır.
18
  """
19
  if not pdf_path:
20
+ return None, None, None
21
 
22
  try:
23
  doc = fitz.open(pdf_path)
24
  if len(doc) == 0:
25
+ raise gr.Error("Yüklenen PDF dosyası boş veya geçersiz.")
26
 
27
  # İlk sayfanın boyutlarını temel alalım.
28
  base_page = doc.load_page(0)
29
  width, height = int(base_page.rect.width), int(base_page.rect.height)
30
 
31
  # Üst üste bindirilecek sayfalar için boş bir tuval (RGBA formatında).
 
32
  composite_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
33
 
34
  # Performans için en fazla ilk 10 sayfayı işleyelim.
 
36
 
37
  for i in range(page_count_to_process):
38
  page = doc.load_page(i)
 
39
  pix = page.get_pixmap(alpha=True)
40
  page_image = Image.frombytes("RGBA", [pix.width, pix.height], pix.samples)
41
 
 
42
  if page_image.size != (width, height):
43
  page_image = page_image.resize((width, height), Image.LANCZOS)
44
 
45
+ alpha_value = int(255 / (i * 0.5 + 2))
 
 
46
  mask = Image.new("L", page_image.size, alpha_value)
47
  composite_image.paste(page_image, (0, 0), mask)
48
 
49
  preview_image_path = os.path.join(TEMP_DIR, "preview.png")
50
  composite_image.save(preview_image_path)
51
 
 
 
52
  return pdf_path, (width, height), preview_image_path
53
  except Exception as e:
54
+ raise gr.Error(f"Önizleme oluşturulurken bir hata oluştu: {str(e)}")
55
 
56
+ def crop_pdf(original_pdf_path: str, preview_dims: tuple, crop_box_coords: list) -> typing.Optional[str]:
57
  """
58
  Kullanıcının seçtiği alana göre PDF'in tüm sayfalarını kırpar ve
59
  sonucu yeni bir PDF dosyası olarak döndürür.
60
  """
61
+ if not original_pdf_path:
62
+ raise gr.Error("Lütfen önce bir PDF dosyası yükleyin.")
63
+ if not crop_box_coords:
64
+ raise gr.Error("Lütfen resim üzerinde bir kırpma alanı seçin.")
65
 
66
  try:
67
  doc = fitz.open(original_pdf_path)
 
 
 
 
68
  x1, y1, x2, y2 = crop_box_coords
69
+
 
70
  preview_width, preview_height = preview_dims
71
  pdf_page_rect = doc.load_page(0).rect
72
  pdf_width, pdf_height = pdf_page_rect.width, pdf_page_rect.height
73
 
 
74
  scale_x = pdf_width / preview_width
75
  scale_y = pdf_height / preview_height
76
 
77
+ crop_rect = fitz.Rect(x1 * scale_x, y1 * scale_y, x2 * scale_x, y2 * scale_y)
 
 
 
 
 
 
78
 
 
79
  for page in doc:
80
  page.set_cropbox(crop_rect)
81
 
 
82
  output_pdf_path = os.path.join(TEMP_DIR, "cropped_output.pdf")
83
  doc.save(output_pdf_path, garbage=4, deflate=True, clean=True)
84
  doc.close()
 
95
  **Bu araç, bir PDF'in tüm sayfalarını aynı anda, tek bir seçimle kırpmanızı sağlar.**
96
  1. **PDF Yükle:** Kırpmak istediğiniz PDF dosyasını yükleyin. İlk 10 sayfanın üst üste bindirilmiş bir önizlemesi oluşturulacaktır.
97
  2. **Alan Seç:** Fare ile sürükleyerek resim üzerinde kalmasını istediğiniz alanı seçin.
98
+ 3. **Kırp & İndir:** "PDF'i Kırp ve İndir" düğmesine tıklayın.
99
  """
100
  )
101
 
102
  # Arka planda veri tutmak için State'ler (durumlar)
103
  original_pdf_path_state = gr.State()
104
  preview_dims_state = gr.State()
105
+ crop_coords_state = gr.State() # Seçim koordinatlarını tutmak için yeni state
106
+
107
  with gr.Row():
108
  with gr.Column(scale=1):
109
  pdf_upload_input = gr.File(label="1. PDF Dosyasını Yükle", file_types=[".pdf"])
110
+ crop_button = gr.Button("✂️ PDF'i Kırp ve İndir", variant="primary")
111
  pdf_download_output = gr.File(label="Sonuç (İndirmeye Hazır)", interactive=False)
112
 
113
  with gr.Column(scale=3):
 
114
  image_preview_output = gr.Image(
115
  label="2. Kırpma Alanını Seçin",
116
+ tool="select", # Güncel Gradio sürümü ile bu parametre çalışacaktır
117
  interactive=True
118
  )
119
+
120
  # Event Listeners (Olay Zinciri)
121
 
122
+ # 1. PDF yüklendiğinde -> create_preview_image fonksiyonunu çalıştır
123
  pdf_upload_input.upload(
124
  fn=create_preview_image,
125
  inputs=[pdf_upload_input],
126
+ outputs=[original_pdf_path_state, preview_dims_state, image_preview_output],
127
+ # Önceki seçimleri ve sonuçları temizle
128
+ trigger_mode="once"
129
+ ).then(
130
+ lambda: (None, None),
131
+ outputs=[crop_coords_state, pdf_download_output]
132
+ )
133
+
134
+ # 2. Resim üzerinde bir alan seçildiğinde -> koordinatları crop_coords_state'e kaydet
135
+ def store_coords(evt: gr.SelectData):
136
+ return evt.index
137
+
138
+ image_preview_output.select(
139
+ fn=store_coords,
140
+ outputs=[crop_coords_state]
141
  )
142
 
143
+ # 3. Kırpma butonuna tıklandığında -> crop_pdf fonksiyonunu çalıştır
 
144
  crop_button.click(
145
  fn=crop_pdf,
146
+ inputs=[original_pdf_path_state, preview_dims_state, crop_coords_state],
147
  outputs=[pdf_download_output]
148
  )
149
 
150
+ app.launch()