Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 365 · После файлов, массивов и изображения

Imagick: пиксели этикетки, плотность и номинальный размер

Сохранить читаемую этикетку с плотностью, проверить PNG pHYs и перечитывание, перевести единицы без пересчёта растра.

Сохранить этикетку с проверяемым номинальным размером

Нужна отдельная PNG-этикетка с артикулом, которую можно передать в программу печати с понятным номинальным размером 40×32 мм. Сохраним нашу читаемую этикетку 400×320 пикселей при 254 пикселях на дюйм, затем заново откроем файл и проверим размеры по его метаданным. Рисунок и надпись останутся прежними: меняем указание физического масштаба, а не качество изображения.

Собственная этикетка 400×320 RGB, без начальной плотности PNG
Собственная этикетка 400×320 RGB, без начальной плотности PNG
Первый код: самостоятельный label-254.png, точные пиксели и проверенный номинал 40×32 мм
Первый код: самостоятельный label-254.png, точные пиксели и проверенный номинал 40×32 мм
Понятие до схемыКонкретный смысл
Пиксельный размерW=400, H=320 — число столбцов и строк. Эти числа не меняются от трёх методов урока. Напечатанная строка 400×320 на растре описывает именно их.
Плотность / PPI / PPCMdx/dy — сколько пикселей приходится на единицу длины по двум осям. PPI — пиксели на дюйм, PPCM — на сантиметр. DPI обычно означает точки принтера на дюйм; здесь измеряем плотность пикселей, а не точки реального принтера. Один дюйм равен 25.4 мм и 2.54 см.
Номинальные миллиметрыПри PPI: ширина=W/dx×25.4, высота=H/dy×25.4. При PPCM: W/dx×10 и H/dy×10. При 254 PPI получаем 40×32 мм; при 127 PPI — 80×64 мм. Это расчёт, не измерение отпечатка.
PNG pHYsЧасть PNG-файла с двумя целыми плотностями и признаком единицы. Здесь 10000 на метр означает 100 на сантиметр. Reader Imagick возвращает PPCM, поэтому 254 PPI после файла стали 100 PPCM.
RGB и одинаковый растрКрасная, зелёная и синяя компоненты: наш PNG хранит по 8 бит на компоненту, color-type 2. Все сравнительные панели имеют одинаковые исходные RGB-пиксели; подписи и схемы показывают изменение метаданных.
ВозвратДва метода установки возвращают bool-статус и меняют текущий объект. getImageResolution возвращает массив x/y. Ни один сам не записывает файл и не проверяет реальный принтер.
400×320, плотность по осям, единица и целое pHYs образуют одну цепочку расчёта
400×320, плотность по осям, единица и целое pHYs образуют одну цепочку расчёта

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$ok = $image->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER);

PPI означает пиксели на дюйм, PPCM — пиксели на сантиметр. DPI относится к точкам принтера; такую физическую печать мы не измеряли. Так выбирают пиксели на сантиметр. Если перед этим было число 100 с единицей дюйм, число останется 100, а физический смысл изменится. Для сохранения смысла PPI→PPCM нужно разделить обе плотности на 2.54 и отдельно передать их в setImageResolution. Одного вызова units недостаточно.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$image->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
$ok = $image->setImageResolution(254.0, 254.0);

Оба аргумента обязательны. Если растр 400×320, номинальная ширина равна 400/254 дюйма, то есть 400/254×25.4=40 мм; высота 320/254×25.4=32 мм. Деление / и умножение * выполняют именно этот расчёт. Пиксели 400×320 при этом сохранены.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$density = $image->getImageResolution();
$x = $density['x'];
$y = $density['y'];
$units = $image->getImageUnits();

= присваивает результат. Массив — пара значений с именами: ['x'] читает горизонтальную, ['y'] вертикальную плотность. Это отдельно от getImageWidth()/getImageHeight(), которые дают число пикселей. getImageUnits возвращает код единицы. Если после PNG читаем x=100 и единицу сантиметр, ширина равна 400/100×10=40 мм; нельзя делить на 100 как будто это PPI.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Перед полной программой: <?php открывает PHP, declare(strict_types=1) включает строгие типы. require подключает helper в папке __DIR__; loadResolutionSource декодирует точный вход Base64 и проверяет SHA. clone отделяет рабочую этикетку от исходника. saveResolutionNative сохраняет именно этот объект с его плотностью; new Imagick(путь) заново читает файл. saveResolutionComparison создаёт отдельную картинку просмотра; её собственные метаданные не описывают плотности внутренних панелей.

В расчёте if/elseif выбирают коэффициент 25.4 либо 10 по единице. === сравнивает значение и тип, <= проверяет границу, || означает «или». Если плотность неположительная либо единица неизвестна, выбрасывается исключение вместо деления на ноль или выдуманных миллиметров. Печать %.2f округляет только вывод, не меняет файл.

Сохранить и перечитать этикетку с номинальным размером 40×32 мм

label-254.png — самостоятельная этикетка 400×320. Записали 254 пикселя на дюйм; PNG содержит pHYs 10000/10000 на метр. После перечитывания Imagick вернул 100/100 пикселей на сантиметр, то есть те же номинальные 40×32 мм. Обе панели сравнения имеют одинаковые исходные пиксели.

