""" أداة تغيير فريم PDF + إضافة لوجو -------------------------------- بتاخد: ملف PDF + صورة الفريم الجديد + صورة اللوجو بتعمل: 1) تحلل الملف وتكتشف أي عنصر متكرر بنفس المكان في أغلب الصفحات (فريم قديم / علامة مائية / هيدر / فوتر) وتشيله. 2) تركب الفريم الجديد في كل صفحة. 3) تضيف اللوجو في صفحة الغلاف وآخر صفحة. 4) تحفظ PDF جديد مضغوط. الاكتشاف هنا "ذكي بالإحصاء" مش نموذج AI بيشوف كل صفحة بعينه، وده مقصود: لملف فيه مئات الصفحات وحجمه يوصل 100 ميجا، تحليل كل صفحة بالذكاء الاصطناعي (vision model) هياخد وقت طويل وتكلفة فعلية لكل صفحة. بدل كده الأداة بتقارن كل الصفحات ببعض: أي صورة أو سطر نص بيتكرر بنفس المكان في أغلب الصفحات (فريم/هيدر/فوتر) بيتشال تلقائي، وده بيشتغل صح مع الكتب والمذكرات لأن الفريم القديم بيكون نفسه في كل صفحة أصلاً. """ import os import tempfile import traceback import pymupdf as fitz # PyMuPDF (import name kept as `fitz` for API familiarity) import gradio as gr def _redact_repeated_images(doc, progress, base=0.05, span=0.35): n_pages = len(doc) xref_counts = {} for page in doc: for img in page.get_images(full=True): xref_counts[img[0]] = xref_counts.get(img[0], 0) + 1 threshold = max(3, int(n_pages * 0.3)) frame_xrefs = {x for x, c in xref_counts.items() if c >= threshold} for i, page in enumerate(doc): for xref in frame_xrefs: try: rects = page.get_image_rects(xref) except Exception: rects = [] for r in rects: page.add_redact_annot(r, fill=(1, 1, 1)) if page.first_annot or True: page.apply_redactions() progress(base + span * (i + 1) / n_pages, desc=f"بيشيل الفريم القديم: صفحة {i + 1}/{n_pages}") return frame_xrefs def _redact_repeated_header_footer_text(doc, progress, base=0.4, span=0.15): n_pages = len(doc) threshold = max(3, int(n_pages * 0.3)) text_counts = {} per_page_blocks = [] for page in doc: h = page.rect.height blocks = page.get_text("blocks") keep = [] for b in blocks: x0, y0, x1, y1, text = b[0], b[1], b[2], b[3], b[4] text = text.strip() if not text: continue in_header = y1 < h * 0.10 in_footer = y0 > h * 0.90 if in_header or in_footer: key = (text, in_header) text_counts[key] = text_counts.get(key, 0) + 1 keep.append((fitz.Rect(x0, y0, x1, y1), key)) per_page_blocks.append(keep) repeated_keys = {k for k, c in text_counts.items() if c >= threshold} for i, page in enumerate(doc): touched = False for rect, key in per_page_blocks[i]: if key in repeated_keys: page.add_redact_annot(rect, fill=(1, 1, 1)) touched = True if touched: page.apply_redactions() progress(base + span * (i + 1) / n_pages, desc=f"بيشيل الهيدر/الفوتر المتكرر: صفحة {i + 1}/{n_pages}") def _apply_new_frame(doc, frame_path, progress, base=0.55, span=0.35): n_pages = len(doc) for i, page in enumerate(doc): page.insert_image(page.rect, filename=frame_path, overlay=False) progress(base + span * (i + 1) / n_pages, desc=f"بيركب الفريم الجديد: صفحة {i + 1}/{n_pages}") def _apply_logo(doc, logo_path, progress, base=0.9, span=0.06): n_pages = len(doc) logo_size = min(110, doc[0].rect.width * 0.16) margin = 18 target_pages = {0, n_pages - 1} for pg_index in target_pages: page = doc[pg_index] pw = page.rect.width rect = fitz.Rect(pw - margin - logo_size, margin, pw - margin, margin + logo_size) page.insert_image(rect, filename=logo_path, overlay=True) progress(base + span, desc="بيضيف اللوجو...") def process_pdf(pdf_file, frame_file, logo_file, progress=gr.Progress()): if pdf_file is None or frame_file is None or logo_file is None: raise gr.Error("لازم ترفع الملف الثلاثة: PDF وصورة الفريم وصورة اللوجو") pdf_path = pdf_file if isinstance(pdf_file, str) else pdf_file.name frame_path = frame_file if isinstance(frame_file, str) else frame_file.name logo_path = logo_file if isinstance(logo_file, str) else logo_file.name try: progress(0, desc="بيفتح الملف وبيحلل الصفحات...") doc = fitz.open(pdf_path) n_pages = len(doc) if n_pages == 0: raise gr.Error("الملف فارغ") _redact_repeated_images(doc, progress) _redact_repeated_header_footer_text(doc, progress) _apply_new_frame(doc, frame_path, progress) _apply_logo(doc, logo_path, progress) base_name = os.path.splitext(os.path.basename(pdf_path))[0] out_path = os.path.join(tempfile.mkdtemp(), f"{base_name}_new.pdf") progress(0.98, desc="بيحفظ الملف النهائي...") doc.save(out_path, garbage=4, deflate=True, clean=True) doc.close() progress(1.0, desc="خلصت ✅") return out_path except gr.Error: raise except Exception as e: traceback.print_exc() raise gr.Error(f"حصل خطأ أثناء المعالجة: {e}") with gr.Blocks(title="أداة تغيير الفريم واللوجو") as demo: gr.Markdown( """ # 🖼️ أداة تغيير الفريم وإضافة اللوجو لملفات PDF ارفع ملف الـ PDF، وصورة الفريم الجديد، وصورة اللوجو — والأداة هتشيل أي فريم/علامة مائية/هيدر أو فوتر متكرر في الملف القديم، وتركب الفريم الجديد، وتحط اللوجو في الغلاف وآخر صفحة. **ملحوظة:** الملفات الكبيرة (لحد 100 ميجا وأكتر من 100 صفحة) بتاخد وقت أطول شوية، استحمل معايا 🙂 """ ) with gr.Row(): pdf_in = gr.File(label="ملف PDF", file_types=[".pdf"], type="filepath") frame_in = gr.File(label="صورة الفريم الجديد", file_types=["image"], type="filepath") logo_in = gr.File(label="صورة اللوجو", file_types=["image"], type="filepath") run_btn = gr.Button("ابدأ المعالجة", variant="primary") out_file = gr.File(label="الملف الناتج") run_btn.click(fn=process_pdf, inputs=[pdf_in, frame_in, logo_in], outputs=out_file) if __name__ == "__main__": demo.queue(max_size=10).launch(max_file_size="150mb")