2025, Oct 05 21:31
PyMuPDF में PDF पेज को किसी भी सूक्ष्म कोण पर घुमाने का सटीक तरीका
Python और PyMuPDF से PDF पेज 2.5° जैसे सूक्ष्म कोण पर घुमाएँ—show_pdf_page के rotate से बिना रैस्टर; टेक्स्ट चयन-योग्य व वेक्टर सुरक्षित। सीमाएँ और कोड उदाहरण देखें.
किसी भी मनचाहे कोण पर PDF पृष्ठ को घुमाने की ज़रूरत आश्चर्यजनक रूप से आम है, लेकिन PyMuPDF का सीधा-सा दिखने वाला API शुरू में रास्ता रोक देता है। सामान्य पेज-रोटेशन टॉगल केवल 90 डिग्री के गुणकों को ही सहारा देते हैं और बस व्यूअर की उन्मुखता बदलते हैं। अगर आपको 2.5 डिग्री जैसा सूक्ष्म घुमाव चाहिए और साथ ही चयन-योग्य टेक्स्ट, वेक्टर आकृतियाँ और छवियाँ सुरक्षित रखनी हैं, तो लाइब्रेरी के भीतर ही एक सुथरा तरीका मौजूद है—वह भी एक ही कॉल में।
जब सीधा तरीका काम न करे
स्वाभाविक तौर पर आप पेज पर सीधा एक ट्रांसफॉर्मेशन मैट्रिक्स आज़माते हैं। दस्तावेज़ खोलते हैं, पेज चुनते हैं, उसकी रोटेशन को शून्य पर सेट करते हैं, एक Matrix बनाते हैं, उसे prerotate करते हैं, और फिर उसे पेज के कंटेंट पर लागू करने की कोशिश करते हैं। अड़चन यह है कि पूरे पेज ऑब्जेक्ट पर इस तरह मैट्रिक्स लगाना उपलब्ध ही नहीं है।
import pymupdf as pm
pdf_obj = pm.open("Sample.pdf")  # इनपुट PDF खोलें
first_pg = pdf_obj[0]             # पहला पेज लें
first_pg.set_rotation(0)          # केवल 0/90/180/270, सिर्फ उन्मुखता (orientation) बदलता है
xform = pm.Matrix(1, 0, 0, 1, 0, 0)
xform.prerotate(2.5)              # लक्ष्य: 2.5 डिग्री
first_pg.add_transformation(xform)  # यह विधि पेज ऑब्जेक्ट के लिए मौजूद नहीं है
pdf_obj.save("Sample_rotated.pdf")
यह क्यों विफल होता है
PDF में पेज रोटेशन फ्लैग वास्तविक कंटेंट को नहीं घुमाता। यह केवल एक उन्मुखता मान सहेजता है जिसे व्यूअर मानते हैं, और यह 0, 90, 180 और 270 डिग्री तक सीमित है। पेज पर सीधे मनमाने कोण का ट्रांसफॉर्म ठेलने की कोशिश API सीमाओं से टकराती है, क्योंकि PyMuPDF में इसे पेज-स्तरीय ट्रांसफॉर्मेशन के रूप में प्रदर्शित ही नहीं किया गया है। अगर आपको 2.5 डिग्री जैसे सूक्ष्म कोण चाहिए, तो ऐसा तरीका अपनाना होगा जो टेक्स्ट और वेक्टर डेटा को अक्षुण्ण भी रखे।
PyMuPDF के साथ सरल और कारगर समाधान
PyMuPDF किसी पेज को ट्रांसफॉर्मेशन लगाकर दूसरे पेज पर रेंडर कर सकता है। मनचाहा रोटेशन संभव करने वाली विधि है show_pdf_page। यह स्रोत पेज को लक्ष्य पेज के आयत (rectangle) में लाती है और rotation पैरामीटर लागू करती है—और नतीजा यह कि टेक्स्ट चयन-योग्य रहता है और वेक्टर कंटेंट जस का तस।
import pymupdf  # fitz नहीं
# एक खाली रिसीवर पेज तैयार करें
sheet = pymupdf.open().new_page(width=595, height=841)
# input.pdf का पेज 0 रिसीवर में आयात करें, 2.5 डिग्री घुमाकर
sheet.show_pdf_page(
    pymupdf.Rect(0, 0, 595, 841),
    pymupdf.open("input.pdf"),
    pno=0,
    rotate=2.5,
    keep_proportion=True
)
# नया दस्तावेज़ सहेजें
sheet.parent.save("output.pdf")
यह तरीका वेक्टर बनाए रखता है, स्कैन की गई छवियों के साथ भी काम करता है और टेक्स्ट को चयन-योग्य रहने देता है। ट्रांसफॉर्मेशन आयात के समय ही होता है, इसलिए कंटेंट रैस्टराइज़ होने से बचता है।
क्या उम्मीद करें, और सीमाएँ कहाँ हैं
यह तरीका पेज के मूल कंटेंट पर केंद्रित है। नतीजतन कुछ सहायक वस्तुएँ साथ में नहीं आ सकतीं। आउटपुट दोबारा जेनरेट होने के कारण मेटाडेटा पूरा स्थानांतरित न हो पाए। एनोटेशन, बुकमार्क और लिंक गायब हो सकते हैं, वैसे ही जैसे वे लाइब्रेरी में होता है जो पेज कंटेंट फिर से बनाती हैं; बदले हुए आयात के बाद मूल निर्देशांक मान्य नहीं रह सकते। सूक्ष्म रोटेशन स्रोत पेज की पहले से लगी रोटेशन को नजरअंदाज़ भी कर सकता है, इसलिए लैंडस्केप स्रोतों या मिश्रित रोटेशन वाले दस्तावेज़ों के लिए आयात के समय उन्मुखता समायोजित करनी पड़ सकती है। एक बोनस साइड-इफेक्ट भी है: यह तकनीक एंबेडेड जावास्क्रिप्ट हटा सकती है, जो सुरक्षा की दृष्टि से उपयोगी हो सकता है, हालांकि यह कुछ फाइलों पर प्रमाणित है, सभी पर नहीं। API परिदृश्य में morph जैसे अन्य फंक्शन भी मौजूद हैं जो संबंधित ट्रांसफॉर्मेशन देते हैं, लेकिन वे आमतौर पर विशिष्ट कंटेंट प्रकारों को लक्ष्य करते हैं। show_pdf_page वाली राह बिना प्रत्येक ऑब्जेक्ट से निपटे संपूर्ण पेज के लिए संतुलित समाधान देती है।
साफ-सुथरा डि-रोटेशन और सैनेटाइज़िंग
यही तरीका रोटेशन को वापस शून्य पर ला सकता है और केवल मूल पेज कंटेंट को दोबारा आयात करके दस्तावेज़ को सैनेटाइज़ कर सकता है। इससे PDF सामान्यीकृत करने, अनचाही अतिरिक्त चीज़ें हटाने और साथ ही संपीड़न में मदद मिलती है।
import pymupdf  # fitz नहीं
out_pdf = pymupdf.open()            # रिसीवर डॉक्यूमेंट
in_pdf = pymupdf.open("input.pdf")  # स्रोत डॉक्यूमेंट
for idx in range(len(in_pdf)):      # स्रोत पेजों पर लूप
    canvas = out_pdf.new_page()     # डिफ़ॉल्ट रूप से A4 सीधा
    # पेज के कोर को 0.0-डिग्री रोटेशन के साथ आयात करें (डि-रोटेशन जैसा कार्य)
    canvas.show_pdf_page(canvas.rect, in_pdf, idx, rotate=0.0)
