Глубокие погружения

Как конвертировать страницы PDF в изображения: практическое руководство

koboshiCo-founder
·9 мин чтения
Как конвертировать страницы PDF в изображения: практическое руководство
Кратко

Страницы PDF не всегда подходят для нужного использования. Это руководство объясняет, когда конвертировать PDF в изображения, каковы компромиссы каждого подхода, нативные способы в ОС и примеры кода на пяти языках.

Фронтенд-разработчик получает 40-страничный PDF с гайдлайнами бренда и хочет перенести три конкретные страницы в Figma. Инженер поддержки хочет вставить диаграмму из даташита в тред Slack. Юристу нужно прикрепить к письму подписанную страницу договора, не отправляя весь файл.

PDF создан для документов с фиксированной вёрсткой. Веб, редакторы изображений и мессенджеры работают с пикселями. Конвертация страницы PDF в изображение закрывает этот разрыв, но выбранный метод влияет на качество выходного файла, его размер и уровень контроля.

Почему PDF одновременно удобен и раздражает для этой задачи

PDF хранит страницы как поток команд рисования: поместить этот глиф, нарисовать этот вектор, отрендерить это изображение в таком-то размере. Это делает его независимым от разрешения и визуально стабильным. Но это также означает, что PDF — не изображение. Чтобы превратить его в растр, что-то должно отрендерить эти команды на растровый холст.

Плюсы:

  • Текст и векторы остаются чёткими при любом масштабе, потому что описаны математически, а не пикселями.
  • Один PDF может содержать сотни страниц в одном файле.
  • Шрифты, цветовые профили и аннотации перемещаются вместе с документом.

Минусы:

  • Разные PDF-ридеры рисуют по-разному. Одна и та же страница может выглядеть иначе в Adobe Acrobat, Preview, Chrome или headless-библиотеке.
  • Отсканированные PDF — это просто изображения, упакованные в PDF-контейнер, поэтому их «конвертация» означает перекодирование, которое может добавить артефакты или раздуть файл.
  • Сложные PDF с прозрачностью, слоями или интерактивными формами могут непредсказуемо схлопываться.
  • Размеры страниц различаются. Страница US Letter при 72 DPI — 612 на 792 пикселя. При 300 DPI — 2550 на 3300. Если не указать разрешение, результат может быть непригоден.

Во что на самом деле превращают PDF

Большинство задач конвертации сводится к одному из трёх форматов. У каждого своё назначение.

ФорматЛучше всего подходитКомпромисс
JPGФото, превью, вложения к письмам, веб-галереиС потерями, но маленький размер
PNGСкриншоты, диаграммы, всё, где нужна прозрачностьБез потерь, больше JPG для фото
WebPСовременный веб, приложения, где важна пропускная способностьМеньше JPG/PNG, немного менее универсален

А также практические параметры:

  • Одна страница или пакет. Одна страница — просто. Папка со счетами требует автоматизации.
  • DPI. 150 DPI достаточно для миниатюр. 300 DPI — стандарт для печати и OCR. 600 DPI — избыточно, если только вы не изучаете мелкие детали.
  • Цветовое пространство. RGB безопасно для экранов. Конвертация CMYK-PDF в RGB с наивным подходом может сдвинуть цвета.

Как выбрать подход

Правильный инструмент зависит от того, что вы оптимизируете.

Быстрая конвертация в браузере

Если нужна страница в виде JPG, PNG или WebP, и файл недостаточно чувствителен, чтобы требовать сервера, браузерный конвертер — самый быстрый путь. Наши инструменты PDF в JPG, PDF в PNG и PDF в WebP рендерят PDF локально. Файл не покидает ваше устройство — это важно для договоров, удостоверений и медицинских записей.

Пакетная работа в командной строке

Для папок с PDF или CI-конвейеров выигрывает командная утилита. Вы получаете воспроизводимый результат, контроль DPI и возможность скриптовать.

Конвертация внутри приложения

Когда конвертация — часть продукта, вызов библиотеки обычно чище, чем запуск CLI-утилиты. Это убирает внешнюю зависимость и даёт обработку ошибок в том же стиле, что и весь остальной код.

Конвертация на Windows

Adobe Acrobat

  1. Откройте PDF и перейдите к нужной странице.
  2. Выберите File > Export to > Image > JPEG/PNG/TIFF.
  3. Задайте выходное разрешение в диалоге экспорта.
  4. Сохраните.

