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

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

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

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

Глава 430 · После первых изображений, файлов и объектов

Gmagick: progressive JPEG, Adam7 PNG и детализация цвета

Проверить структуру записанного файла, сравнить 4:4:4/4:2:2 на цветных границах и выбрать явный рецепт экспорта.

Проверить image-настройку по настоящему JPEG

Нужно progressive JPEG, но одного успешного setter недостаточно. В этой сборке setImageInterlaceScheme(LINE) и getter согласованно возвращают LINE, однако реальный JPEG записывается baseline. На странице виден его декодированный PNG; тип кодирования доказывает SOF0 в сохранённом JPEG, а не внешний вид готовой картинки.

Декодированный JPEG: image getter обещал LINE, но сохранённый файл здесь baseline SOF0
Декодированный JPEG: image getter обещал LINE, но сохранённый файл здесь baseline SOF0

Файлы именно этого выполненного примера: Скачать настоящий baseline JPEG: image-setting.jpg. PNG выше — декодированные превью, не демонстрация порядка загрузки JPEG.

$image = new Gmagick(__DIR__ . "/encoding.ppm");
$image->setImageFormat("JPEG");
$image->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);
$setting = $image->getImageInterlaceScheme();
$image->writeImage(__DIR__ . "/image-setting.jpg");

Этот короткий пример показывает именно image-настройку. Контракт принимает int INTERLACE_* и возвращает Gmagick, getter возвращает int. В проверенном Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 значение перед записью равно LINE, после открытия JPEG — NO. Полная программа разбирает SOF0/SOF2 маленькой функцией из helper; так видно отличие состояния объекта от результата кодера. Работающий способ задания кодеру показан следующим шагом.

Проверить image-настройку по настоящему JPEGСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
$image=new Gmagick(__DIR__.'/encoding.ppm');$image->setImageDepth(8);$image->setImageFormat('JPEG');$image->setCompressionQuality(80);
$image->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);$requested=$image->getImageInterlaceScheme();
$image->writeImage(__DIR__.'/gm100-export-image-interlace-image-setting.jpg');$reopened=new Gmagick(__DIR__.'/gm100-export-image-interlace-image-setting.jpg');$actualGetter=$reopened->getImageInterlaceScheme();
$header=gmJpegHeader('gm100-export-image-interlace-image-setting.jpg');gmPng($reopened,'gm100-export-image-interlace-decoded.png');

gmReport('gm100-export-image-interlace',["gmagick.setimageinterlacescheme", "gmagick.getimageinterlacescheme"],["gm100-export-image-interlace-decoded.png"],['setting_roundtrip'=>$requested===Gmagick::INTERLACE_LINE,'saved_baseline'=>$header["progressive"]===false&&$header["sof"]===192,'reread_differs'=>$actualGetter!==$requested],$errors??[],['requested'=>$requested,'reread_getter'=>$actualGetter,'jpeg_header'=>$header],[]);
echo "image-interlace: requested=LINE saved=baseline getter-alone=insufficient\n";
Ожидаемый результат
image-interlace: requested=LINE saved=baseline getter-alone=insufficient

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: утверждать «файл progressive», потому что getter вернул LINE. Решение: проверить структуру созданного JPEG или открыть его независимым анализатором. Полная загрузка baseline и progressive может давать одинаковые пиксели, поэтому screenshot конечного изображения не подтверждает порядок появления сканов.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Записать настоящий progressive JPEG

Запишем два реальных JPEG с одинаковым качеством 80 и субдискретизацией 4:4:4: baseline и progressive. Их конечные превью могут совпадать. Отличается структура файла: SOF0 и SOF2, которая позволяет декодеру по-разному обрабатывать поступающие данные.

Финальное декодированное изображение baseline JPEG
Финальное декодированное изображение baseline JPEG
Финальное декодированное изображение progressive JPEG; порядок загрузки эта картинка не показывает
Финальное декодированное изображение progressive JPEG; порядок загрузки эта картинка не показывает

Файлы именно этого выполненного примера: Скачать настоящий baseline JPEG: baseline.jpg; Скачать настоящий progressive JPEG: progressive.jpg. PNG выше — декодированные превью, не демонстрация порядка загрузки JPEG.

$image = new Gmagick(__DIR__ . "/encoding.ppm");
$image->setImageFormat("JPEG");
$image->setCompressionQuality(80);
$image->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);
$image->setInterlaceScheme(Gmagick::INTERLACE_LINE);
$image->writeImage(__DIR__ . "/progressive.jpg");