Сохранить и перечитать этикетку с номинальным размером 40×32 ммПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$label = clone $source;
if (!$label->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH)) { throw new RuntimeException('Units failed'); }
if (!$label->setImageResolution(254.0, 254.0)) { throw new RuntimeException('Density failed'); }
saveResolutionNative($label, 'label-254.png');
$loaded = new Imagick(__DIR__ . '/label-254.png');
$density = $loaded->getImageResolution();
$units = $loaded->getImageUnits();
if ($units === Imagick::RESOLUTION_PIXELSPERINCH) { $factor = 25.4; }
elseif ($units === Imagick::RESOLUTION_PIXELSPERCENTIMETER) { $factor = 10.0; }
else { throw new RuntimeException('Physical unit is unknown'); }
if ($density['x'] <= 0 || $density['y'] <= 0) { throw new RuntimeException('Positive density required'); }
$widthMm = $factor * $loaded->getImageWidth() / $density['x'];
$heightMm = $factor * $loaded->getImageHeight() / $density['y'];
saveResolutionComparison([$source, $loaded], 'resolution-first.png');
echo "resolution-first.png\nlabel-254.png\n";
printf("reload units=%d x=%.2f y=%.2f nominal-mm=%.2fx%.2f\n", $units, $density['x'], $density['y'], $widthMm, $heightMm);

label-254.png — самостоятельная этикетка 400×320. Записали 254 пикселя на дюйм; PNG содержит pHYs 10000/10000 на метр. После перечитывания Imagick вернул 100/100 пикселей на сантиметр, то есть те же номинальные 40×32 мм. Обе панели сравнения имеют одинаковые исходные пиксели. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-first.png
label-254.png
reload units=2 x=100.00 y=100.00 nominal-mm=40.00x32.00

Почему одинаковые картинки имеют разные указания масштаба

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

Различить число пикселей, плотность и единицу измерения

После исходника показаны 127 PPI, 254 PPI и 100 PPCM. Все четыре растра 400×320 попиксельно одинаковы; различаются настройки объектов. 254 PPI и 100 PPCM задают один физический смысл. Метаданные отдельных панелей не являются метаданными составного comparison PNG.

Различить число пикселей, плотность и единицу измеренияПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$a = clone $source; $a->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $a->setImageResolution(127.0, 127.0);
$b = clone $source; $b->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $b->setImageResolution(254.0, 254.0);
$c = clone $source; $c->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER); $c->setImageResolution(100.0, 100.0);
$density = $b->getImageResolution();
saveResolutionComparison([$source, $a, $b, $c], 'resolution-controls.png');
echo "resolution-controls.png\n";
printf("b-live units=%d x=%.2f y=%.2f\n", $b->getImageUnits(), $density['x'], $density['y']);

После исходника показаны 127 PPI, 254 PPI и 100 PPCM. Все четыре растра 400×320 попиксельно одинаковы; различаются настройки объектов. 254 PPI и 100 PPCM задают один физический смысл. Метаданные отдельных панелей не являются метаданными составного comparison PNG. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-controls.png
b-live units=1 x=254.00 y=254.00

Задать плотность по двум осям

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$image->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
$ok = $image->setImageResolution(254.0, 254.0);

Оба аргумента обязательны. Если растр 400×320, номинальная ширина равна 400/254 дюйма, то есть 400/254×25.4=40 мм; высота 320/254×25.4=32 мм. Деление / и умножение * выполняют именно этот расчёт. Пиксели 400×320 при этом сохранены.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

127 и 254 PPI: один растр, два номинальных размера
127 и 254 PPI: один растр, два номинальных размера

Получить две номинальные ширины без изменения растра

Два самостоятельных PNG содержат один рисунок 400×320, но плотности 127 и 254 пикселя на дюйм задают номинальные 80×64 и 40×32 мм. Удвоение плотности уменьшило физический размер вдвое; новые детали и новые пиксели не появились.

Получить две номинальные ширины без изменения растраПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$large = clone $source; $large->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$large->setImageResolution(127.0, 127.0)) { throw new RuntimeException('Density failed'); }
$small = clone $source; $small->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$small->setImageResolution(254.0, 254.0)) { throw new RuntimeException('Density failed'); }
saveResolutionNative($large, 'density-127.png');
saveResolutionNative($small, 'density-254.png');
saveResolutionComparison([$source, $large, $small], 'resolution-density.png');
echo "resolution-density.png\ndensity-127.png\ndensity-254.png\n";

Два самостоятельных PNG содержат один рисунок 400×320, но плотности 127 и 254 пикселя на дюйм задают номинальные 80×64 и 40×32 мм. Удвоение плотности уменьшило физический размер вдвое; новые детали и новые пиксели не появились. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-density.png
density-127.png
density-254.png

В обычной этикетке нужны одинаковые плотности по осям. Разные x/y полезны как контроль ошибок: пиксельный прямоугольник 400×320 ещё не означает те же физические пропорции. Если получатель учитывает pHYs, 254/127 PPI даёт 40×64 мм; исправление 254/254 возвращает номинал 40×32 мм. Рисунок на странице ниже намеренно не растягивается.

Неравные оси и допуск к рассчитанному размеру: схемы, а не пробная печать
Неравные оси и допуск к рассчитанному размеру: схемы, а не пробная печать

Обнаружить разные плотности по осям и задать одинаковые

В density-xy.png X=254 PPI, Y=127 PPI: номинально 40×64 мм. В density-square.png обе оси 254 PPI: 40×32 мм. Пиксельные изображения остаются одинаковыми; если программа печати учитывает неодинаковые оси, физические пропорции различаются. Это диагностический контрпример, не рекомендация растянуть этикетку.

Обнаружить разные плотности по осям и задать одинаковыеПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$unequal = clone $source; $unequal->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$unequal->setImageResolution(254.0, 127.0)) { throw new RuntimeException('Unequal density failed'); }
$square = clone $unequal;
if (!$square->setImageResolution(254.0, 254.0)) { throw new RuntimeException('Equal density failed'); }
saveResolutionNative($unequal, 'density-xy.png');
saveResolutionNative($square, 'density-square.png');
saveResolutionComparison([$source, $unequal, $square], 'resolution-xy.png');
echo "resolution-xy.png\ndensity-xy.png\ndensity-square.png\n";

