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

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


| Понятие до схемы | Конкретный смысл |
|---|---|
| Пиксельный размер | W=400, H=320 — число столбцов и строк. Эти числа не меняются от трёх методов урока. Напечатанная строка 400×320 на растре описывает именно их. |
| Плотность / PPI / PPCM | dx/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. Ни один сам не записывает файл и не проверяет реальный принтер. |

Самая маленькая запись
$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 мм. Обе панели сравнения имеют одинаковые исходные пиксели.
<?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 — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Получить две номинальные ширины без изменения растра
Два самостоятельных 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
Заданные 300 PPI превратились в целое pHYs 11811 на метр; перечитывание вернуло 118.11 PPCM. Поэтому одно только число из getImageResolution нельзя называть DPI без чтения единицы. Растр этикетки не изменён.
<?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 — число с двумя знаками после точки. Основы: массивы, объекты и методы, исключения.

Увидеть, что смена единицы не переводит число плотности
В живых объектах осталось 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 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов.
<?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/jpg | HTTP-заголовок не перекодирует байты. В этом уроке все результаты явно сохраняются как 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 26851679 | resampleImage может менять число пикселей, тогда как metadata density — другая задача. Все наши исходные 400×320 сохранены; уменьшение пиксельного размера требует другого урока. |
| SO 4076936 | Нужно читать/писать DPI для будущей печати. Getter даёт x/y, единица читается отдельно; одинаковое число в PPI и PPCM не означает одинаковый физический размер. |
| SO 70333765 | PNG-этикетке нужен заданный физический размер без изменения рисунка. Мы рассчитываем номинальные 40×32 мм и проверяем сохранённый PNG, но не подменяем этим настройку страницы PDF или драйвера печати. |
| SO 75716790 | Меньшее PPI не обязано уменьшать файл и не удаляет детали. Наша metadata-коррекция намеренно сохраняет все пиксели; для веб-оптимизации нужны размеры растра/кодирование и отдельные измерения. |
| SO 78455312 | Расчёт с жёстко заданным 300 игнорирует метаданные файла. Берём реальные x/y и units после чтения, проверяем номинальный размер с явным допуском. |
Рассчитать собственный номинал и продолжить

Упражнение: для той же этикетки 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 без чтения единицы. Растр этикетки не изменён.
<?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 на метр и исходные пиксели, значит номинальный размер совпал. Равенство метаданных и пикселей не является обещанием одинаковых всех байтов файлов.
<?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. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


