Чому зображення, взяті з PDF-файлу, відрізняються від зображених на сторінці?
Зображення з прозорістю можна зберігати окремо як основне зображення та програмну маску. Далі за допомогою Pillow створіть RGBA PNG, вставте PDF-файл у пам’яті та перегляньте основне зображення та SMask. Вилучення байтів основного зображення не означає отримання повного ефекту прозорості, а також реконструкцію всіх екземплярів відображення на сторінці.
Зображення, які ви витягуєте з PDF-файлів, часто виглядають інакше, ніж ви бачите на сторінці: вони або зовсім чорні, неправильного розміру, або відсутні фони чи водяні знаки. Зазвичай проблема полягає не в самому коді, а в тому, що ви читаєте оригінальний об’єкт зображення всередині PDF-файлу та пропускаєте інструкції щодо композиції під час відтворення сторінки.
Ця стаття написана для розробників і обробників документів, яким потрібно використовувати сценарії для аналізу зображень PDF. Він підходить для таких сценаріїв, як попередня обробка OCR і реорганізація вмісту. Після прочитання ви зможете зрозуміти різницю між оригінальним об’єктом і відображенням сторінки, знати, чому SMask (м’яка маска) спричиняє втрату прозорих ділянок, а також освоїти набір методів самоперевірки за допомогою синтетичних зразків.
У цій статті використовуються синтетичні зразки для демонстрації методу обробки. Код було перевірено з прикладами в ізольованому середовищі, і це не є гарантією всіх реальних файлів або продуктивності продукту. Перед обробкою важливих документів збережіть оригінали та перегляньте їх відповідно до меж і пунктів прийняття в тексті.
Результати вилучення зображень PDF не відповідають сторінці? Висновок одним реченням
Витягнуті байти основного зображення не відповідають повному ефекту на сторінці. Одночасно потрібно обробляти SMask, а фактичний результат візуалізації пристрою для читання використовується як контрольний показник прийнятності.
| ваша ситуація | Рекомендовані практики | причина |
|---|---|---|
| Результатом вилучення є одноколірний прямокутник, а прозора область стає чорною або білою | Перевірте, чи smask_xref дорівнює 0, і об’єднайте SMask як альфа-канал із основним зображенням | Зображення з прозорістю можна зберігати окремо як основне зображення та програмну маску. Вилучення лише основного зображення призведе до втрати інформації про прозорість. |
| Витягується повне велике зображення, і на сторінці відображається лише його частина. | Зчитайте матрицю CTM і /BBox, обріжте відповідно до області відображення | Одну і ту саму базову карту можна повторно використовувати кількома сторінками, і на кожній сторінці відображається лише її частина. |
| Орієнтація зображення перевернута або деформована | Зчитайте параметри матриці для геометричної корекції та вручну перевірте текст і грані | Матриця перетворення може містити негативне масштабування або нерівномірні перетворення |
| Видобуток успішний, але сторінку не видно | Запитуйте статус OCG і порівняйте з CropBox | Зображення може бути приховано необов’язковою групою вмісту або за межами області кадрування |
| Зображення розмите або має низьку роздільну здатність | Зареєструйте метадані DPI та позначте їх як низьку якість, за потреби перескануйте вихідні файли | Оригінальне вбудоване зображення може бути мініатюрою з низькою роздільною здатністю |
Різниця між оригінальними об'єктами та конвеєрами візуалізації
PDF-файли структуровані як сховище ресурсів. `Document.extract_image(xref)` Цей метод дозволяє вивезти деталі зі складу такими, як вони є. Відображення на сторінці також має пройти кілька процесів: масштабування матриці трансформації (CTM), вирізання контуру відсікання (Clip Path), змішування групи прозорості (Transparency Group) і накладання м’якої маски (Soft Mask).
Найбільш типова відмінність походить від SMask. Багато PNG із каналом прозорості розділені на дві частини всередині PDF: потік зображення RGB та окремий потік сірої маски. Якщо ви витягнете лише основне зображення та відкинете пов’язаний об’єкт SMask, ви отримаєте прямокутник без прозорості, а початково прозора область стане чорною або білою.
Крім того, щоб заощадити обсяг, ту саму базову карту високої роздільної здатності можна повторно використовувати на кількох сторінках, і кожна сторінка відображає лише її частину через різні /BBox і матриці. Пряме вилучення призведе до повного великого зображення, а не обрізаних фрагментів, які бачить користувач. Це «те, що ви бачите, не те, що ви отримуєте» є невід'ємною характеристикою PDF як формату обміну і не є недоліком бібліотеки аналізу.
У наведеній нижче таблиці порівнюються дві точки зору:
📊 Основне порівняння
| Контрастні розміри | Витягніть оригінальний об'єкт безпосередньо | Результати візуалізації сторінки |
|---|---|---|
| Отримайте вміст | Оригінальні частини в сховищі ресурсів, наприклад основний потік зображень | Візуальні ефекти після обробки інструкціями синтезу |
| прозорість | Основне зображення та SMask можуть зберігатися окремо, і їх потрібно пов’язати вручну. | М’які маски накладаються, а прозорі області відображаються нормально. |
| Розмір і асортимент | Може мати повний розмір базової карти | Обмежується CTM, /BBox і відсічними контурами |
| Ситуація повторного використання | Одна і та сама базова карта може використовуватися кількома сторінками | Кожна сторінка представляє лише свою частину |
Синтетичне тестове середовище та обробка граничних випадків
Щоб перевірити логіку вилучення, не покладаючись на зовнішні файли, потрібно створити синтетичний PDF-файл, що містить SMask. Наступний код використовує PyMuPDF для створення тестового документа в пам’яті, в якому об’єкт зображення має незалежну м’яку маску, імітуючи ситуацію в реальній сцені, де «піктограма має прозорий фон, але базовий шар зберігається в окремому потоці».
from io import BytesIO
from PIL import Image
import pymupdf
im = Image.new("RGBA", (16, 16), (255, 0, 0, 128))
raw = BytesIO()
im.save(raw, format="PNG")
with pymupdf.open() as doc:
page = doc.new_page(width=100, height=100)
page.insert_image(pymupdf.Rect(10, 10, 70, 70), stream=raw.getvalue())
images = page.get_images(full=True)
assert len(images) == 1
xref, smask = images[0][:2]
assert xref > 0 and smask > 0
assert doc.extract_image(xref)["width"] == 16
assert doc.extract_image(smask)["image"]
Правильні вихідні очікування: програма повинна мати можливість розпізнати, що зображення пов’язано з SMask, і успішно витягти основні дані зображення.
Код повністю самодостатній і не потребує зовнішніх вхідних файлів. Він синтезує PDF-файл із SMask у пам’яті, а потім перевіряє, чи правильно розпізнає логіка вилучення маску. Код містить два ключових твердження: одне перевіряє цілісність витягнутих даних, а інше перевіряє обізнаність про пов’язаний стан SMask.
Цей код зосереджений на перевірці цілісності на рівні метаданих. У фактичному виробництві, якщо використовується smask_xref != 0, потрібно використовувати такі бібліотеки, як Pillow, щоб вставити результат doc.extract_image(smask_xref) на основне зображення як альфа-канал. Ці два твердження охоплюють два основні контракти «дані можуть бути витягнуті» та «асоціація маски видима» відповідно, що може запобігти помилковим успіхам, коли порожні документи або змінюється API.
Прийняття результатів вилучення та межі перевірки вручну
Автоматизоване вилучення не може повністю замінити візуальне підтвердження. У наведеній нижче таблиці наведено звичайні аномалії, стратегії поводження та ситуації, які слід залишити на розсуд людини.
| Спостерігайте за явищами | Можливі причини | Автоматизована обробка рішень | Умови запуску ручного перегляду |
|---|---|---|---|
| Зображення повністю чорне або повністю біле | SMask було видобуто як окреме зображення; не вдалося декодувати колірний простір | Перевірте асоціацію SMask; спробуйте резервний колірний простір | Вміст усе ще не розпізнається після повернення; задіяні плашкові кольори або кольори, пов’язані з пристроєм |
| Орієнтація зображення перевернута або розтягнута | Матриця CTM містить негативне масштабування або нерівномірне перетворення | Зчитування параметрів матриці для геометричної корекції | Текст або обличчя явно деформовані після виправлення; складний векторний відсічний контур |
| Кілька маленьких картинок об'єднані в одну велику картинку | Плитковий візерунок або смугасте зберігання | Вирізати або з’єднати відповідно до координат BBox | Розрив зварювання очевидний; за логікою це має бути самостійна семантична одиниця |
| Видобуток успішний, але сторінка не відображається | Hidden by OCG (додаткова група вмісту); за межами посівної площі | Фільтр статусу запиту OCG; порівняти CropBox | Складна логіка рівня, наприклад вкладений OCMD; динамічні поля форми |
| Дуже низька роздільна здатність або розмиті | Оригінальне вбудовування – це мініатюра низької чіткості | Зареєструвати метадані DPI, позначити як низьку якість | Основна графіка або текст не читаються через розмитість; вихідний документ необхідно повторно відсканувати. |
Слід зазначити, що «демонстрація коду» лише перевіряє підключення викликів API і потоків даних і не означає, що наскрізний ефект відповідає стандартам. У разі виявлення вкладеної логіки OCG, користувальницьких шейдерів або зашифрованих документів вихідні дані сценарію надаються лише для довідки та мають бути прийняті проти фактичного відтворення програмою для читання PDF.
🎯 Який спосіб вам підходить?
Якщо потрібно зберегти ефект прозорості
Спочатку перевірте, чи існує SMask, об’єднайте його в альфа-канал, а потім виконайте подальшу обробку.
Якщо вам потрібна лише частина зображення на сторінці
Прочитайте CTM і /BBox і обріжте відповідно до області відображення замість безпосереднього збереження основного зображення.
Якщо ваше зображення є відсканованим або вбудованим у низьку роздільну здатність
Спочатку запишіть метадані DPI та позначте якість. Якщо ключовий вміст незрозумілий, поверніться до вихідного файлу та повторіть сканування.
Якщо документ містить шари, шифрування або складне кадрування
Розглядайте вихід сценарію як попередній результат, і кінцевий ефект візуалізації в програмі читання PDF матиме перевагу.
❓ Часті запитання (FAQ)
1. Чому прозора область вилученого зображення стає чорною?
Загальною причиною є те, що інформація про прозорість зберігається в SMask, і лише основне зображення витягується без включення маски.
2. Розлучене зображення набагато більше, ніж те, що ви бачите на сторінці. що відбувається
Ту саму базову карту можна повторно використовувати на кількох сторінках. Кожна сторінка відображає лише частину через /BBox і матрицю. Пряме вилучення призведе до повної базової карти.
3. Код проходить. Чи означає це, що отримані результати можна використовувати безпосередньо?
не можна. Демонстрація коду лише перевіряє підключення викликів API і потоків даних, а для остаточного прийняття потрібно використовувати фактичні результати візуалізації зчитувача.
4. Розпакування пройшло успішно, але зображення не видно на сторінці. Що може бути причиною?
Зображення може бути приховано додатковою групою вмісту (OCG) або за межами області кадрування. Статус OCG можна запитати та порівняти з CropBox.
📝 Підсумок
Оригінальний об’єкт зображення у PDF та ефект відображення сторінки — це два рівні речей, і зв’язок між ними потрібно з’ясувати перед видобуванням. Обробляйте SMask, матрицю та інформацію про кадрування разом і використовуйте результати візуалізації для прийняття, щоб результати були надійними.
Спробуйте зараз: завантажте документ, щоб розпочати переклад, зберігаючи вихідний макет