setInterlaceScheme — отдельный существующий runtime-метод настройки Wand/кодера, подтверждённый текущим C и запуском. Он не подменяет официальную карточку setImageInterlaceScheme и не записан как новый документированный метод PHP.net. В полном сравнении обеим копиям задаётся одинаковый sampling, затем одна получает NO, другая LINE на обоих уровнях. У результата проверяется настоящий JPEG-заголовок. PNG-превью создаётся после чтения этого JPEG, а не из ещё несохранённого объекта.

Записать настоящий progressive JPEGСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/encoding.ppm');$baseline=clone $source;$progressive=clone $source;
foreach([$baseline,$progressive]as $image){$image->setImageDepth(8);$image->setImageFormat('JPEG');$image->setCompressionQuality(80);$image->setSamplingFactors([1.0,1.0,1.0]);}
$baseline->setImageInterlaceScheme(Gmagick::INTERLACE_NO);$baseline->setInterlaceScheme(Gmagick::INTERLACE_NO);
$progressive->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);$progressive->setInterlaceScheme(Gmagick::INTERLACE_LINE);
$selected=$progressive->getImageInterlaceScheme();$baseline->writeImage(__DIR__.'/gm100-export-progressive-baseline.jpg');$progressive->writeImage(__DIR__.'/gm100-export-progressive-progressive.jpg');
$a=gmJpegHeader('gm100-export-progressive-baseline.jpg');$b=gmJpegHeader('gm100-export-progressive-progressive.jpg');
gmPng(new Gmagick(__DIR__.'/gm100-export-progressive-baseline.jpg'),'gm100-export-progressive-baseline-view.png');gmPng(new Gmagick(__DIR__.'/gm100-export-progressive-progressive.jpg'),'gm100-export-progressive-progressive-view.png');

gmReport('gm100-export-progressive',["gmagick.setimageinterlacescheme", "gmagick.getimageinterlacescheme", "gmagick.setsamplingfactors"],["gm100-export-progressive-baseline-view.png", "gm100-export-progressive-progressive-view.png"],['setting_line'=>$selected===Gmagick::INTERLACE_LINE,'actual_header_modes'=>!$a["progressive"]&&$b["progressive"],'same_sampling'=>$a["sampling_factors"]===$b["sampling_factors"]],$errors??[],['baseline'=>$a,'progressive'=>$b],["Gmagick::setInterlaceScheme"]);
echo "jpeg: baseline=SOF0 progressive=SOF2 sampling=444\n";
Ожидаемый результат
jpeg: baseline=SOF0 progressive=SOF2 sampling=444

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: гарантировать, что progressive всегда меньше. Решение: измерять конкретные файлы; такой гарантии нет. Эффект постепенного появления зависит также от браузера, декодера и доставки данных. Здесь доказан формат progressive, а сетевой эксперимент с медленной загрузкой не имитируется статическими картинками.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Записать PNG Adam7 и проверить IHDR

Для схемы с резкими цветами пригодится PNG без потери пикселей. Сохраним обычный PNG и реальный Adam7. Они показывают одну и ту же конечную мишень; в IHDR у первого interlace=0, у второго 1. Этот байт относится к организации данных PNG.

Обычный PNG: IHDR interlace=0
Обычный PNG: IHDR interlace=0
Настоящий Adam7 PNG: IHDR interlace=1, конечные пиксели те же
Настоящий Adam7 PNG: IHDR interlace=1, конечные пиксели те же
$image = new Gmagick(__DIR__ . "/encoding.ppm");
$image->setImageDepth(8);
$image->setImageFormat("PNG");
$image->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);
$image->setInterlaceScheme(Gmagick::INTERLACE_LINE);
$image->writeImage(__DIR__ . "/adam7.png");

Для нашей сборки важна отдельная настройка Wand setInterlaceScheme; image-only LINE в discovery не изменил IHDR. После повторного чтения настоящего Adam7 getImageInterlaceScheme здесь вернул 0, поэтому getter не заменяет проверку заголовка. Полная программа читает сигнатуру PNG, IHDR и значение interlace, затем сравнивает пиксельные подписи декодированных файлов. Adam7 не добавляет анимацию и не меняет размер холста.