В density-xy.png X=254 PPI, Y=127 PPI: номинально 40×64 мм. В density-square.png обе оси 254 PPI: 40×32 мм. Пиксельные изображения остаются одинаковыми; если программа печати учитывает неодинаковые оси, физические пропорции различаются. Это диагностический контрпример, не рекомендация растянуть этикетку. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-xy.png
density-xy.png
density-square.png

Проверить сохранённый файл, единицу и расчёт

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$density = $image->getImageResolution();
$x = $density['x'];
$y = $density['y'];
$units = $image->getImageUnits();

= присваивает результат. Массив — пара значений с именами: ['x'] читает горизонтальную, ['y'] вертикальную плотность. Это отдельно от getImageWidth()/getImageHeight(), которые дают число пикселей. getImageUnits возвращает код единицы. Если после PNG читаем x=100 и единицу сантиметр, ширина равна 400/100×10=40 мм; нельзя делить на 100 как будто это PPI.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Запись PNG, целое pHYs и значения getter после перечитывания
Запись PNG, целое pHYs и значения getter после перечитывания

Прочитать реальные плотности после записи PNG

Заданные 300 PPI превратились в целое pHYs 11811 на метр; перечитывание вернуло 118.11 PPCM. Поэтому одно только число из getImageResolution нельзя называть DPI без чтения единицы. Растр этикетки не изменён.

Прочитать реальные плотности после записи PNGПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$label = clone $source; $label->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $label->setImageResolution(300.0, 300.0);
saveResolutionNative($label, 'checked-label.png');
$loaded = new Imagick(__DIR__ . '/checked-label.png');
$density = $loaded->getImageResolution();
saveResolutionComparison([$source, $loaded], 'resolution-reload.png');
echo "resolution-reload.png\nchecked-label.png\n";
printf("reload units=%d x=%.2f y=%.2f\n", $loaded->getImageUnits(), $density['x'], $density['y']);

Заданные 300 PPI превратились в целое pHYs 11811 на метр; перечитывание вернуло 118.11 PPCM. Поэтому одно только число из getImageResolution нельзя называть DPI без чтения единицы. Растр этикетки не изменён. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-reload.png
checked-label.png
reload units=2 x=118.11 y=118.11

Во второй задаче проверяем две полученные этикетки против требования 40×32 мм. foreach перебирает массив «имя файла => PPI»; => связывает ключ и значение, $panels[] добавляет просмотр. abs берёт модуль разницы, && означает «оба условия верны», <=0.05 задаёт выбранный нами допуск в миллиметрах. Это проверка результата файла, а не утверждение, что любое разрешение 300 лучше подходит к задаче.

Проверить номинальные миллиметры полученного файла

Проверка заданного допуска ±0.05 мм принимает файл 254 PPI и отклоняет файл 300 PPI для требования 40×32 мм. Это проверка метаданных и расчёта, не результат пробной печати. Для неизвестной единицы или неположительной плотности программа прекращает расчёт.

Проверить номинальные миллиметры полученного файлаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$panels = [$source];
foreach (['accepted-label.png' => 254.0, 'wrong-size-label.png' => 300.0] as $filename => $ppi) {
    $label = clone $source; $label->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $label->setImageResolution($ppi, $ppi);
    saveResolutionNative($label, $filename);
    $loaded = new Imagick(__DIR__ . '/' . $filename);
    $density = $loaded->getImageResolution();
    $units = $loaded->getImageUnits();
    if ($units === Imagick::RESOLUTION_PIXELSPERINCH) { $factor = 25.4; }
    elseif ($units === Imagick::RESOLUTION_PIXELSPERCENTIMETER) { $factor = 10.0; }
    else { throw new RuntimeException('Physical unit is unknown'); }
    if ($density['x'] <= 0 || $density['y'] <= 0) { throw new RuntimeException('Positive density required'); }
    $widthMm = $factor * $loaded->getImageWidth() / $density['x'];
    $heightMm = $factor * $loaded->getImageHeight() / $density['y'];
    $matches = abs($widthMm - 40.0) <= 0.05 && abs($heightMm - 32.0) <= 0.05;
    printf("%s nominal-mm=%.2fx%.2f matches=%d\n", $filename, $widthMm, $heightMm, (int)$matches);
    $panels[] = $loaded;
}
saveResolutionComparison($panels, 'resolution-check.png');
echo "resolution-check.png\n";

Проверка заданного допуска ±0.05 мм принимает файл 254 PPI и отклоняет файл 300 PPI для требования 40×32 мм. Это проверка метаданных и расчёта, не результат пробной печати. Для неизвестной единицы или неположительной плотности программа прекращает расчёт. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
accepted-label.png nominal-mm=40.00x32.00 matches=1
wrong-size-label.png nominal-mm=33.87x27.09 matches=0
resolution-check.png

Выбрать единицу и при необходимости перевести числа

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$ok = $image->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER);

PPI означает пиксели на дюйм, PPCM — пиксели на сантиметр. DPI относится к точкам принтера; такую физическую печать мы не измеряли. Так выбирают пиксели на сантиметр. Если перед этим было число 100 с единицей дюйм, число останется 100, а физический смысл изменится. Для сохранения смысла PPI→PPCM нужно разделить обе плотности на 2.54 и отдельно передать их в setImageResolution. Одного вызова units недостаточно.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Смена единицы без перевода числа и отдельный явный перевод PPI→PPCM
Смена единицы без перевода числа и отдельный явный перевод PPI→PPCM

Увидеть, что смена единицы не переводит число плотности

В живых объектах осталось 100/100, но сначала это пиксели на дюйм, затем на сантиметр. Номинальная ширина стала около 101.60 мм против 40.00 мм. От setter единиц не требуется автоматическая конверсия; её выполняет программа отдельно, если нужно сохранить физический размер.