# वैकल्पिक: कचरा साफ करें और कोर स्ट्रीम को संपीड़ित करें
out_pdf.save("output.pdf", garbage=3, deflate=True)
यह जानना क्यों मायने रखता है
रैस्टराइज़ किए बिना भिन्नांश डिग्री पर घुमा पाना मतलब आप अपनी PDF की गुणवत्ता और पहुंचयोग्यता बनाए रखते हैं। चयन-योग्य टेक्स्ट वैसा ही रहता है, वेक्टर वेक्टर ही रहते हैं, और फ़ाइल आकार हल्के बने रहते हैं। साथ ही, पेजों को दोबारा आयात करना दस्तावेज़ को सामान्य करने का व्यावहारिक तरीका देता है—एंबेडेड स्क्रिप्ट हट सकती हैं, नाज़ुक अतिरिक्त चीज़ें छूट जाती हैं, और पहले किए गए संपादनों से आई विचित्रताओं से किनारा किया जा सकता है।
समापन
90 के गुणकों पर पेज घुमाना केवल एक उन्मुखता फ्लैग है; इससे सटीक झुकाव नहीं मिलता। जब आपको 2.5 डिग्री जैसा हल्का कोण या कोई भी सूक्ष्म रोटेशन चाहिए और साथ में PDF की संरचना भी सुरक्षित रखनी हो, तो show_pdf_page के rotate पैरामीटर के साथ पेज को नए पेज में आयात करें। ध्यान रखें, आप मूलतः पेज के कोर को फिर से बना रहे हैं—कुछ मेटाडेटा और इंटरैक्टिव तत्व पीछे छूट सकते हैं। यदि यह समझौता आपके उपयोग-परिदृश्य में ठीक बैठता है, तो Python और PyMuPDF में ही आपको एक कॉम्पैक्ट, सटीक और स्क्रिप्टेबल समाधान मिल जाता है।