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

Дерево руководства
Глава 422 · После первых изображений Gmagick, массивов и объектов
Gmagick: пиксели, печатная плотность и чтение raw
Рассчитать физический размер, отличить метаданные от resample и декодировать собственный RGB16 с известной геометрией.
Разделить пиксели и плотность печати
Перед печатью сначала разделим три величины:320×200 пикселей,100 пикселей на единицу длины и физический размер.320÷100=3.2,200÷100=2. Если единица — дюйм, получаем 3.2×2 дюйма; если сантиметр —3.2×2 сантиметра. На экране обе картинки ниже выглядят одинаково: пиксели не пересчитывались.


<?php
$image = new Gmagick(__DIR__ . '/product.ppm');
$image->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);
$image->setImageResolution(100, 100);
$density = $image->getImageResolution();
echo $density['x'], ' px/in', "\n";setImageUnits задаёт смысл чисел, setImageResolution — значения поX иY. Получается вывод «100 px/in». Для растра точнее говорить PPI, пиксели на дюйм; слово DPI часто используется интерфейсами, но точки принтера и пиксели файла не обязаны совпадать. Плотность — рекомендация для физического размещения, а не гарантия качества конкретного устройства. В полной программе проверяем также значение единиц.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/product.ppm');
$inch=clone $source;$inch->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);$inch->setImageResolution(100,100);
$cm=clone $source;$cm->setImageUnits(Gmagick::RESOLUTION_PIXELSPERCENTIMETER);$cm->setImageResolution(100,100);
$before=['inch'=>['units'=>$inch->getImageUnits(),'density'=>$inch->getImageResolution()],'cm'=>['units'=>$cm->getImageUnits(),'density'=>$cm->getImageResolution()]];
$inch->setImageDepth(8);
$inch->setImageFormat('PNG');
$inch->writeImage(__DIR__.'/gm99-density100-inch.png');
$cm->setImageDepth(8);
$cm->setImageFormat('PNG');
$cm->writeImage(__DIR__.'/gm99-density100-cm.png');
$a=new Gmagick(__DIR__.'/gm99-density100-inch.png');$b=new Gmagick(__DIR__.'/gm99-density100-cm.png');
$after=['inch'=>['units'=>$a->getImageUnits(),'density'=>$a->getImageResolution()],'cm'=>['units'=>$b->getImageUnits(),'density'=>$b->getImageResolution()]];
gmReport('gm99-density-label',["gmagick.construct", "gmagick.setimageunits", "gmagick.setimageresolution", "gmagick.getimageunits", "gmagick.getimageresolution", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-density100-inch.png", "gm99-density100-cm.png"],
['same_pixels'=>$a->getImageSignature()===$b->getImageSignature(),'units_before'=>$before['inch']['units']===Gmagick::RESOLUTION_PIXELSPERINCH&&$before['cm']['units']===Gmagick::RESOLUTION_PIXELSPERCENTIMETER,'png_units'=>$after['inch']['units']===Gmagick::RESOLUTION_PIXELSPERCENTIMETER&&abs($after['inch']['density']['x']-39.37)<0.001&&abs($after['cm']['density']['x']-100)<0.001,'size_gm99_density100_inch'=>gmInspect('gm99-density100-inch.png')['width']===320&&gmInspect('gm99-density100-inch.png')['height']===200,'size_gm99_density100_cm'=>gmInspect('gm99-density100-cm.png')['width']===320&&gmInspect('gm99-density100-cm.png')['height']===200],
$errors ?? [], ['before_save'=>$before,'after_save'=>$after]);
echo "gm99-density100-inch.png 320x200 gm99-density100-cm.png 320x200\n";
Ожидаемый результат
gm99-density100-inch.png 320x200 gm99-density100-cm.png 320x200
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-density100-inch.png 320x200 gm99-density100-cm.png 320x200
После сохранения PNG100 px/in читаются здесь как 39.37 px/cm, с округлением: это почти то же физическое значение, потому что один дюйм равен 2.54 см. Не считайте такое чтение потерей плотности только из-за изменения числа. Второй файл действительно содержит 100 px/cm и означает другой размер. У PPM исходная плотность 0; придумывать 300 для неизвестного входа без правила приложения нельзя.
Визуальная модель: сетка 320×200 задаёт количество исходных точек. Линейка 100 px/in говорит, сколько точек разместить на дюйме. Смена линейки не добавляет ячеек сетки; resample меняет сетку. Это модель расчёта размера, а не модель работы всех сопел или лазерных точек принтера.
Изменить число отсчётов для той же физической ширины
Нужен тот же физический отпечаток, но с другим количеством отсчётов. Исходные 320×200 при 100 px/in занимают 3.2×2 дюйма. Для 200 px/in потребуются 640×400, для 50 —160×100. Ниже видны реальные изменённые растры; увеличение количества пикселей само по себе не создаёт новых деталей.



<?php
$image = new Gmagick(__DIR__ . '/product.ppm');
$image->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);
$image->setImageResolution(100, 100);
$image->resampleImage(200, 200, Gmagick::FILTER_LANCZOS, 1.0);
$image->setImageResolution(200, 200);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/print-200.png');Аргументы resampleImage — целевые плотности по осям, фильтр и blur.200 не является шириной будущего файла. FILTER_LANCZOS выбирает пересчёт,1.0 оставляет стандартный фактор. Важная особенность этого runtime: resampleImage изменяет геометрию, но getImageResolution сразу после него остаётся 100. Поэтому следующий явный setImageResolution(200,200) необходим для согласования физического размера.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/product.ppm');$source->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);$source->setImageResolution(100,100);
$up=clone $source;$up->resampleImage(200,200,Gmagick::FILTER_LANCZOS,1.0);$upObserved=$up->getImageResolution();$up->setImageResolution(200,200);
$down=clone $source;$down->resampleImage(50,50,Gmagick::FILTER_LANCZOS,1.0);$downObserved=$down->getImageResolution();$down->setImageResolution(50,50);
$physical=[$source->getImageWidth()/100,$up->getImageWidth()/200,$down->getImageWidth()/50];
$errors=['empty'=>gmTry(fn()=>(new Gmagick())->resampleImage(100,100,Gmagick::FILTER_POINT,1.0))];
$up->setImageDepth(8);
$up->setImageFormat('PNG');
$up->writeImage(__DIR__.'/gm99-resample200.png');
$down->setImageDepth(8);
$down->setImageFormat('PNG');
$down->writeImage(__DIR__.'/gm99-resample50.png');
gmReport('gm99-print-resample',["gmagick.construct", "gmagick.setimageunits", "gmagick.setimageresolution", "gmagick.resampleimage", "gmagick.getimageresolution", "gmagick.getimagewidth", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-resample200.png", "gm99-resample50.png"],
['physical_width'=>abs($physical[0]-3.2)<1e-9&&$physical===[3.2,3.2,3.2],'observed_density_not_updated'=>$upObserved===['x'=>100.0,'y'=>100.0]&&$downObserved===$upObserved,'empty_rejected'=>$errors['empty']['class']==='GmagickException','size_gm99_resample200'=>gmInspect('gm99-resample200.png')['width']===640&&gmInspect('gm99-resample200.png')['height']===400,'size_gm99_resample50'=>gmInspect('gm99-resample50.png')['width']===160&&gmInspect('gm99-resample50.png')['height']===100],
$errors ?? [], ['inches'=>$physical,'getter_after_resample_before_fix'=>[$upObserved,$downObserved]]);
echo "gm99-resample200.png 640x400 gm99-resample50.png 160x100\n";
Ожидаемый результат
gm99-resample200.png 640x400 gm99-resample50.png 160x100
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-resample200.png 640x400 gm99-resample50.png 160x100
Полная программа фиксирует оставшиеся 100, затем назначает целевые значения и проверяет 320/100=640/200=160/50=3.2. Для назначения плотности без изменения пикселей resample не нужен. Для заданной веб-ширины лучше resizeImage с пиксельными сторонами. Пустой объект даёт GmagickException; исходная плотность должна быть известна до расчёта отношения.
Собрать проверяемый маршрут печатной копии
Печатный сервис должен остановиться, если вход не сообщает единицы или плотность. Функция printCopy принимает известный исходник и целевую плотность, пересчитывает копию и явно обновляет метаданные. На выходе 160×100 при 50 px/in — прежняя ширина 3.2 дюйма.


<?php
$image = new Gmagick(__DIR__ . '/product.ppm');
$image->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);
$image->setImageResolution(100, 100);
$copy = clone $image;
$copy->resampleImage(50, 50, Gmagick::FILTER_LANCZOS, 1.0);
$copy->setImageResolution(50, 50);Полная функция сначала читает getImageResolution и getImageUnits. Она принимает только известные px/in и положительные значения по обеим осям. Ограничение целевой плотности 600 — правило маленького учебного сервиса, помогающее ограничить рост, а не предел библиотеки. throw сообщает InvalidArgumentException, return передаёт готовую копию. Оригинал остаётся 320×200.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
function printCopy(Gmagick $source,float $target):Gmagick {
if($target<=0||$target>600)throw new InvalidArgumentException('Choose a positive target no greater than600');
$density=$source->getImageResolution();$units=$source->getImageUnits();
if($units!==Gmagick::RESOLUTION_PIXELSPERINCH||$density['x']<=0||$density['y']<=0)throw new InvalidArgumentException('Source needs known px/in density');
$copy=clone $source;$copy->resampleImage($target,$target,Gmagick::FILTER_LANCZOS,1.0);$copy->setImageResolution($target,$target);return $copy;
}
$source=new Gmagick(__DIR__.'/product.ppm');$source->setImageUnits(Gmagick::RESOLUTION_PIXELSPERINCH);$source->setImageResolution(100,100);
$result=printCopy($source,50);$density=$result->getImageResolution();
$errors=['target'=>gmTry(fn()=>printCopy($source,0)),'unknown_density'=>gmTry(fn()=>printCopy(new Gmagick(__DIR__.'/product.ppm'),50))];
$result->setImageDepth(8);
$result->setImageFormat('PNG');
$result->writeImage(__DIR__.'/gm99-print-copy.png');
gmReport('gm99-print-function',["gmagick.construct", "gmagick.getimageresolution", "gmagick.getimageunits", "gmagick.resampleimage", "gmagick.setimageresolution", "gmagick.setimageunits", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-print-copy.png"],
['density50'=>$density===['x'=>50.0,'y'=>50.0],'original_size'=>$source->getImageWidth()===320&&$source->getImageHeight()===200,'target_rejected'=>$errors['target']['class']==='InvalidArgumentException','unknown_rejected'=>$errors['unknown_density']['class']==='InvalidArgumentException','size_gm99_print_copy'=>gmInspect('gm99-print-copy.png')['width']===160&&gmInspect('gm99-print-copy.png')['height']===100],
$errors ?? [], ['target_density'=>$density,'physical_width_inches'=>3.2]);
echo "gm99-print-copy.png 160x100\n";
Ожидаемый результат
gm99-print-copy.png 160x100
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-print-copy.png 160x100
Две ошибочные ситуации различаются: нулевая цель и неизвестная плотность исходника. Числа из имени файла вроде «300dpi» не заменяют свойства изображения и не гарантируют пригодность к печати. Даже корректная плотность не говорит о резкости, цветовом профиле и разрешённом физическом размере — эти требования надо согласовать отдельно. Этот пример работает с одним локальным изображением, а не с PDF-рендерингом.
Прочитать поток RGB с известной геометрией
Поток датчика без заголовка не сообщает, где заканчивается строка и сколько в нём пикселей. Для собственного RGB16 файла заранее известны 32×20, три компонента и два байта на компонент:32×20×3×2=3840 байт. Маленький оригинал, двойной размер и увеличение×10 показаны отдельно.



<?php
$image = new Gmagick();
$image->setSize(32, 20);
$hint = $image->getSize();
$image->readImage('rgb:' . __DIR__ . '/sensor16.rgb');
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/sensor.png');setSize должен стоять до чтения, getSize возвращает массив columns/rows. Префикс rgb: выбирает декодер потока, затем идёт путь. В нашем файле каждое исходное 8-битное значениеv расширено до 16 бит какv×257: оба байта одинаковы. Поэтому неоднозначность порядка этих двух байтов не влияет на данный специально созданный набор. Это не утверждение, что любой RGB16 файл устроен одинаково.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image=new Gmagick();$image->setSize(32,20);$hint=$image->getSize();
$image->readImage('rgb:'.__DIR__.'/sensor16.rgb');$effectiveDepth=$image->getImageDepth();
$sample=clone $image;$sample->cropImage(1,1,16,10);$center=$sample->getImageHistogram()[0]->getColor(true);
$double=clone $image;$double->magnifyImage();
$view=clone $image;$view->resizeImage(320,200,Gmagick::FILTER_POINT,1.0);
$image->setImageDepth(8);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__.'/gm99-raw-native.png');
$double->setImageDepth(8);
$double->setImageFormat('PNG');
$double->writeImage(__DIR__.'/gm99-raw-double.png');
$view->setImageDepth(8);
$view->setImageFormat('PNG');
$view->writeImage(__DIR__.'/gm99-raw-view.png');
gmReport('gm99-raw-decode',["gmagick.construct", "gmagick.setsize", "gmagick.getsize", "gmagick.readimage", "gmagick.getimagedepth", "gmagick.cropimage", "gmagick.getimagehistogram", "gmagickpixel.getcolor", "gmagick.magnifyimage", "gmagick.resizeimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-raw-native.png", "gm99-raw-double.png", "gm99-raw-view.png"],
['hint'=>$hint===['columns'=>32,'rows'=>20],'byte_count'=>filesize(__DIR__."/sensor16.rgb")===3840,'effective_eight'=>$effectiveDepth===8,'known_center'=>$center===['r'=>131,'g'=>134,'b'=>132],'size_gm99_raw_native'=>gmInspect('gm99-raw-native.png')['width']===32&&gmInspect('gm99-raw-native.png')['height']===20,'size_gm99_raw_double'=>gmInspect('gm99-raw-double.png')['width']===64&&gmInspect('gm99-raw-double.png')['height']===40,'size_gm99_raw_view'=>gmInspect('gm99-raw-view.png')['width']===320&&gmInspect('gm99-raw-view.png')['height']===200],
$errors ?? [], ['read_hint'=>$hint,'storage_bits_per_sample'=>16,'effective_depth'=>$effectiveDepth,'center'=>$center]);
echo "gm99-raw-native.png 32x20 gm99-raw-double.png 64x40 gm99-raw-view.png 320x200\n";
Ожидаемый результат
gm99-raw-native.png 32x20 gm99-raw-double.png 64x40 gm99-raw-view.png 320x200
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-raw-native.png 32x20 gm99-raw-double.png 64x40 gm99-raw-view.png 320x200
В фиксированной Q16-сборке поток RGB8 из 1920 байт дал Unexpected end-of-file; сохранённая попытка отдельно проверена, универсальный 8-битный декодер здесь не обещается. Работающий RGB16 содержит 3840 байт, однако getImageDepth показывает 8: все значения эффективно представимы 8 битами. Нельзя выводить размер raw-потока из этого getter. Полная программа проверяет центр RGB131,134,132 и увеличивает копию через magnifyImage; большое увеличение для чтения сделано точечным resizeImage.
Проверить, что подсказка чтения не является изменением размера
У PPM есть заголовок с реальными размерами. Поэтому настройка объекта 32×20 не обязана уменьшать прочитанный PPM320×200. Этот пример показывает исходную карточку и отдельно выполненное уменьшение, чтобы слово size не подменило нужную операцию.