Acrobat даёт стабильный результат, но он платный, а скриптование возможно только через платный SDK.

PDF-XChange Editor

Более лёгкая альтернатива с бесплатным тарифом. File > Export > Export Pages as Images позволяет выбрать формат, DPI и диапазон страниц.

PowerShell с pdftoppm

Установите Poppler для Windows, затем используйте pdftoppm из PowerShell:

pdftoppm -jpeg -r 300 input.pdf output

Это создаёт output-1.jpg, output-2.jpg и так далее — по одному файлу на страницу при 300 DPI.

Для PNG с прозрачным фоном:

pdftoppm -png -r 300 input.pdf output

Для одной страницы:

pdftoppm -jpeg -r 300 -f 1 -l 1 input.pdf output

Флаги -f и -l задают первую и последнюю страницы.

PowerShell с ImageMagick

ImageMagick может рендерить PDF, но на Windows обычно делегирует это Ghostscript:

magick -density 300 input.pdf[0] output.jpg

[0] означает первую страницу. Без него ImageMagick может попытаться создать многофреймовое изображение.

Конвертация на macOS

Preview

  1. Откройте PDF в Preview.
  2. Выберите нужную страницу в боковой панели миниатюр.
  3. Выберите File > Export, укажите формат и задайте разрешение.

Preview быстр и приватен, но обрабатывает одну страницу за раз.

Терминал с sips

macOS включает sips, но он плохо рендерит текст PDF. Используйте его только для PDF, которые уже являются растрами:

sips -s format jpeg input.pdf --out output.jpg

Для полноценного рендеринга PDF установите Poppler через Homebrew:

brew install poppler
pdftoppm -jpeg -r 300 input.pdf output

Быстрое действие Automator

Можно собрать сервис по правому клику в Automator, который запускает pdftoppm для любого выбранного PDF. Полезно, если вы регулярно конвертируете страницы и не хотите запоминать флаги.

Конвертация на Linux

Poppler обычно — лучший выбор на Linux.

sudo apt install poppler-utils

pdftoppm -jpeg -r 300 input.pdf output
pdftoppm -png -r 300 input.pdf output

Для выхода в WebP сначала конвертируйте в PNG, затем используйте cwebp:

pdftoppm -png -r 300 input.pdf temp
cwebp temp-1.png -o output.webp

Пакетная конвертация

Если у вас папка с PDF и нужно по одному изображению первой страницы для каждого:

for f in *.pdf; do
    pdftoppm -jpeg -r 300 -f 1 -l 1 "$f" "${f%.pdf}"
done

ImageMagick

ImageMagick работает на Linux, но для PDF часто медленнее, потому что растеризует через Ghostscript:

magick -density 300 input.pdf[0] -quality 90 output.jpg

-density нужно ставить до чтения PDF. Если поставить после, это не сработает.

Конвертация с помощью кода

TypeScript / Node.js

Используйте pdfjs-dist, чтобы рендерить страницы на canvas, затем экспортируйте в данные изображения.

import * as pdfjsLib from "pdfjs-dist"
import { createCanvas } from "canvas"
import fs from "fs"

async function pdfPageToPng(
  pdfPath: string,
  pageNumber: number,
  outputPath: string,
  scale: number = 2
) {
  const data = new Uint8Array(fs.readFileSync(pdfPath))
  const pdf = await pdfjsLib.getDocument({ data }).promise
  const page = await pdf.getPage(pageNumber)

  const viewport = page.getViewport({ scale })
  const canvas = createCanvas(viewport.width, viewport.height)
  const context = canvas.getContext("2d")

  await page.render({ canvasContext: context, viewport }).promise

  const buffer = canvas.toBuffer("image/png")
  fs.writeFileSync(outputPath, buffer)

  await pdf.destroy()
}

await pdfPageToPng("input.pdf", 1, "output.png", 2)

Значение scale примерно соответствует DPI: 2 при 72 DPI даёт выходное разрешение 144 DPI. Для 300 DPI используйте масштаб около 4.17.

В браузере наш конвертер PDF в PNG выполняет тот же шаг рендеринга на canvas, не отправляя файл никуда.

PHP

PHP может вызывать pdftoppm или использовать библиотеки вроде spatie/pdf-to-image, которая оборачивает ImageMagick:

<?php

use Spatie\PdfToImage\Pdf;