Записать PNG Adam7 и проверить IHDRСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/encoding.ppm');$plain=clone $source;$adam=clone $source;
foreach([$plain,$adam]as $image){$image->setImageDepth(8);$image->setImageFormat('PNG');}
$plain->setImageInterlaceScheme(Gmagick::INTERLACE_NO);$plain->setInterlaceScheme(Gmagick::INTERLACE_NO);
$adam->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);$adam->setInterlaceScheme(Gmagick::INTERLACE_LINE);$selected=$adam->getImageInterlaceScheme();
$plain->writeImage(__DIR__.'/gm100-export-png-interlace-plain.png');$adam->writeImage(__DIR__.'/gm100-export-png-interlace-adam7.png');
$flags=[gmPngInterlace('gm100-export-png-interlace-plain.png'),gmPngInterlace('gm100-export-png-interlace-adam7.png')];$reopened=new Gmagick(__DIR__.'/gm100-export-png-interlace-adam7.png');$reread=$reopened->getImageInterlaceScheme();

gmReport('gm100-export-png-interlace',["gmagick.setimageinterlacescheme", "gmagick.getimageinterlacescheme"],["gm100-export-png-interlace-plain.png", "gm100-export-png-interlace-adam7.png"],['selected_line'=>$selected===Gmagick::INTERLACE_LINE,'actual_ihdr_flags'=>$flags===[0,1],'pixels_identical'=>(new Gmagick(__DIR__."/gm100-export-png-interlace-plain.png"))->getImageSignature()===$reopened->getImageSignature()],$errors??[],['ihdr_interlace'=>$flags,'reread_getter'=>$reread],["Gmagick::setInterlaceScheme"]);
echo "png: plain=0 adam7=1 final-pixels=identical\n";
Ожидаемый результат
png: plain=0 adam7=1 final-pixels=identical

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: получить меньший PNG за счёт interlace. Решение: сравнить реальные размеры, а не обещать уменьшение: на нашей мишени Adam7 получился больше. Для пиксельной графики сначала выбирайте подходящий формат и требования к доставке, а затем включайте нужный порядок проходов.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Сравнить реальные JPEG 4:4:4 и 4:2:2

Тонкие красно-синие и зелёно-жёлтые полосы позволяют увидеть влияние JPEG-субдискретизации. Сохраним одинаковое качество 80, но разные sampling-настройки. В JPEG4:2:2 цветная информация по горизонтали реже, чем в 4:4:4, поэтому цветные границы нашей мишени меняются заметнее.

Исходник: резкие цветные полосы и отдельные чёрно-белые детали
Исходник: резкие цветные полосы и отдельные чёрно-белые детали
Декодированный JPEG 4:4:4: цветные границы сохраняются лучше на этой мишени
Декодированный JPEG 4:4:4: цветные границы сохраняются лучше на этой мишени
Декодированный JPEG 4:2:2: цвет усреднён по горизонтали, полосы меняются
Декодированный JPEG 4:2:2: цвет усреднён по горизонтали, полосы меняются

Файлы именно этого выполненного примера: Скачать настоящий baseline JPEG: 444.jpg; Скачать настоящий baseline JPEG: 422.jpg. PNG выше — декодированные превью, не демонстрация порядка загрузки JPEG.

$image = new Gmagick(__DIR__ . "/encoding.ppm");
$image->setImageFormat("JPEG");
$image->setCompressionQuality(80);
$image->setSamplingFactors([2.0, 1.0, 1.0]);
$configured = $image->getSamplingFactors();
$image->writeImage(__DIR__ . "/sample422.jpg");

PHP.net описывает массив float по цветовым компонентам в RGB-порядке. Нельзя механически перенести строки «2x2» из Imagick: этот Gmagick setter преобразует элементы в double. В проверенной сборке массив[1,1,1] дал SOF-факторы 1×1,1×1,1×1 —4:4:4; [2,1,1] дал 2×1,1×1,1×1 —4:2:2. Это не 4:2:0. Реальные JPEG-компоненты относятся к кодированному представлению; изменение sampling не равнозначно смене colorspace входа.