Увидеть, что смена единицы не переводит число плотностиПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$inch = clone $source; $inch->setImageResolution(100.0, 100.0);
if (!$inch->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH)) { throw new RuntimeException('Inch units failed'); }
$cm = clone $inch;
if (!$cm->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER)) { throw new RuntimeException('Centimeter units failed'); }
$inchDensity = $inch->getImageResolution(); $cmDensity = $cm->getImageResolution();
saveResolutionNative($inch, 'units-inch.png'); saveResolutionNative($cm, 'units-cm.png');
saveResolutionComparison([$source, $inch, $cm], 'units-choice.png');
echo "units-choice.png\nunits-inch.png\nunits-cm.png\n";
printf("live inch-x=%.2f cm-x=%.2f\n", $inchDensity['x'], $cmDensity['x']);

В живых объектах осталось 100/100, но сначала это пиксели на дюйм, затем на сантиметр. Номинальная ширина стала около 101.60 мм против 40.00 мм. От setter единиц не требуется автоматическая конверсия; её выполняет программа отдельно, если нужно сохранить физический размер. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
units-choice.png
units-inch.png
units-cm.png
live inch-x=100.00 cm-x=100.00

Чтобы сохранить номинальный размер при переходе к сантиметрам, сначала читаем обе плотности, делим каждую на 2.54, затем сохраняем единицу сантиметр и новые числа. Для 254 PPI это точно 100 PPCM; два файла дают одинаковое pHYs 10000 на метр. При других дробных числах формат может внести округление, поэтому снова перечитайте файл и проверяйте физический смысл с допуском.

Перевести PPI в PPCM с сохранением номинального размера

Переводим каждую плотность 254/2.54=100 и меняем единицу на сантиметр. Оба самостоятельных PNG имеют pHYs 10000/10000 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов.

Перевести PPI в PPCM с сохранением номинального размераПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$inch = clone $source; $inch->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $inch->setImageResolution(254.0, 254.0);
$density = $inch->getImageResolution();
$cm = clone $inch;
if (!$cm->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER)) { throw new RuntimeException('Units failed'); }
if (!$cm->setImageResolution($density['x'] / 2.54, $density['y'] / 2.54)) { throw new RuntimeException('Converted density failed'); }
$converted = $cm->getImageResolution();
saveResolutionNative($inch, 'equivalent-inch.png'); saveResolutionNative($cm, 'equivalent-cm.png');
saveResolutionComparison([$source, $inch, $cm], 'units-convert.png');
echo "units-convert.png\nequivalent-inch.png\nequivalent-cm.png\n";
printf("converted x=%.2f y=%.2f\n", $converted['x'], $converted['y']);

Переводим каждую плотность 254/2.54=100 и меняем единицу на сантиметр. Оба самостоятельных PNG имеют pHYs 10000/10000 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
units-convert.png
equivalent-inch.png
equivalent-cm.png
converted x=100.00 y=100.00

Не перепутать метаданные, пиксели и реальную печать

ПроблемаРешение и граница
Картинка выглядит прежнейПлотность — метаданные. Указание размера печати не дорисовывает деталей. Изменение числа пикселей требует отдельных операций изменения размера.
После PNG значение стало 100 вместо 254Прочитайте units:100 PPCM соответствует254 PPI. Сравнивайте физический размер, а не голые числа.
Вычисление даёт неверные миллиметрыДля X используйте width и density[x], для Y — height и density[y]. Известная единица и положительные плотности обязательны для нашего расчёта.
Смена units изменила смыслSetter не переводит числовые плотности. Если требуется сохранить смысл, программа переводит обе оси отдельно.
Изображение отправили с header image/jpgHTTP-заголовок не перекодирует байты. В этом уроке все результаты явно сохраняются как PNG; официальный HTTP-пример сохранён как исходный контекст.
Этикетка напечаталась иначеДрайвер мог масштабировать «по странице», игнорировать density или учитывать поля. Нужна настройка фактической печати и измерение тестового отпечатка; этот урок такую проверку не выполнял.

Нулевые плотности могут присутствовать у файла без физической шкалы. Нельзя просто заменить неизвестную единицу на дюйм и объявить исходный физический размер известным: это новое предположение. Внешние значения должны быть конечными, положительными и разумными для задачи; наши программы задают известные фиксированные числа, а в расчёте дополнительно отказываются от неизвестной единицы/неположительной плотности. Статус true не является проверкой качества текста, цвета и фактических миллиметров на бумаге.