<?php
$image = new Gmagick();
$image->setSize(32, 20);
$image->readImage(__DIR__ . '/product.ppm');
echo $image->getImageWidth(), 'x', $image->getImageHeight(), "\n";
$image->minifyImage();До minifyImage код выводит «320x200». getSize по-прежнему описывает настройку columns32/rows20, а getImageWidth/getImageHeight — действительный растр. После minifyImage результат 160×100. Отсюда правило: подсказку декодеру не используем как универсальное изменение размера. Массив вместо целой ширины setSize отдельно даёт TypeError.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image=new Gmagick();$image->setSize(32,20);$hint=$image->getSize();
$image->readImage(__DIR__.'/product.ppm');$actual=[$image->getImageWidth(),$image->getImageHeight()];
$small=clone $image;$small->minifyImage();
$errors=['size_type'=>gmTry(fn()=>(new Gmagick())->setSize([],20))];
$image->setImageDepth(8);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__.'/gm99-size-hint-source.png');
$small->setImageDepth(8);
$small->setImageFormat('PNG');
$small->writeImage(__DIR__.'/gm99-size-hint-half.png');
gmReport('gm99-size-hint',["gmagick.construct", "gmagick.setsize", "gmagick.getsize", "gmagick.readimage", "gmagick.getimagewidth", "gmagick.getimageheight", "gmagick.minifyimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-size-hint-source.png", "gm99-size-hint-half.png"],
['hint_separate'=>$hint===['columns'=>32,'rows'=>20]&&$actual===[320,200],'type_rejected'=>$errors['size_type']['class']==='TypeError','size_gm99_size_hint_source'=>gmInspect('gm99-size-hint-source.png')['width']===320&&gmInspect('gm99-size-hint-source.png')['height']===200,'size_gm99_size_hint_half'=>gmInspect('gm99-size-hint-half.png')['width']===160&&gmInspect('gm99-size-hint-half.png')['height']===100],
$errors ?? [], ['hint'=>$hint,'decoded_geometry'=>$actual]);
echo "gm99-size-hint-source.png 320x200 gm99-size-hint-half.png 160x100\n";
Ожидаемый результат
gm99-size-hint-source.png 320x200 gm99-size-hint-half.png 160x100
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-size-hint-source.png 320x200 gm99-size-hint-half.png 160x100
Для формата без размеров подсказка нужна; для формата с заголовком решение зависит от декодера. Пример не обещает, что setSize одинаково действует на все поддерживаемые форматы. Если сервис требует точную миниатюру, сначала прочитайте и проверьте действительную геометрию, затем вызовите соответствующий метод изменения размера.
Получить два масштаба превью из одного оригинала
Для страницы каталога нужны большая версия и маленькое превью. Оба результата создаются независимо из одного оригинала. Увеличение вдвое по каждой оси даёт 640×400, уменьшение —160×100; это разные растры с разной площадью и количеством данных.