Сравнить реальные JPEG 4:4:4 и 4:2:2Самостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/encoding.ppm');$full=clone $source;$reduced=clone $source;
foreach([$full,$reduced]as $image){$image->setImageDepth(8);$image->setImageFormat('JPEG');$image->setCompressionQuality(80);}
$full->setSamplingFactors([1.0,1.0,1.0]);$reduced->setSamplingFactors([2.0,1.0,1.0]);$configured=[$full->getSamplingFactors(),$reduced->getSamplingFactors()];
$full->writeImage(__DIR__.'/gm100-export-sampling-444.jpg');$reduced->writeImage(__DIR__.'/gm100-export-sampling-422.jpg');$a=gmJpegHeader('gm100-export-sampling-444.jpg');$b=gmJpegHeader('gm100-export-sampling-422.jpg');
gmPng($source,'gm100-export-sampling-source.png');gmPng(new Gmagick(__DIR__.'/gm100-export-sampling-444.jpg'),'gm100-export-sampling-444-view.png');gmPng(new Gmagick(__DIR__.'/gm100-export-sampling-422.jpg'),'gm100-export-sampling-422-view.png');

gmReport('gm100-export-sampling',["gmagick.setsamplingfactors", "gmagick.getsamplingfactors"],["gm100-export-sampling-source.png", "gm100-export-sampling-444-view.png", "gm100-export-sampling-422-view.png"],['actual_444'=>$a["sampling_factors"]===[[1,1],[1,1],[1,1]],'actual_422'=>$b["sampling_factors"]===[[2,1],[1,1],[1,1]],'decoded_pixels_differ'=>(new Gmagick(__DIR__."/gm100-export-sampling-444.jpg"))->getImageSignature()!==(new Gmagick(__DIR__."/gm100-export-sampling-422.jpg"))->getImageSignature()],$errors??[],['getters'=>$configured,'full'=>$a,'reduced'=>$b],[]);
echo "sampling: numeric111=444 numeric211=422 confirmed=SOF\n";
Ожидаемый результат
sampling: numeric111=444 numeric211=422 confirmed=SOF

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: считать число 80 единственной характеристикой качества JPEG. Решение: вместе с качеством фиксировать sampling и оценивать важные детали. Для логотипа или схемы с мелкими цветными линиями полезно сравнить PNG без потерь и JPEG4:4:4; для фотографии выбор зависит от содержания и измеренного размера.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Отделить настройки sampling от заголовка файла

Getter sampling не оказался паспортом JPEG. На новом изображении он вернул[], после setSamplingFactors([2,1,1]) — индексированный массив[2,1], а после открытия сохранённого JPEG снова[]. При этом SOF файла содержит три компонента и подтверждает 4:2:2.

JPEG содержит три SOF-компонента, хотя getter после открытия вернул пустой массив
JPEG содержит три SOF-компонента, хотя getter после открытия вернул пустой массив

Файлы именно этого выполненного примера: Скачать настоящий baseline JPEG: output.jpg. PNG выше — декодированные превью, не демонстрация порядка загрузки JPEG.

$image = new Gmagick(__DIR__ . "/encoding.ppm");
$image->setSamplingFactors([2.0, 1.0, 1.0]);
$configured = $image->getSamplingFactors();
$image->setImageFormat("JPEG");
$image->writeImage(__DIR__ . "/output.jpg");
$loaded = new Gmagick(__DIR__ . "/output.jpg");
$afterRead = $loaded->getSamplingFactors();

Официальный текст getter обещает associative array с горизонтальными и вертикальными коэффициентами; текущий C формирует обычный индексированный массив float. Наблюдаемая длина и пустой readback показаны явно в JSON. Поэтому пользовательский отчёт хранит отдельно requested/configured и фактические sampling_factors из SOF. Пустой getter после чтения не означает, что в JPEG отсутствуют коэффициенты выборки.

Отделить настройки sampling от заголовка файлаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
$image=new Gmagick(__DIR__.'/encoding.ppm');$before=$image->getSamplingFactors();$ret=$image->setSamplingFactors([2.0,1.0,1.0]);$configured=$image->getSamplingFactors();
$image->setImageDepth(8);$image->setImageFormat('JPEG');$image->setCompressionQuality(80);$image->writeImage(__DIR__.'/gm100-export-sampling-readback-output.jpg');
$loaded=new Gmagick(__DIR__.'/gm100-export-sampling-readback-output.jpg');$readback=$loaded->getSamplingFactors();$header=gmJpegHeader('gm100-export-sampling-readback-output.jpg');gmPng($loaded,'gm100-export-sampling-readback-decoded.png');