Весь переносимый helper
<?php
declare(strict_types=1);
function loadResolutionSource(): Imagick {
    $encoded = file_get_contents(__DIR__ . '/source.png.b64');
    if ($encoded === false) { throw new RuntimeException('Cannot read source'); }
    $bytes = base64_decode($encoded, true);
    if ($bytes === false || hash('sha256', $bytes) !== '4cd2d0100e934db342f2812ee0e7c94d774a13dc5b35cc875a2d7c4fe4cfb975') { throw new RuntimeException('Unexpected source bytes'); }
    if (file_put_contents(__DIR__ . '/source.png', $bytes) === false) { throw new RuntimeException('Cannot restore source'); }
    return new Imagick(__DIR__ . '/source.png');
}
function saveResolutionNative(Imagick $image, string $filename): void {
    $saved = clone $image;
    $saved->setImageFormat('png'); $saved->setImageDepth(8); $saved->setOption('png:color-type', '2');
    if (!$saved->writeImage(__DIR__ . '/' . $filename)) { throw new RuntimeException('Cannot save ' . $filename); }
}
function saveResolutionComparison(array $panels, string $filename): void {
    $width = 0; $height = 0;
    foreach ($panels as $panel) { $width += $panel->getImageWidth(); $height = max($height, $panel->getImageHeight()); }
    $canvas = new Imagick(); $canvas->newImage($width, $height, 'white'); $x = 0;
    foreach ($panels as $panel) {
        $canvas->compositeImage($panel, Imagick::COMPOSITE_OVER, $x, intdiv($height - $panel->getImageHeight(), 2));
        $x += $panel->getImageWidth();
    }
    saveResolutionNative($canvas, $filename);
}
Задача из прочитанного обсужденияНаш ответ
SO 3907785Плотность загруженного растра и настройки чтения перепутаны. Наш ответ — явно задать единицу и плотность текущего PNG, сохранить, перечитать; без ненужного resampling и обещания уменьшить файл.
SO 26851679resampleImage может менять число пикселей, тогда как metadata density — другая задача. Все наши исходные 400×320 сохранены; уменьшение пиксельного размера требует другого урока.
SO 4076936Нужно читать/писать DPI для будущей печати. Getter даёт x/y, единица читается отдельно; одинаковое число в PPI и PPCM не означает одинаковый физический размер.
SO 70333765PNG-этикетке нужен заданный физический размер без изменения рисунка. Мы рассчитываем номинальные 40×32 мм и проверяем сохранённый PNG, но не подменяем этим настройку страницы PDF или драйвера печати.
SO 75716790Меньшее PPI не обязано уменьшать файл и не удаляет детали. Наша metadata-коррекция намеренно сохраняет все пиксели; для веб-оптимизации нужны размеры растра/кодирование и отдельные измерения.
SO 78455312Расчёт с жёстко заданным 300 игнорирует метаданные файла. Берём реальные x/y и units после чтения, проверяем номинальный размер с явным допуском.

Рассчитать собственный номинал и продолжить

Числа плотности → setImageResolution; единица → setImageUnits; сохранённые x/y → getImageResolution
Числа плотности → setImageResolution; единица → setImageUnits; сохранённые x/y → getImageResolution

Упражнение: для той же этикетки 400×320 задать номинальные 50×40 мм. Решение: 400/50=8 пикселей на мм, то есть 80 PPCM или 203.2 PPI по обеим осям. При сохранении проверьте pHYs и повторно рассчитанные миллиметры. Это самостоятельное изменение программы: свидетельства ниже относятся к исходным восьми запускам.

Следующий шаг: отдельная вставка и поля, читаемость скана и фильтры, сохранение прозрачности и выбор фона. PDF-страницы, настройки чтения setResolution и исторические aliases остаются отдельными темами полного справочника.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

Imagick::setImageResolutionЗадаёт числовую плотность по двум осям текущего изображения и возвращает true при успехе; не меняет число пикселей.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::setImageResolution(float $x_resolution, float $y_resolution): bool

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$image->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
$ok = $image->setImageResolution(254.0, 254.0);

Оба аргумента обязательны. Если растр 400×320, номинальная ширина равна 400/254 дюйма, то есть 400/254×25.4=40 мм; высота 320/254×25.4=32 мм. Деление / и умножение * выполняют именно этот расчёт. Пиксели 400×320 при этом сохранены.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Официальная сигнатура, возврат и ошибки

Imagick::setImageResolution(float $x_resolution, float $y_resolution): bool
ПараметрЗначение
$x_resolutionОбязательный float: плотность по горизонтали. Это не ширина растра в пикселях; единицу отдельно задаёт setImageUnits.
$y_resolutionОбязательный float: плотность по вертикали. Это не высота растра в пикселях; обе плотности задаются отдельно.
ЕдиницаПри RESOLUTION_PIXELSPERINCH значения выражены в пикселях на дюйм, при RESOLUTION_PIXELSPERCENTIMETER — на сантиметр. При неизвестной единице физический размер не вычисляем.

Sets the image resolution. Официальная доступность: PECL imagick 2, PECL imagick 3. Возврат: Returns true on success. Полный исходный XML и все его примеры сохранены ниже. Таблицы изменений у этих трёх записей отсутствуют; не придумываем дополнительные версии.

В проверенной Imagick 3.8.1 / ImageMagick 7.1.1-46 метод присваивает текущему изображению два числа resolution.x/y. Он не пересчитывает ширину/высоту, не делает изображение более детальным, не меняет единицу и не является resampleImage. Изменение плотности не предназначено для уменьшения интернет-трафика. setResolution до чтения векторного PDF — другая настройка процесса чтения; здесь уже загруженный растровый PNG.

Официальный пример — HTTP-контекст: функция принимает путь, использует realpath, устанавливает 50/50 и выводит blob. Строка header("Content-Type: image/jpg") сама не кодирует PNG/JPEG и не создаёт файл; формат должен соответствовать реально сформированным байтам. В наших CLI-программах явный PNG и writeImage через открытый helper, без HTTP-заголовков.

Все три метода на пустом объекте в ограниченной проверке дали ImagickException. PHP-обёртка преобразует внутренний отказ в ImagickException; неверный PHP-тип может дать TypeError. В исходном XML setImageUnits раздел ошибок не заполнен, поэтому уточнение относится к проверенной реализации и не заменяет raw-контракт. Внутренние setters не обещают проверять положительность/конечность числа и разрешённый список единиц: setImageResolution(0,0) в пробе вернул true. Для расчёта физических размеров программа сама проверяет плотности >0 и известную единицу; для внешних чисел нужна также is_finite и пределы приложения. Это политика приложения, не гарантия автоматического исключения API.