$pdf = new Pdf('input.pdf');
$pdf->setPage(1)
    ->setOutputFormat('png')
    ->saveImage('output.png');

Если не хотите добавлять зависимость, вызывайте Poppler напрямую:

<?php

function pdfPageToPng(string $input, int $page, string $output, int $dpi = 300): void {
    $cmd = sprintf(
        'pdftoppm -png -r %d -f %d -l %d %s %s',
        $dpi,
        $page,
        $page,
        escapeshellarg($input),
        escapeshellarg($output)
    );
    exec($cmd);
}

pdfPageToPng('input.pdf', 1, 'output', 300);

Это записывает output-1.png. Перед использованием в продакшене добавьте собственную проверку ошибок.

Go

В Go нет встроенного PDF-рендерера, но github.com/gen2brain/go-fitz оборачивает MuPDF:

package main

import (
	"image/jpeg"
	"os"

	"github.com/gen2brain/go-fitz"
)

func main() {
	doc, err := fitz.New("input.pdf")
	if err != nil {
		panic(err)
	}
	defer doc.Close()

	img, err := doc.Image(0)
	if err != nil {
		panic(err)
	}

	out, err := os.Create("output.jpg")
	if err != nil {
		panic(err)
	}
	defer out.Close()

	if err := jpeg.Encode(out, img, &jpeg.Options{Quality: 90}); err != nil {
		panic(err)
	}
}

go-fitz возвращает изображения в разрешении рендеринга PDF по умолчанию. Если нужен контроль DPI, смотрите документацию библиотеки.

Java

Apache PDFBox — стандартный выбор для работы с PDF на Java.

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class PdfToImage {
    public static void main(String[] args) throws IOException {
        try (PDDocument document = PDDocument.load(new File("input.pdf"))) {
            PDFRenderer renderer = new PDFRenderer(document);
            BufferedImage image = renderer.renderImageWithDPI(0, 300);
            ImageIO.write(image, "png", new File("output.png"));
        }
    }
}

Зависимость Maven:

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>3.0.2</version>
</dependency>

renderImageWithDPI принимает индекс страницы с нуля и значение DPI.

Python

Python упрощает задачу с помощью pymupdf или pdf2image.

С pymupdf:

import fitz

doc = fitz.open("input.pdf")
page = doc[0]

mat = fitz.Matrix(2, 2)
pix = page.get_pixmap(matrix=mat)
pix.save("output.png")

Matrix управляет масштабом. Для примерно 300 DPI из PDF с 72 DPI используйте fitz.Matrix(300/72, 300/72).

С pdf2image, которая оборачивает Poppler:

from pdf2image import convert_from_path

images = convert_from_path("input.pdf", dpi=300, first_page=1, last_page=1)
images[0].save("output.jpg", "JPEG", quality=90)

pdf2image удобна, но требует установленного в системе Poppler.

Типичные ловушки

  • Забыть про DPI. Рендеринг PDF по умолчанию часто 72 или 96 DPI. При таком разрешении текст выглядит размытым. Всегда указывайте выходное DPI, если важно качество.
  • Игнорировать цветовое пространство. CMYK-PDF, конвертированный в RGB без профиля, может выглядеть выцветшим или перенасыщенным.
  • Перекодирование отсканированных PDF. Если PDF уже является JPEG-сканом, конвертация в PNG не вернёт потерянные детали. Она только увеличит размер файла.
  • Подмена шрифтов. Headless-серверы иногда не содержат шрифтов, встроенных в PDF. Рендерер подставляет другие, и вёрстка ломается. Встраивание шрифтов при создании PDF предотвращает это.
  • Ошибка на единицу в нумерации страниц. API кода обычно используют индексацию страниц с нуля. Командные утилиты обычно — с единицы.

Что использовать в каком случае

  • Разовое личное использование: Preview на macOS, PDF-ридер на Windows или браузерный конвертер.
  • Пакетная обработка на сервере: pdftoppm или pdf2image.
  • Внутри продукта: Apache PDFBox для Java, pymupdf для Python, pdfjs-dist для TypeScript.
  • Чувствительные к приватности файлы: используйте браузерный инструмент, чтобы PDF не покидал устройство.

Если нужен самый быстрый путь без установки чего-либо, наши конвертеры PDF в JPG, PDF в PNG и PDF в WebP работают полностью в браузере.

Ещё посты в блоге