gmReport('gm100-export-sampling-readback',["gmagick.setsamplingfactors", "gmagick.getsamplingfactors"],["gm100-export-sampling-readback-decoded.png"],['same_object'=>$ret===$image,'getter_shape_observed'=>$before===[]&&$configured===[2.0,1.0]&&$readback===[],'file_contains_422'=>$header["sampling_factors"]===[[2,1],[1,1],[1,1]]],$errors??[],['before'=>$before,'configured'=>$configured,'reopened'=>$readback,'actual_file'=>$header],[]);
echo "sampling-readback: configured=2-values reopened=empty file=422\n";
Ожидаемый результат
sampling-readback: configured=2-values reopened=empty file=422

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: восстановить параметры чужого JPEG для повторного экспорта. Решение: прочитать реальную структуру или использовать проверенный анализатор, затем задать новый рецепт явно. Не переносить [] в новый экспорт под предположением, что это сохранит старую субдискретизацию.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Выбрать экспорт для цветной графики и веб-превью

Сервису удобнее принимать смысловые имена пресетов, чем произвольные наборы констант. sharp сохраняет цветные детали через 4:4:4, compact использует 4:2:2; оба создают настоящий progressive JPEG. Названия — наш выбор интерфейса, а реальные свойства записываются в отчёт.

sharp: progressive JPEG с реальной субдискретизацией 4:4:4
sharp: progressive JPEG с реальной субдискретизацией 4:4:4
compact: progressive JPEG с реальной субдискретизацией 4:2:2; сравните цветные полосы
compact: progressive JPEG с реальной субдискретизацией 4:2:2; сравните цветные полосы

Файлы именно этого выполненного примера: Скачать настоящий progressive JPEG: sharp.jpg; Скачать настоящий progressive JPEG: compact.jpg. PNG выше — декодированные превью, не демонстрация порядка загрузки JPEG.

$source = new Gmagick(__DIR__ . "/encoding.ppm");
$sharp = exportJpeg($source, "sharp", "sharp.jpg");
$compact = exportJpeg($source, "compact", "compact.jpg");
echo $sharp["actual"]["progressive"] ? "progressive" : "baseline";

Функция exportJpeg полностью приведена ниже. Белый список допускает два пресета; clone защищает исходник от настроек соседнего варианта. Далее явно задаются формат, глубина, качество, sampling и оба уровня interlace, выполняется запись и разбирается SOF. Никакой метод не вызывается по произвольной пользовательской строке. Слово compact здесь обозначает рецепт, а не обещание, что каждый конкретный файл окажется меньше.

Выбрать экспорт для цветной графики и веб-превьюСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/gm100-export-fixture.php';
gmRestore();
function exportJpeg(Gmagick $source,string $preset,string $file):array {
    if(!in_array($preset,['sharp','compact'],true))throw new InvalidArgumentException('Choose sharp or compact');
    $copy=clone $source;$copy->setImageDepth(8);$copy->setImageFormat('JPEG');$copy->setCompressionQuality(80);
    $copy->setSamplingFactors($preset==='sharp'?[1.0,1.0,1.0]:[2.0,1.0,1.0]);$factors=$copy->getSamplingFactors();
    $copy->setImageInterlaceScheme(Gmagick::INTERLACE_LINE);$copy->setInterlaceScheme(Gmagick::INTERLACE_LINE);$setting=$copy->getImageInterlaceScheme();
    $copy->writeImage(__DIR__.'/'.$file);return ['preset'=>$preset,'setting'=>$setting,'configured'=>$factors,'actual'=>gmJpegHeader($file)];
}
$source=new Gmagick(__DIR__.'/encoding.ppm');$sharp=exportJpeg($source,'sharp','gm100-export-export-policy-sharp.jpg');$compact=exportJpeg($source,'compact','gm100-export-export-policy-compact.jpg');
gmPng(new Gmagick(__DIR__.'/gm100-export-export-policy-sharp.jpg'),'gm100-export-export-policy-sharp-view.png');gmPng(new Gmagick(__DIR__.'/gm100-export-export-policy-compact.jpg'),'gm100-export-export-policy-compact-view.png');
$errors=['unknown_preset'=>gmTry(fn()=>exportJpeg($source,'other','unused.jpg'))];