Восьмибитные RGB-пиксели нашей этикетки во всех контролях сохранены точно. Файл может иметь другие байты из-за метаданных и времени записи. PNG хранит физическую плотность в целых пикселях на метр; не выводим универсальный алгоритм округления всех форматов из одного примера. JPEG, TIFF, PDF, драйвер печати и браузер имеют отдельные правила. Номинальные миллиметры не являются измерением принтера, обещанием цветопробы или готовности для типографии.

Полный официальный XML и исходные примеры
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimageresolution">
 <refnamediv>
  <refname>Imagick::setImageResolution</refname>
  <refpurpose>Sets the image resolution</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageResolution</methodname>
   <methodparam><type>float</type><parameter>x_resolution</parameter></methodparam>
   <methodparam><type>float</type><parameter>y_resolution</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image resolution.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>x_resolution</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>y_resolution</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>



 <refsect1 role="examples">
  &reftitle.examples;
  <para>
    <example>
      <title> <function>Imagick::setImageResolution</function></title>
      <programlisting role="php">
      <![CDATA[
<?php
function setImageResolution($imagePath) {
    $imagick = new \Imagick(realpath($imagePath));
    $imagick->setImageResolution(50, 50);
    
    header("Content-Type: image/jpg");
    echo $imagick->getImageBlob();
}

?>
]]>
      </programlisting>
    </example>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Получить две номинальные ширины без изменения растра

Два самостоятельных PNG содержат один рисунок 400×320, но плотности 127 и 254 пикселя на дюйм задают номинальные 80×64 и 40×32 мм. Удвоение плотности уменьшило физический размер вдвое; новые детали и новые пиксели не появились.

Получить две номинальные ширины без изменения растраПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$large = clone $source; $large->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$large->setImageResolution(127.0, 127.0)) { throw new RuntimeException('Density failed'); }
$small = clone $source; $small->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$small->setImageResolution(254.0, 254.0)) { throw new RuntimeException('Density failed'); }
saveResolutionNative($large, 'density-127.png');
saveResolutionNative($small, 'density-254.png');
saveResolutionComparison([$source, $large, $small], 'resolution-density.png');
echo "resolution-density.png\ndensity-127.png\ndensity-254.png\n";

Два самостоятельных PNG содержат один рисунок 400×320, но плотности 127 и 254 пикселя на дюйм задают номинальные 80×64 и 40×32 мм. Удвоение плотности уменьшило физический размер вдвое; новые детали и новые пиксели не появились. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-density.png
density-127.png
density-254.png

Обнаружить разные плотности по осям и задать одинаковые

В density-xy.png X=254 PPI, Y=127 PPI: номинально 40×64 мм. В density-square.png обе оси 254 PPI: 40×32 мм. Пиксельные изображения остаются одинаковыми; если программа печати учитывает неодинаковые оси, физические пропорции различаются. Это диагностический контрпример, не рекомендация растянуть этикетку.

Обнаружить разные плотности по осям и задать одинаковыеПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$unequal = clone $source; $unequal->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH);
if (!$unequal->setImageResolution(254.0, 127.0)) { throw new RuntimeException('Unequal density failed'); }
$square = clone $unequal;
if (!$square->setImageResolution(254.0, 254.0)) { throw new RuntimeException('Equal density failed'); }
saveResolutionNative($unequal, 'density-xy.png');
saveResolutionNative($square, 'density-square.png');
saveResolutionComparison([$source, $unequal, $square], 'resolution-xy.png');
echo "resolution-xy.png\ndensity-xy.png\ndensity-square.png\n";

В density-xy.png X=254 PPI, Y=127 PPI: номинально 40×64 мм. В density-square.png обе оси 254 PPI: 40×32 мм. Пиксельные изображения остаются одинаковыми; если программа печати учитывает неодинаковые оси, физические пропорции различаются. Это диагностический контрпример, не рекомендация растянуть этикетку. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-xy.png
density-xy.png
density-square.png
Imagick::getImageResolutionВозвращает массив числовых плотностей текущего изображения с ключами x и y, не пиксельные размеры.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageResolution(): array

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$density = $image->getImageResolution();
$x = $density['x'];
$y = $density['y'];
$units = $image->getImageUnits();

= присваивает результат. Массив — пара значений с именами: ['x'] читает горизонтальную, ['y'] вертикальную плотность. Это отдельно от getImageWidth()/getImageHeight(), которые дают число пикселей. getImageUnits возвращает код единицы. Если после PNG читаем x=100 и единицу сантиметр, ширина равна 400/100×10=40 мм; нельзя делить на 100 как будто это PPI.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Официальная сигнатура, возврат и ошибки

Imagick::getImageResolution(): array
ПараметрЗначение
Нет аргументовПустые скобки (). Возвращённый array содержит double x и y. Единицу читают отдельно getImageUnits; само наличие массива не доказывает положительную плотность или заданный физический размер.

Gets the image X and Y resolution. Официальная доступность: PECL imagick 2, PECL imagick 3. Возврат: Returns the resolution as an array. Полный исходный XML и все его примеры сохранены ниже. Таблицы изменений у этих трёх записей отсутствуют; не придумываем дополнительные версии.

Массив возвращается по текущему изображению, а не по всему списку кадров. Его x/y могут стать другими после записи формата. В нашей PNG-пробе 254 PPI превратились в pHYs 10000 на метр и вернулись как 100 PPCM. 300 PPI вернулись как 118.11 PPCM из целого 11811 на метр. Это не ошибка getter: изменились единица представления и округление файла, а физический смысл почти тот же. Проверяйте пару значений вместе с getImageUnits и размерами в пикселях.