<?php
$source = new Gmagick(__DIR__ . '/product.ppm');
$large = clone $source;
$large->magnifyImage();
$small = clone $source;
$small->minifyImage();У обоих методов нет аргументов. Важно слово «каждая»:640×400 содержит вчетверо больше пикселей,160×100 — вчетверо меньше. Полная программа сохраняет оба файла и проверяет неизменность оригинала. Magnify возвращает тот же объект, хотя официальный тип результата обозначен mixed. clone нужен для независимости, а не для получения возвращаемого значения.
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/product.ppm');$sourceSignature=$source->getImageSignature();
$large=clone $source;$same=$large->magnifyImage()===$large;
$small=clone $source;$small->minifyImage();
$large->setImageDepth(8);
$large->setImageFormat('PNG');
$large->writeImage(__DIR__.'/gm99-magnified.png');
$small->setImageDepth(8);
$small->setImageFormat('PNG');
$small->writeImage(__DIR__.'/gm99-minified.png');
gmReport('gm99-preview-sizes',["gmagick.construct", "gmagick.getimagesignature", "gmagick.magnifyimage", "gmagick.minifyimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-magnified.png", "gm99-minified.png"],
['same_object'=>$same,'source_preserved'=>$source->getImageSignature()===$sourceSignature,'scaled_geometry'=>$large->getImageWidth()===640&&$small->getImageWidth()===160,'size_gm99_magnified'=>gmInspect('gm99-magnified.png')['width']===640&&gmInspect('gm99-magnified.png')['height']===400,'size_gm99_minified'=>gmInspect('gm99-minified.png')['width']===160&&gmInspect('gm99-minified.png')['height']===100],
$errors ?? [], ['original'=>[320,200],'large'=>[640,400],'small'=>[160,100]]);
echo "gm99-magnified.png 640x400 gm99-minified.png 160x100\n";
Ожидаемый результат
gm99-magnified.png 640x400 gm99-minified.png 160x100
Архив запускается командой php example.php с Gmagick. Проверенный отдельный runtime: PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Собственные входы восстанавливаются из .b64; gm-fixture.php проверяет файлы и результат, изучаемые операции находятся в самой программе. PNG и metrics.json записываются рядом.
Вывод успешного запуска
gm99-magnified.png 640x400 gm99-minified.png 160x100
Увеличение не восстанавливает мелкие детали, потерянные при уменьшении. Для заданной ширины вроде 240, выбора фильтра и запрета роста маленького входа используйте resizeImage или thumbnailImage из предыдущего маршрута. Эти результаты относятся к чётным 320×200; правило округления нечётных сторон здесь не заявляется. При обработке больших файлов учитывайте одновременно оригинал и обе копии в памяти.
Упражнение: ширина 600 px при 300 px/in — сколько дюймов? Ответ:2. Изменится ли ширина 600 px от одного setImageResolution(150,150)? Ответ:нет, изменится расчётный размер до 4 дюймов. Сколько байт в нашем 32×20 RGB16 без заголовка? Ответ:3840; эффективная глубина 8 не отменяет упаковку 16 бит. Для точных пиксельных размеров см. resizeImage и thumbnailImage, для выпуска файла — контракты экспорта. Геометрические эффекты разобраны в преобразованиях изображения.
Практический вопрос, из которого вырос сценарий
PHP Imagick::resampleImage resizes image instead of resampling: При запросе меньшей плотности автор получает меньшие пиксельные стороны, но прежнее число в метаданных, и смешивает плотность с размером веб-изображения. Сначала считаем физический размер как пиксели/плотность, затем отдельно показываем setters и resampleImage. На нашем Gmagick resample меняет стороны, но оставляет старую плотность; после измерения этого факта явно записываем целевое значение. PNG читается с учётом сантиметровых единиц и округления, а неизвестная исходная плотность отклоняется функцией.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Gmagick::getimageresolutionПрочитать плотность отдельно по X и Y
PECL gmagick >= Unknown · gmagick
Gmagick::getimageresolution(): arrayБез аргументов; результат array. Проверенная реализация возвращает ключи x и y с float. Это плотность, которую нужно интерпретировать вместе с getImageUnits, а не ширина и высота в пикселях. У PPM нашего входа обе величины 0: размер файла известен, печатная плотность — нет. После записи PNG значения могут вернуться в пикселях на сантиметр:100 px/in здесь читаются как 39.37 px/cm. Сравнивайте физический смысл с допуском, а не голое число 100 независимо от единиц.
Gmagick::getimageresolution(): arrayАргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.
Возврат по PHP.net: array — массив с указанными выше ключами.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Разделить пиксели и плотность печати; Собрать проверяемый маршрут печатной копии.
Gmagick::getimageunitsПрочитать единицы плотности
PECL gmagick >= Unknown · gmagick
Gmagick::getimageunits(): intАргументов нет, результат int. Сравнивайте с Gmagick::RESOLUTION_UNDEFINED, RESOLUTION_PIXELSPERINCH либо RESOLUTION_PIXELSPERCENTIMETER. Без единиц число 100 нельзя честно объявить 100 dpi. PNG может хранить и возвращать другую единицу с эквивалентной величиной. У этой страницы PHP.net отдельный список исключений не приведён; C-обёртка проверяет наличие изображения. Функция печатной копии отвергает неизвестные единицы вместо молчаливого предположения.
Gmagick::getimageunits(): intАргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.
Возврат по PHP.net: int — целое число с указанным выше смыслом.
Отдельный раздел ошибок на этой странице PHP.net отсутствует; это не гарантия успеха на пустом или неверном входе.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Разделить пиксели и плотность печати; Собрать проверяемый маршрут печатной копии.
Gmagick::getsizeПрочитать настройку геометрии декодера
PECL gmagick >= Unknown · gmagick
Gmagick::getsize(): arrayБез аргументов; array с ключами columns и rows. Это размер, связанный с объектом для чтения данных, а не универсальный аналог getImageWidth/getImageHeight. В новом объекте проверено 0/0; после setSize(32,20) —32/20. Raw-поток использует указанную геометрию. PPM с собственным заголовком остаётся 320×200 даже при настройке 32×20, что показано отдельным PNG. Измерять готовое изображение нужно методами ширины и высоты.
Gmagick::getsize(): arrayАргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.
Возврат по PHP.net: array — массив с указанными выше ключами.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Прочитать поток RGB с известной геометрией; Проверить, что подсказка чтения не является изменением размера.
Gmagick::magnifyimageУвеличить обе стороны вдвое
PECL gmagick >= Unknown · gmagick
Gmagick::magnifyimage(): mixedАргументов нет. PHP.net обозначает возвращаемый тип mixed и описывает увеличенный объект Gmagick; в проверенной сборке возвращается тот же объект.32×20 становится 64×40,320×200 —640×400. Площадь и число пикселей растут вчетверо, поэтому память нельзя оценивать только множителем 2. Метод не добавляет новых реальных деталей исходника. Для заданного размера и выбора фильтра используйте resizeImage. Пример сохраняет оригинал через clone.
Gmagick::magnifyimage(): mixedАргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.
Возврат по PHP.net: mixed; описание обещает увеличенный Gmagick, что подтверждено на указанной сборке.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Прочитать поток RGB с известной геометрией; Получить два масштаба превью из одного оригинала.
Gmagick::minifyimageУменьшить обе стороны вдвое
PECL gmagick >= Unknown · gmagick
Gmagick::minifyimage(): GmagickБез аргументов, результат Gmagick. На чётных размерах 320×200 получаем 160×100; площадь составляет четверть исходной. Это действие над пикселями, тогда как setSize задаёт настройку чтения. Способ пересчёта отличается от простого удаления каждого второго пикселя; видимый результат сохраняется для оценки. Для произвольных нечётных размеров не обещаем правило округления без отдельной проверки; для точных сторон и фильтра подходит resizeImage. Уменьшение и последующее увеличение не восстанавливают утраченную детализацию.
Gmagick::minifyimage(): GmagickАргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.
Возврат по PHP.net: Gmagick — изменённый объект изображения.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Проверить, что подсказка чтения не является изменением размера; Получить два масштаба превью из одного оригинала.
Gmagick::resampleimageПересчитать пиксели под целевую плотность
PECL gmagick >= Unknown · gmagick
Gmagick::resampleimage(float $xResolution, float $yResolution, int $filter, float $blur): GmagickxResolution и yResolution — целевые плотности float, не требуемые пиксельные стороны. filter — int из FILTER_*, blur — float: официально больше 1 размывает, меньше 1 заостряет; это не обещание восстановления деталей. Возвращается Gmagick. При известной исходной плотности 100 px/in запрос 200 даёт 320×200→640×400, запрос 50 —160×100. Но getter плотности в этом runtime остаётся 100: для сохранения физического размера явно записываем новую плотность после операции. X и Y можно задавать различно; это меняет соотношение отсчётов по осям. Неизвестную исходную плотность наша функция отклоняет. Пустой объект даёт GmagickException.
Gmagick::resampleimage(float $xResolution, float $yResolution, int $filter, float $blur): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
xResolution | float — обязательный | Плотность по горизонтальной оси в заданных единицах. |
yResolution | float — обязательный | Плотность по вертикальной оси в заданных единицах. |
filter | int — обязательный | Константа FILTER_* алгоритма пересчёта. |
blur | float — обязательный | Фактор размытия;1.0 в наших примерах. |
Возврат по PHP.net: Gmagick — изменённый объект изображения.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Изменить число отсчётов для той же физической ширины; Собрать проверяемый маршрут печатной копии.
Gmagick::setimageresolutionЗаписать печатную плотность изображения
PECL gmagick >= Unknown · gmagick
Gmagick::setimageresolution(float $xResolution, float $yResolution): GmagickxResolution и yResolution — float, плотности по осям в текущих единицах. Результат Gmagick. Метод не создаёт дополнительные пиксели:320×200 остаётся 320×200, меняется расчётный физический размер. Перед вызовом требуется существующее изображение; это не настройка декодирования ещё не прочитанного PDF. Для изменения количества отсчётов служит resampleImage. В этой сборке после resampleImage целевую плотность приходится записать явно; программа показывает отдельно наблюдение и исправление метаданных.
Gmagick::setimageresolution(float $xResolution, float $yResolution): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
xResolution | float — обязательный | Плотность по горизонтальной оси в заданных единицах. |
yResolution | float — обязательный | Плотность по вертикальной оси в заданных единицах. |
Возврат по PHP.net: Gmagick — изменённый объект изображения.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Разделить пиксели и плотность печати; Изменить число отсчётов для той же физической ширины.
Gmagick::setimageunitsЗадать единицы для значения плотности
PECL gmagick >= Unknown · gmagick
Gmagick::setimageunits(int $resolution): Gmagickresolution — int из констант RESOLUTION_*; название параметра не означает само число пикселей на дюйм. Метод возвращает Gmagick. Задаём единицы, затем обе числовые плотности через setImageResolution. Один и тот же 320×200 при 100 px/in означает 3.2×2 дюйма, а при 100 px/cm —3.2×2 сантиметра. Не заявляйте, что смена метки единиц сама гарантированно пересчитает числовую плотность: задавайте согласованные значения явно и проверяйте записанный файл.
Gmagick::setimageunits(int $resolution): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
resolution | int — обязательный | Константа RESOLUTION_*, обозначающая единицы. |
Возврат по PHP.net: Gmagick — изменённый объект изображения.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Разделить пиксели и плотность печати; Собрать проверяемый маршрут печатной копии.
Gmagick::setsizeПередать размеры до чтения потока без заголовка
PECL gmagick >= Unknown · gmagick
Gmagick::setsize(int $columns, int $rows): Gmagickcolumns и rows — int, ширина и высота в пикселях; результат Gmagick. Официальное назначение — установить геометрию до чтения raw RGB/GRAY/CMYK. Упомянутые в тексте PHP.net COLORSPACE_* — цветовые модели, а не значения, которые надо подставлять вместо сторон; в реальном примере декодер выбирает префикс rgb: пути. Размеров недостаточно для произвольного raw: нужны модель, порядок компонентов, разрядность, байтовый порядок и размещение строк. Наш фиксированный Q16 runtime прочёл собственный interleaved RGB16 размером 32×20 из 3840 байт; RGB8 из 1920 байт дал Unexpected end-of-file. Это граница конкретной пары файла и декодера, не универсальная формула для всех raw-файлов.
Gmagick::setsize(int $columns, int $rows): Gmagick| Аргумент | Тип | Смысл |
|---|---|---|
columns | int — обязательный | Ширина данных в пикселях перед чтением. |
rows | int — обязательный | Высота данных в пикселях перед чтением. |
Возврат по PHP.net: Gmagick — изменённый объект изображения.
Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.
Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.
Два применения: Прочитать поток RGB с известной геометрией; Проверить, что подсказка чтения не является изменением размера.
Источники и обсуждения
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