gmReport('gm100-export-export-policy',["gmagick.setsamplingfactors", "gmagick.getsamplingfactors", "gmagick.setimageinterlacescheme", "gmagick.getimageinterlacescheme"],["gm100-export-export-policy-sharp-view.png", "gm100-export-export-policy-compact-view.png"],['both_progressive'=>$sharp["actual"]["progressive"]&&$compact["actual"]["progressive"],'different_sampling'=>$sharp["actual"]["sampling_factors"]!==$compact["actual"]["sampling_factors"]],$errors??[],['sharp'=>$sharp,'compact'=>$compact],["Gmagick::setInterlaceScheme"]);
echo "export: sharp=progressive444 compact=progressive422 unknown=rejected\n";
Ожидаемый результат
export: sharp=progressive444 compact=progressive422 unknown=rejected

Распакуйте архив и выполните php example.php. Вложенные .b64 содержат все входы; helper проверяет SHA256 и восстанавливает PPM. gmPng сохраняет копию в PNG8. gmJpegHeader читает SOF0/SOF2 и коэффициенты компонентов из настоящего JPEG, gmPngInterlace читает IHDR. metrics.json содержит результаты и проверки. JPEG/PNG и квитанции появятся после выполнения; исходные файлы не берутся из внешней папки.

Упражнение: добавить режим для маленькой диаграммы с текстом. Решение: сначала сравнить выход PNG без потерь с JPEG-пресетами на её деталях, затем добавить отдельное осмысленное правило. Конечные PNG-превью полезны для оценки искажений, но не показывают progressive-проходы загрузки.

Связанные шаги: имена и путь записи, кодирование JPEG/PNG, окружение и рабочий объект, качество, метаданные и глубина файла.

Из реальной задачи разработчика

How can I save a JPG image in 4:2:0 colorspace with Imagick?. Нужно получить JPEG с меньшей цветовой выборкой; попытка менять colorspace испортила цвета. Разделяем преобразование пространства и JPEG sampling. Для текущего Gmagick используем массивы чисел, проверяем факторы каждого SOF-компонента и честно называем [2,1,1] схемой4:2:2 в этой сборке. Показываем цветные границы реальных декодированных файлов, не переносим строки Imagick или обещания4:2:0 без проверки.

Из реальной задачи разработчика

Why doesn't setImageInterlaceScheme() make a jpeg progressive?. Автор Gmagick выставил image interlace и получил подтверждение getter, но JPEG не стал progressive. Наше решение отдельно показывает состояние текущего изображения и настройку кодера Wand. Программа сохраняет настоящий baseline и progressive JPEG, проверяет SOF0/SOF2 и даёт ссылки на реальные файлы. Работающий setInterlaceScheme назван отдельным runtime API, без подмены официальной карточки image-setter.

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

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

Gmagick::getimageinterlaceschemeПрочитать interlace-состояние текущего изображения

PECL gmagick >= Unknown · gmagick

Gmagick::getimageinterlacescheme(): int

Без аргументов возвращает int — схему interlace текущего изображения. Сравнивайте с именованными INTERLACE_*, а не считайте число готовым описанием структуры файла. На нашей сборке getter после image-setter возвращает LINE, но JPEG всё ещё может быть baseline; после чтения настоящего Adam7 PNG получено 0. Поэтому вывод о progressive/Adam7 делается по реальному JPEG SOF или PNG IHDR. Getter полезен для наблюдения состояния объекта, но не заменяет проверку выполненного экспорта.

Gmagick::getimageinterlacescheme(): int

Параметров нет: вызов записывается с пустыми скобками.

Официальная ошибка — GmagickException. Дополнительно PHP проверяет типы аргументов; прикладные ограничения пути и пресета в наших функциях дают InvalidArgumentException до вызова библиотеки. Не смешивайте эти уровни проверки.

Два самостоятельных применения: Проверить image-настройку по настоящему JPEG; Записать PNG Adam7 и проверить IHDR.

Отметка PHP.net: PECL gmagick >= Unknown. Unknown не сообщает известную минимальную версию. Наблюдения относятся к PHP 8.3.6/Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 Q16; поведение экспортного кодера подтверждается реальными файлами.

Gmagick::getsamplingfactorsПрочитать sampling-настройку, не подменяя анализ JPEG

PECL gmagick >= Unknown · gmagick

Gmagick::getsamplingfactors(): array

Без аргументов возвращает array. Официальное описание говорит об ассоциативном массиве горизонтальных и вертикальных коэффициентов; текущий C добавляет числа double с последовательными индексами. В наших программах после [2,1,1] получено [2.0,1.0], а после открытия JPEG — пустой массив. При этом сам файл содержит три компонента SOF и реальную схему 4:2:2. Разделяйте configured getter и фактические sampling_factors в заголовке; отсутствие значений в getter не означает отсутствие субдискретизации в файле.

