Видобування зображень
PDF Oxide видобуває зображення зі сторінок PDF, розбираючи потік вмісту, розв’язуючи посилання на XObject через оператори Do, рекурсивно обходячи вкладені Form XObject та декодуючи вбудовані зображення. Використовуйте extract_images(), щоб отримати об’єкти зображень у пам’яті, або extract_images_to_files(), щоб зберегти їх безпосередньо на диск як файли PNG чи JPEG.
Починаючи з v0.3.5, видобування зображень обробляє повний потік вмісту сторінки, а не лише сканує словник XObject. Це коректно обробляє зображення, розміщені через оператори Do, вкладені Form XObject із виявленням циклів та вбудовані зображення, закодовані послідовностями BI/ID/EI.
Підтримка колірних просторів
Видобуті зображення декодуються та повертаються в їхньому оригінальному колірному просторі — без втрат на перекодуванні:
- DeviceRGB / DeviceGray / DeviceCMYK — повертаються як є.
- Indexed (1, 2, 4, 8 біт на компонент) — палітра розв’язується через
resolve_indexed_paletteта розгортається черезexpand_indexed_to_rgb. Підтримує палітри Indexed на основі базових колірних просторів RGB, Grayscale та CMYK. Раніше видавали помилкиInvalid RGB image dimensionsна багатьох реальних PDF. - CalRGB / CalGray / ICCBased — конвертуються в RGB під час декодування.
Розгортання палітри захищене від зловмисних вхідних даних за допомогою захисту від переповнення checked_mul та обмеження на виділення 256 МіБ; обрізані потоки відхиляються коректно замість генерування сміттєвих пікселів.
Толерантність до пошкоджених зображень
Зображення з відсутніми записами /ColorSpace, нульовими розмірами або недійсними потоками пропускаються з попередженням — вони більше не аварійно завершують відмальовування сторінки. Така сама толерантність застосовується до пошкоджених зображень, вкладених у Form XObject.
Швидкий приклад
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
images = doc.extract_image_bytes(0)
for img in images:
print(f"{img['width']}x{img['height']}")
Node.js
const { PdfDocument } = require("pdf-oxide");
const doc = new PdfDocument("report.pdf");
const images = doc.getEmbeddedImages(0);
for (const img of images) {
console.log(`${img.width}x${img.height}`);
}
Go
import pdfoxide "github.com/yfedoseev/pdf_oxide/go"
doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
images, _ := doc.Images(0)
for _, img := range images {
fmt.Printf("%dx%d\n", img.Width, img.Height)
}
C#
using PdfOxide.Core;
using var doc = PdfDocument.Open("report.pdf");
var images = doc.ExtractImages(0);
foreach (var img in images)
{
Console.WriteLine($"{img.Width}x{img.Height}");
}
WASM
const doc = new WasmPdfDocument(bytes);
const images = doc.extractImages(0);
for (const img of images) {
console.log(`${img.width}x${img.height}`);
}
Rust
use pdf_oxide::PdfDocument;
let mut doc = PdfDocument::open("report.pdf")?;
let images = doc.extract_images(0)?;
for img in &images {
println!("{}x{} {:?}", img.width(), img.height(), img.color_space());
}
Довідник API
extract_images(page_index) -> Vec<PdfImage>
Видобути всі зображення зі сторінки. Розбирає потік вмісту сторінки, щоб знайти:
- Зображення XObject, на які посилаються через оператори
Do - Form XObject, що містять вкладені зображення (рекурсивно, з виявленням циклів)
- Вбудовані зображення, закодовані послідовностями
BI/ID/EI
Відстеження CTM (Current Transformation Matrix) надає обмежувальні рамки для кожного зображення.
| Параметр | Тип | Опис |
|---|---|---|
page_index |
int / usize |
Індекс сторінки з нуля |
Повертає: вектор об’єктів PdfImage.
Поля та методи PdfImage
| Метод / Поле | Тип | Опис |
|---|---|---|
width() |
u32 |
Ширина зображення у пікселях |
height() |
u32 |
Висота зображення у пікселях |
color_space() |
&ColorSpace |
Колірний простір (DeviceRGB, DeviceGray, DeviceCMYK тощо) |
bits_per_component() |
u8 |
Біт на колірний компонент (зазвичай 8) |
data() |
&ImageData |
Сирі дані зображення (байти JPEG або сирі пікселі) |
bbox() |
Option<&Rect> |
Обмежувальна рамка в користувацькому просторі PDF (якщо CTM відстежувалася) |
save_as_png(path) |
Result<()> |
Зберегти зображення як файл PNG |
save_as_jpeg(path) |
Result<()> |
Зберегти зображення як файл JPEG |
to_png_bytes() |
Result<Vec<u8>> |
Закодувати як байти PNG у пам’яті |
to_jpeg_bytes() |
Result<Vec<u8>> |
Закодувати як байти JPEG у пам’яті |
Варіанти ColorSpace
| Варіант | Опис |
|---|---|
DeviceRGB |
3-канальний RGB |
DeviceGray |
Одноканальні відтінки сірого |
DeviceCMYK |
4-канальний CMYK |
Indexed |
Колір на основі палітри |
ICCBased |
Колір на основі профілю ICC |
CalGray |
Каліброване сіре |
CalRGB |
Каліброване RGB |
Lab |
Колір CIE Lab* |
Варіанти ImageData
| Варіант | Опис |
|---|---|
Jpeg(Vec<u8>) |
Стиснуті дані JPEG (DCT pass-through) |
Raw { pixels, format } |
Декодовані піксельні дані з PixelFormat (RGB, Gray, CMYK, RGBA) |
Rust
let mut doc = PdfDocument::open("report.pdf")?;
let images = doc.extract_images(0)?;
for (i, image) in images.iter().enumerate() {
println!(
"Image {}: {}x{} {:?} {}bpc",
i, image.width(), image.height(),
image.color_space(), image.bits_per_component(),
);
if let Some(bbox) = image.bbox() {
println!(" Position: ({:.1}, {:.1})", bbox.x, bbox.y);
}
image.save_as_png(&format!("output/image_{}.png", i))?;
}
extract_images_to_files(page_index, output_dir, prefix, start_index) -> Vec<ExtractedImageRef>
Видобути зображення зі сторінки та зберегти їх безпосередньо у файли. Зображення JPEG зберігаються у їхньому оригінальному форматі (без втрат на перекодуванні); інші зображення зберігаються як PNG.
| Параметр | Тип | За замовчуванням | Опис |
|---|---|---|---|
page_index |
usize |
– | Індекс сторінки з нуля |
output_dir |
impl AsRef<Path> |
– | Каталог для збереження зображень (створюється за відсутності) |
prefix |
Option<&str> |
"img" |
Префікс імені файлу |
start_index |
Option<usize> |
1 |
Початковий індекс для імен файлів |
Повертає: вектор ExtractedImageRef, що описує збережені файли.
Поля ExtractedImageRef
| Поле | Тип | Опис |
|---|---|---|
filename |
String |
Збережене ім’я файлу (наприклад, "img_001.png") |
format |
ImageFormat |
Png або Jpeg |
width |
u32 |
Ширина зображення у пікселях |
height |
u32 |
Висота зображення у пікселях |
Rust
let mut doc = PdfDocument::open("report.pdf")?;
let refs = doc.extract_images_to_files(0, "output/images", Some("fig"), Some(1))?;
for img_ref in &refs {
println!("Saved: {} ({}x{}, {:?})", img_ref.filename, img_ref.width, img_ref.height, img_ref.format);
}
Розширені приклади
Видобування всіх зображень з усіх сторінок
use pdf_oxide::PdfDocument;
use std::path::Path;
let mut doc = PdfDocument::open("book.pdf")?;
let page_count = doc.page_count()?;
let mut total = 0;
for page in 0..page_count {
let refs = doc.extract_images_to_files(
page,
"output/images",
Some(&format!("page{}", page + 1)),
Some(1),
)?;
total += refs.len();
println!("Page {}: {} images", page + 1, refs.len());
}
println!("Total: {} images extracted", total);
Отримання байтів зображення в пам’яті (без дискового вводу-виводу)
let mut doc = PdfDocument::open("report.pdf")?;
let images = doc.extract_images(0)?;
for image in &images {
let png_bytes = image.to_png_bytes()?;
println!("PNG size: {} bytes", png_bytes.len());
// Use png_bytes with an HTTP response, database, etc.
}
Фільтрування зображень за розміром
let mut doc = PdfDocument::open("report.pdf")?;
let images = doc.extract_images(0)?;
// Only keep images larger than 100x100 pixels
let large_images: Vec<_> = images.iter()
.filter(|img| img.width() > 100 && img.height() > 100)
.collect();
println!("{} large images on page 1", large_images.len());
for img in &large_images {
println!(" {}x{} {:?}", img.width(), img.height(), img.color_space());
}
Розрізнення JPEG pass-through та перекодованих зображень
use pdf_oxide::extractors::ImageData;
let mut doc = PdfDocument::open("report.pdf")?;
let images = doc.extract_images(0)?;
for (i, image) in images.iter().enumerate() {
match image.data() {
ImageData::Jpeg(bytes) => {
// Original JPEG data -- save directly for zero quality loss
std::fs::write(format!("image_{}.jpg", i), bytes)?;
println!("Image {}: JPEG pass-through ({} bytes)", i, bytes.len());
}
ImageData::Raw { pixels, format } => {
// Raw pixels -- must encode to a file format
image.save_as_png(&format!("image_{}.png", i))?;
println!("Image {}: raw {:?} ({}x{})", i, format, image.width(), image.height());
}
}
}
Пов’язані сторінки
- Видобування тексту – видобування тексту разом із зображеннями
- Конвертація в HTML – вбудовування видобутих зображень у вивід HTML
- Конвертація в Markdown – включення зображень у вивід Markdown