Все три метода на пустом объекте в ограниченной проверке дали ImagickException. PHP-обёртка преобразует внутренний отказ в ImagickException; неверный PHP-тип может дать TypeError. В исходном XML setImageUnits раздел ошибок не заполнен, поэтому уточнение относится к проверенной реализации и не заменяет raw-контракт. Внутренние setters не обещают проверять положительность/конечность числа и разрешённый список единиц: setImageResolution(0,0) в пробе вернул true. Для расчёта физических размеров программа сама проверяет плотности >0 и известную единицу; для внешних чисел нужна также is_finite и пределы приложения. Это политика приложения, не гарантия автоматического исключения API.

Восьмибитные RGB-пиксели нашей этикетки во всех контролях сохранены точно. Файл может иметь другие байты из-за метаданных и времени записи. PNG хранит физическую плотность в целых пикселях на метр; не выводим универсальный алгоритм округления всех форматов из одного примера. JPEG, TIFF, PDF, драйвер печати и браузер имеют отдельные правила. Номинальные миллиметры не являются измерением принтера, обещанием цветопробы или готовности для типографии.

Полный официальный XML и исходные примеры
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimageresolution">
 <refnamediv>
  <refname>Imagick::getImageResolution</refname>
  <refpurpose>Gets the image X and Y resolution</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>array</type><methodname>Imagick::getImageResolution</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Gets the image X and Y resolution.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns the resolution as an array.
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Прочитать реальные плотности после записи PNG

Заданные 300 PPI превратились в целое pHYs 11811 на метр; перечитывание вернуло 118.11 PPCM. Поэтому одно только число из getImageResolution нельзя называть DPI без чтения единицы. Растр этикетки не изменён.

Прочитать реальные плотности после записи PNGПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$label = clone $source; $label->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $label->setImageResolution(300.0, 300.0);
saveResolutionNative($label, 'checked-label.png');
$loaded = new Imagick(__DIR__ . '/checked-label.png');
$density = $loaded->getImageResolution();
saveResolutionComparison([$source, $loaded], 'resolution-reload.png');
echo "resolution-reload.png\nchecked-label.png\n";
printf("reload units=%d x=%.2f y=%.2f\n", $loaded->getImageUnits(), $density['x'], $density['y']);

Заданные 300 PPI превратились в целое pHYs 11811 на метр; перечитывание вернуло 118.11 PPCM. Поэтому одно только число из getImageResolution нельзя называть DPI без чтения единицы. Растр этикетки не изменён. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
resolution-reload.png
checked-label.png
reload units=2 x=118.11 y=118.11

Проверить номинальные миллиметры полученного файла

Проверка заданного допуска ±0.05 мм принимает файл 254 PPI и отклоняет файл 300 PPI для требования 40×32 мм. Это проверка метаданных и расчёта, не результат пробной печати. Для неизвестной единицы или неположительной плотности программа прекращает расчёт.

Проверить номинальные миллиметры полученного файлаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$panels = [$source];
foreach (['accepted-label.png' => 254.0, 'wrong-size-label.png' => 300.0] as $filename => $ppi) {
    $label = clone $source; $label->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $label->setImageResolution($ppi, $ppi);
    saveResolutionNative($label, $filename);
    $loaded = new Imagick(__DIR__ . '/' . $filename);
    $density = $loaded->getImageResolution();
    $units = $loaded->getImageUnits();
    if ($units === Imagick::RESOLUTION_PIXELSPERINCH) { $factor = 25.4; }
    elseif ($units === Imagick::RESOLUTION_PIXELSPERCENTIMETER) { $factor = 10.0; }
    else { throw new RuntimeException('Physical unit is unknown'); }
    if ($density['x'] <= 0 || $density['y'] <= 0) { throw new RuntimeException('Positive density required'); }
    $widthMm = $factor * $loaded->getImageWidth() / $density['x'];
    $heightMm = $factor * $loaded->getImageHeight() / $density['y'];
    $matches = abs($widthMm - 40.0) <= 0.05 && abs($heightMm - 32.0) <= 0.05;
    printf("%s nominal-mm=%.2fx%.2f matches=%d\n", $filename, $widthMm, $heightMm, (int)$matches);
    $panels[] = $loaded;
}
saveResolutionComparison($panels, 'resolution-check.png');
echo "resolution-check.png\n";

Проверка заданного допуска ±0.05 мм принимает файл 254 PPI и отклоняет файл 300 PPI для требования 40×32 мм. Это проверка метаданных и расчёта, не результат пробной печати. Для неизвестной единицы или неположительной плотности программа прекращает расчёт. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
accepted-label.png nominal-mm=40.00x32.00 matches=1
wrong-size-label.png nominal-mm=33.87x27.09 matches=0
resolution-check.png
Imagick::setImageUnitsЗадаёт единицу плотности текущего изображения, возвращает bool-статус; числовые плотности не пересчитывает.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::setImageUnits(int $units): bool

Самая маленькая запись

$image содержит загруженное изображение. $ обозначает переменную; -> вызывает её метод; () содержит аргументы, запятые разделяют их; ; завершает инструкцию. Imagick:: обращается к именованной константе класса. Строки в кавычках являются текстом; числа 254.0/100.0 — float. Setter возвращает bool true/false как статус, не новую картинку: не заменяйте им $image.

$ok = $image->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER);

PPI означает пиксели на дюйм, PPCM — пиксели на сантиметр. DPI относится к точкам принтера; такую физическую печать мы не измеряли. Так выбирают пиксели на сантиметр. Если перед этим было число 100 с единицей дюйм, число останется 100, а физический смысл изменится. Для сохранения смысла PPI→PPCM нужно разделить обе плотности на 2.54 и отдельно передать их в setImageResolution. Одного вызова units недостаточно.

clone создаёт рабочую копию. if проверяет условие, ! отрицает статус, throw new RuntimeException прекращает цепочку при отказе. echo выводит строку, . соединяет строки, "\n" задаёт перевод строки. printf подставляет значения: %d — целое, %.2f — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Официальная сигнатура, возврат и ошибки