Gmagick::getsamplingfactors(): array

Параметров нет: вызов записывается с пустыми скобками.

Официальная ошибка — GmagickException. Дополнительно PHP проверяет типы аргументов; прикладные ограничения пути и пресета в наших функциях дают InvalidArgumentException до вызова библиотеки. Не смешивайте эти уровни проверки.

Два самостоятельных применения: Сравнить реальные JPEG 4:4:4 и 4:2:2; Отделить настройки sampling от заголовка файла.

Отметка PHP.net: PECL gmagick >= Unknown. Unknown не сообщает известную минимальную версию. Наблюдения относятся к PHP 8.3.6/Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 Q16; поведение экспортного кодера подтверждается реальными файлами.

Gmagick::setimageinterlaceschemeЗадать interlace для изображения и проверить экспорт

PECL gmagick >= Unknown · gmagick

Gmagick::setimageinterlacescheme(int $interlace): Gmagick

Обязательный int interlace выбирается из Gmagick::INTERLACE_*. Метод устанавливает схему текущего изображения и возвращает Gmagick. Среди констант есть UNDEFINED, NO, LINE, PLANE и PARTITION; их смысл при записи зависит от формата и кодера. В Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 image-only LINE/PLANE не сделали JPEG progressive, хотя getter прочитал настройку. Рабочие программы дополнительно вызывают подтверждённый runtime-метод Wand setInterlaceScheme(LINE), затем проверяют настоящий файл. Эти два API показаны раздельно; наличие image-настройки не объявляется доказательством успешного кодирования.

Gmagick::setimageinterlacescheme(int $interlace): Gmagick
ПараметрТип и обязательностьНазначение
$interlaceint; обязательныйОдна из именованных констант Gmagick::INTERLACE_*; результат кодирования проверяется отдельно.

Официальная ошибка — GmagickException. Дополнительно PHP проверяет типы аргументов; прикладные ограничения пути и пресета в наших функциях дают InvalidArgumentException до вызова библиотеки. Не смешивайте эти уровни проверки.

Два самостоятельных применения: Проверить image-настройку по настоящему JPEG; Записать настоящий progressive JPEG.

Отметка PHP.net: PECL gmagick >= Unknown. Unknown не сообщает известную минимальную версию. Наблюдения относятся к PHP 8.3.6/Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 Q16; поведение экспортного кодера подтверждается реальными файлами.

Gmagick::setsamplingfactorsЗадать числовые коэффициенты и проверить SOF

PECL gmagick >= Unknown · gmagick

Gmagick::setsamplingfactors(array $factors): Gmagick

Принимает обязательный array factors. PHP.net описывает массив float для цветовых компонентов в RGB-порядке; возвращает Gmagick. Текущий C преобразует элементы в double, поэтому строки вида «2x2» из примеров Imagick здесь не являются переносимым рецептом. Наблюдаемые числовые массивы: [1.0,1.0,1.0] создаёт JPEG с факторами 1×1,1×1,1×1 (4:4:4), [2.0,1.0,1.0] —2×1,1×1,1×1 (4:2:2). Не называйте второй 4:2:0. Полные программы проверяют настоящий заголовок и показывают декодированные цветные границы. Sampling меняет пространственную детализацию цветовых компонент JPEG, а не заменяет преобразование colorspace.

Gmagick::setsamplingfactors(array $factors): Gmagick
ПараметрТип и обязательностьНазначение
$factorsarray; обязательныйМассив float; официальный текст описывает компоненты в RGB-порядке. Реальное отображение в JPEG проверяется по SOF.

Официальная ошибка — GmagickException. Дополнительно PHP проверяет типы аргументов; прикладные ограничения пути и пресета в наших функциях дают InvalidArgumentException до вызова библиотеки. Не смешивайте эти уровни проверки.

Два самостоятельных применения: Сравнить реальные JPEG 4:4:4 и 4:2:2; Выбрать экспорт для цветной графики и веб-превью.

Отметка PHP.net: PECL gmagick >= Unknown. Unknown не сообщает известную минимальную версию. Наблюдения относятся к PHP 8.3.6/Gmagick 2.0.6RC1/GraphicsMagick 1.3.42 Q16; поведение экспортного кодера подтверждается реальными файлами.

Источники и обсуждения

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

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

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

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