Серверна обробка зображень через ImageMagick
ImageMagick — стандарт де-факто для серверної обробки зображень. Підтримує 200+ форматів, складні трансформації та працює через CLI або бібліотеки (Wand для Python, Imagick для PHP, imagemagick для Node.js). Використовується там, де Sharp не справляється: PDF-конвертація, PSD, складні кольорові профілі, векторна растеризація.
Установка
# Ubuntu/Debian
apt install imagemagick libmagickwand-dev
# Alpine (Docker)
apk add imagemagick
# macOS
brew install imagemagick
# Перевірити підтримувані формати
convert -list format | grep -E 'WEBP|AVIF|PDF'
Python: Wand (біндинг до MagickWand)
pip install Wand
from wand.image import Image
from wand.color import Color
import io
def process_image(input_path: str, output_dir: str, filename: str):
with Image(filename=input_path) as img:
# Auto-orient по EXIF
img.auto_orient()
# Нормалізувати в RGB (PDF/CMYK → sRGB)
if img.colorspace == 'cmyk':
img.transform_colorspace('srgb')
# Убрати прозорість перед JPEG
if img.alpha_channel and filename.endswith('.jpg'):
img.background_color = Color('white')
img.alpha_channel = 'remove'
# Генерація варіантів
sizes = {
'thumb': (150, 150, 'cover'),
'medium': (800, 600, 'inside'),
'large': (1920, 1080, 'inside'),
}
results = {}
for name, (w, h, fit) in sizes.items():
with img.clone() as variant:
if fit == 'cover':
# Resize + crop по центру
variant.transform(resize=f'{w}x{h}^')
variant.gravity = 'center'
variant.extent(w, h)
else:
variant.transform(resize=f'{w}x{h}>')
variant.strip() # видалити метаданні
variant.compression_quality = 85
out_path = f"{output_dir}/{name}.webp"
variant.format = 'webp'
variant.save(filename=out_path)
results[name] = out_path
return results
PHP: Imagick
<?php
class ImageProcessor
{
public function process(string $inputPath, string $outputDir): array
{
$imagick = new Imagick($inputPath);
// Auto-orient та нормалізація
$imagick->autoOrient();
// Для багатосторінкових файлів (PDF, GIF) — взяти перший кадр
$imagick = $imagick->coalesceImages()->current();
// CMYK → sRGB
if ($imagick->getColorspace() === Imagick::COLORSPACE_CMYK) {
$imagick->transformImageColorspace(Imagick::COLORSPACE_SRGB);
}
$sizes = [
'thumb' => [150, 150, Imagick::GRAVITY_CENTER],
'medium' => [800, 600, null],
'large' => [1920, 1080, null],
];
$results = [];
foreach ($sizes as $name => [$w, $h, $gravity]) {
$variant = clone $imagick;
if ($gravity) {
// Thumbnail з обрізкою по центру
$variant->cropThumbnailImage($w, $h);
} else {
$variant->thumbnailImage($w, $h, true); // fit inside
}
$variant->stripImage(); // видалити EXIF
$variant->setImageFormat('webp');
$variant->setImageCompressionQuality(82);
$outPath = "{$outputDir}/{$name}.webp";
$variant->writeImage($outPath);
$results[$name] = $outPath;
$variant->destroy();
}
$imagick->destroy();
return $results;
}
}
PDF та PSD конвертація
Унікальна можливість ImageMagick — конвертація PDF сторінок в зображення:
from wand.image import Image
def pdf_to_images(pdf_path: str, output_dir: str, dpi: int = 150):
"""Конвертувати PDF в JPG превью сторінок"""
with Image(filename=pdf_path, resolution=dpi) as pdf:
images = pdf.sequence
for i, page in enumerate(images):
with Image(page) as img:
img.format = 'jpeg'
img.compression_quality = 85
# Білий фон (PDF може бути прозорим)
img.background_color = Color('white')
img.alpha_channel = 'flatten'
img.save(filename=f"{output_dir}/page_{i+1:04d}.jpg")
return len(images)
# PSD → PNG шарів
with Image(filename='design.psd') as psd:
for i, layer in enumerate(psd.sequence):
with Image(layer) as l:
l.format = 'png'
l.save(filename=f"layer_{i}.png")
Конфігурація політики безпеки
ImageMagick має жорсткі ліміти за замовчуванням у /etc/ImageMagick-6/policy.xml. PDF-конвертація часто заблокована:
<!-- /etc/ImageMagick-6/policy.xml -->
<policymap>
<!-- Обмеження ресурсів -->
<policy domain="resource" name="memory" value="512MiB"/>
<policy domain="resource" name="map" value="1GiB"/>
<policy domain="resource" name="width" value="16KP"/>
<policy domain="resource" name="height" value="16KP"/>
<policy domain="resource" name="area" value="128MP"/>
<policy domain="resource" name="disk" value="2GiB"/>
<policy domain="resource" name="time" value="120"/>
<!-- Дозволити PDF (заблокован за замовчуванням для безпеки) -->
<policy domain="coder" rights="read|write" pattern="PDF"/>
<policy domain="coder" rights="read|write" pattern="LABEL"/>
<!-- Запретити небезпечні формати -->
<policy domain="coder" rights="none" pattern="MVG"/>
<policy domain="coder" rights="none" pattern="MSL"/>
<policy domain="delegate" rights="none" pattern="URL"/>
</policymap>
CLI: пакетна обробка
# Конвертація директорії в WebP
for f in /uploads/raw/*.jpg; do
convert "$f" \
-auto-orient \
-strip \
-resize '1920x1080>' \
-quality 82 \
"${f%.jpg}.webp"
done
# Паралельна обробка через GNU Parallel
find /uploads/raw -name '*.jpg' | \
parallel -j4 convert {} \
-auto-orient -strip \
-resize '800x600>' \
-quality 82 \
{.}.webp
# Додати watermark
convert input.jpg \
\( watermark.png -resize 200x -alpha on -evaluate multiply 0.7 \) \
-gravity SouthEast -composite \
output.jpg
Коли вибирати ImageMagick замість Sharp
| Завдання | Sharp | ImageMagick |
|---|---|---|
| JPEG/WebP/AVIF обробка | Краще (3–5× швидше) | Так |
| PDF → зображення | Ні | Так |
| PSD шари | Ні | Так |
| CMYK → RGB | Ні | Так |
| 200+ форматів | Ні | Так |
| SVG растеризація | Частково | Так |
| Споживання пам'яті | Низькі | Високе |
Термін виконання
Настройка серверної обробки через ImageMagick/Wand з підтримкою PDF та нестандартних форматів — 1–2 робочі дні.