Imagick::setImageUnits(int $units): bool
ПараметрЗначение
$unitsОбязательный int-код константы RESOLUTION_PIXELSPERINCH либо RESOLUTION_PIXELSPERCENTIMETER; RESOLUTION_UNDEFINED означает неизвестную единицу. Это не число DPI. В проверенной сборке коды 1/2/0, но в PHP используем имена.

Sets the image units of resolution. Официальная доступность: PECL imagick 2, PECL imagick 3. Возврат: Returns true on success. Полный исходный XML и все его примеры сохранены ниже. Таблицы изменений у этих трёх записей отсутствуют; не придумываем дополнительные версии.

Библиотека присваивает только код единицы текущего изображения. Она не делит 254 на 2.54 автоматически и не меняет пиксели. Установка RESOLUTION_UNDEFINED не даёт права вычислять миллиметры: в PNG может сохраниться только отношение плотностей без известной физической единицы. Константы относятся к плотности изображения, а не к внутренней яркости, цветовому каналу или настройкам принтера.

Все три метода на пустом объекте в ограниченной проверке дали ImagickException. PHP-обёртка преобразует внутренний отказ в ImagickException; неверный PHP-тип может дать TypeError. В исходном XML setImageUnits раздел ошибок не заполнен, поэтому уточнение относится к проверенной реализации и не заменяет raw-контракт. Внутренние setters не обещают проверять положительность/конечность числа и разрешённый список единиц: setImageResolution(0,0) в пробе вернул true. Для расчёта физических размеров программа сама проверяет плотности >0 и известную единицу; для внешних чисел нужна также is_finite и пределы приложения. Это политика приложения, не гарантия автоматического исключения API.

Восьмибитные RGB-пиксели нашей этикетки во всех контролях сохранены точно. Файл может иметь другие байты из-за метаданных и времени записи. PNG хранит физическую плотность в целых пикселях на метр; не выводим универсальный алгоритм округления всех форматов из одного примера. JPEG, TIFF, PDF, драйвер печати и браузер имеют отдельные правила. Номинальные миллиметры не являются измерением принтера, обещанием цветопробы или готовности для типографии.

Полный официальный XML и исходные примеры
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimageunits">
 <refnamediv>
  <refname>Imagick::setImageUnits</refname>
  <refpurpose>Sets the image units of resolution</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageUnits</methodname>
   <methodparam><type>int</type><parameter>units</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image units of resolution.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>units</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Увидеть, что смена единицы не переводит число плотности

В живых объектах осталось 100/100, но сначала это пиксели на дюйм, затем на сантиметр. Номинальная ширина стала около 101.60 мм против 40.00 мм. От setter единиц не требуется автоматическая конверсия; её выполняет программа отдельно, если нужно сохранить физический размер.

Увидеть, что смена единицы не переводит число плотностиПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$inch = clone $source; $inch->setImageResolution(100.0, 100.0);
if (!$inch->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH)) { throw new RuntimeException('Inch units failed'); }
$cm = clone $inch;
if (!$cm->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER)) { throw new RuntimeException('Centimeter units failed'); }
$inchDensity = $inch->getImageResolution(); $cmDensity = $cm->getImageResolution();
saveResolutionNative($inch, 'units-inch.png'); saveResolutionNative($cm, 'units-cm.png');
saveResolutionComparison([$source, $inch, $cm], 'units-choice.png');
echo "units-choice.png\nunits-inch.png\nunits-cm.png\n";
printf("live inch-x=%.2f cm-x=%.2f\n", $inchDensity['x'], $cmDensity['x']);

В живых объектах осталось 100/100, но сначала это пиксели на дюйм, затем на сантиметр. Номинальная ширина стала около 101.60 мм против 40.00 мм. От setter единиц не требуется автоматическая конверсия; её выполняет программа отдельно, если нужно сохранить физический размер. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
units-choice.png
units-inch.png
units-cm.png
live inch-x=100.00 cm-x=100.00

Перевести PPI в PPCM с сохранением номинального размера

Переводим каждую плотность 254/2.54=100 и меняем единицу на сантиметр. Оба самостоятельных PNG имеют pHYs 10000/10000 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов.

Перевести PPI в PPCM с сохранением номинального размераПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__ . '/resolution-fixture.php';
$source = loadResolutionSource();
$inch = clone $source; $inch->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); $inch->setImageResolution(254.0, 254.0);
$density = $inch->getImageResolution();
$cm = clone $inch;
if (!$cm->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER)) { throw new RuntimeException('Units failed'); }
if (!$cm->setImageResolution($density['x'] / 2.54, $density['y'] / 2.54)) { throw new RuntimeException('Converted density failed'); }
$converted = $cm->getImageResolution();
saveResolutionNative($inch, 'equivalent-inch.png'); saveResolutionNative($cm, 'equivalent-cm.png');
saveResolutionComparison([$source, $inch, $cm], 'units-convert.png');
echo "units-convert.png\nequivalent-inch.png\nequivalent-cm.png\n";
printf("converted x=%.2f y=%.2f\n", $converted['x'], $converted['y']);

Переводим каждую плотность 254/2.54=100 и меняем единицу на сантиметр. Оба самостоятельных PNG имеют pHYs 10000/10000 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов. Для запуска в одной папке нужны example.php, resolution-fixture.php и source.png.b64; сохраните также остальные файлы ZIP. Команда: php example.php с Imagick. PHP не требует сети, внешнего принтера или шрифтов. Самостоятельные PNG перечислены в выводе; составная картинка нужна только для просмотра пикселей. Полный helper открыт в разделе проверки.

Ожидаемый вывод
units-convert.png
equivalent-inch.png
equivalent-cm.png
converted x=100.00 y=100.00
Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.