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

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

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

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

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

Gmagick: цветовые пространства, каналы и глубина

Разделить компоненты, сравнить серый и двухцветный тип, ограничить глубину и проверить цветовой маршрут.

Получить серую версию цветного оригинала

Продолжаем первые изображения Gmagick и цвета, каналы GmagickPixel и гистограммы. Нужен Gmagick для GraphicsMagick; Imagick — другое расширение. Проверенное окружение: PHP8.3.6, Gmagick2.0.6RC1, GraphicsMagick1.3.42 Q16. Синтаксис объектов, стрелки и констант разбирается рядом с вызовами; базовые понятия доступны в главах о переменных, о массивах и об объектах.

Для чёрно-белой карточки нужна серая версия цветного рисунка. Сначала сравним оригинал и результат, сохранив одинаковые 320×200 пикселей. Наш вход — собственный плавный RGB-градиент с 57 502 цветами: на нём видно потерю цветовой информации, а не только смену подписи в свойствах.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Серая версия после setImageColorspace(COLORSPACE_GRAY), сохранённая в PNG8
Серая версия после setImageColorspace(COLORSPACE_GRAY), сохранённая в PNG8 — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$space = $image->getImageColorspace();
$image->setImageColorspace(Gmagick::COLORSPACE_GRAY);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/gray.png');

Переменная $image хранит объект прочитанного изображения. getImageColorspace() возвращает числовую константу, поэтому её сравнивают с Gmagick::COLORSPACE_RGB, а не строкой «RGB». Вызов setImageColorspace получает константу GRAY. На этом Gmagick он действительно преобразует пиксели; одноимённые методы других расширений могут иметь другой смысл. PNG выбирается отдельно, потому что цветовое пространство и формат файла отвечают на разные вопросы.

Получить серую версию цветного оригиналаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/spectrum.ppm');
$sourceSpace=$source->getImageColorspace();
$gray=clone $source;$same=$gray->setImageColorspace(Gmagick::COLORSPACE_GRAY)===$gray;
$graySpace=$gray->getImageColorspace();$grayType=$gray->getImageType();
$source->setImageDepth(8);
$source->setImageFormat('PNG');
$source->writeImage(__DIR__.'/gm99-spectrum-source.png');
$gray->setImageDepth(8);
$gray->setImageFormat('PNG');
$gray->writeImage(__DIR__.'/gm99-space-gray.png');

gmReport('gm99-space-gray',["gmagick.construct", "gmagick.getimagecolorspace", "gmagick.setimagecolorspace", "gmagick.getimagetype", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-spectrum-source.png", "gm99-space-gray.png"],
    ['source_rgb'=>$sourceSpace===Gmagick::COLORSPACE_RGB,'target_gray'=>$graySpace===Gmagick::COLORSPACE_GRAY&&$grayType===Gmagick::IMGTYPE_GRAYSCALE,'same_object'=>$same,'size_gm99_spectrum_source'=>gmInspect('gm99-spectrum-source.png')['width']===320&&gmInspect('gm99-spectrum-source.png')['height']===200,'size_gm99_space_gray'=>gmInspect('gm99-space-gray.png')['width']===320&&gmInspect('gm99-space-gray.png')['height']===200],
    $errors ?? [], ['source_space'=>$sourceSpace,'converted_space'=>$graySpace,'converted_type'=>$grayType]);
echo "gm99-spectrum-source.png 320x200 gm99-space-gray.png 320x200\n";
Ожидаемый результат
gm99-spectrum-source.png 320x200 gm99-space-gray.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-spectrum-source.png 320x200 gm99-space-gray.png 320x200

Полная программа сохраняет обе версии и читает тип перед записью. После повторного чтения серого PNG данная сборка может сообщить RGB, хотя тип остаётся Grayscale и все три компонента каждого пикселя равны. Поэтому для требований «только серые пиксели» одного идентификатора пространства мало. Цветовые профили и преобразование для определённого принтера этим простым вызовом не подтверждаются.

Все входы собственные и входят в ZIP побайтно в .b64. После php example.php помощник gm-fixture.php восстанавливает обычные product.ppm, spectrum.ppm, palette.ppm и два raw-файла рядом. Он проверяет данные и записывает metrics.json, но не выполняет изучаемые преобразования. У spectrum.ppm формула RGB8: R=floor(255×x/319), G=floor(255×y/199), B=floor(255×(x+y)/518), где x=0…319, y=0…199. Поэтому переходы воспроизводимы, а не получены из чужой фотографии. Короткие фрагменты предполагают, что нужный файл уже лежит рядом.

Посмотреть три составляющие одного изображения

Иногда нужно понять, какая составляющая создаёт детали изображения: например, сравнить канал с сильным контрастом и канал с помехами. Три серых результата ниже показывают численные значения R, G и B. Они не окрашены красным, зелёным и синим: светлый пиксель означает большое значение выбранного компонента.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Красный канал: горизонтальное изменение яркости
Красный канал: горизонтальное изменение яркости — 320 × 200 px.
Зелёный канал: вертикальное изменение яркости
Зелёный канал: вертикальное изменение яркости — 320 × 200 px.
Синий канал: диагональное изменение яркости
Синий канал: диагональное изменение яркости — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$red = clone $image;
$red->separateImageChannel(Gmagick::CHANNEL_RED);
$range = $red->getImageExtrema();
echo $range['min'], ' .. ', $range['max'], "\n";

clone создаёт независимую копию; $image сохраняет исходные компоненты. separateImageChannel переносит выбранный канал в серое представление. CHANNEL_RED задаёт компонент изображения, а COLOR_RED в GmagickPixel читает отдельное значение цвета — это разные группы констант. Массив $range имеет ключи min и max; вывод на стенде Q16 — «0 .. 65535». Q16 описывает внутренний диапазон, даже когда файл содержит 8-битные значения.

Посмотреть три составляющие одного изображенияСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/spectrum.ppm');
$red=clone $source;$red->separateImageChannel(Gmagick::CHANNEL_RED);
$green=clone $source;$green->separateImageChannel(Gmagick::CHANNEL_GREEN);
$blue=clone $source;$blue->separateImageChannel(Gmagick::CHANNEL_BLUE);
$extrema=['red'=>$red->getImageExtrema(),'green'=>$green->getImageExtrema(),'blue'=>$blue->getImageExtrema()];
$red->setImageDepth(8);
$red->setImageFormat('PNG');
$red->writeImage(__DIR__.'/gm99-channel-red.png');
$green->setImageDepth(8);
$green->setImageFormat('PNG');
$green->writeImage(__DIR__.'/gm99-channel-green.png');
$blue->setImageDepth(8);
$blue->setImageFormat('PNG');
$blue->writeImage(__DIR__.'/gm99-channel-blue.png');

gmReport('gm99-channel-views',["gmagick.construct", "gmagick.separateimagechannel", "gmagick.getimageextrema", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-channel-red.png", "gm99-channel-green.png", "gm99-channel-blue.png"],
    ['full_range'=>$extrema['red']===['min'=>0,'max'=>65535]&&$extrema['green']===$extrema['red']&&$extrema['blue']===$extrema['red'],'size_gm99_channel_red'=>gmInspect('gm99-channel-red.png')['width']===320&&gmInspect('gm99-channel-red.png')['height']===200,'size_gm99_channel_green'=>gmInspect('gm99-channel-green.png')['width']===320&&gmInspect('gm99-channel-green.png')['height']===200,'size_gm99_channel_blue'=>gmInspect('gm99-channel-blue.png')['width']===320&&gmInspect('gm99-channel-blue.png')['height']===200],
    $errors ?? [], $extrema);
echo "gm99-channel-red.png 320x200 gm99-channel-green.png 320x200 gm99-channel-blue.png 320x200\n";
Ожидаемый результат
gm99-channel-red.png 320x200 gm99-channel-green.png 320x200 gm99-channel-blue.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-channel-red.png 320x200 gm99-channel-green.png 320x200 gm99-channel-blue.png 320x200

В полной программе все три копии создаются из одного оригинала. У красного здесь горизонтальный переход, у зелёного вертикальный, у синего диагональный: это следует из формулы собственного входа. Извлекать следующий канал из уже серой копии было бы ошибкой. Экстремумы помогают обнаружить диапазон, но не заменяют гистограмму и сами не измеряют читаемость документа.

Сократить уровни одного канала до двух и четырёх бит

Для ограниченного дисплея или контролируемой пробы нужно сократить точность одной составляющей. Ниже меняется только красный: два бита оставляют четыре уровня, четыре бита — шестнадцать. Сравните цветные полосы с плавным исходником; число пикселей остаётся прежним.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Красный канал: четыре уровня после depth=2; остальные компоненты сохранены
Красный канал: четыре уровня после depth=2; остальные компоненты сохранены — 320 × 200 px.
Красный канал: шестнадцать уровней после depth=4
Красный канал: шестнадцать уровней после depth=4 — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$before = $image->getImageChannelDepth(Gmagick::CHANNEL_RED);
$image->setImageChannelDepth(Gmagick::CHANNEL_RED, 2);
$after = $image->getImageChannelDepth(Gmagick::CHANNEL_RED);
echo $before, ' -> ', $after, "\n";

Вывод «8 -> 2» относится к красному каналу. Число возможных уровней равно 2 в степени числа бит:2²=4. Это не четыре цвета всей картинки: зелёная и синяя составляющие по-прежнему имеют свои значения. В полной программе центр меняется с RGB127,128,127 на 85,128,127, а при четырёх битах —119,128,127. Проверки касаются фактических PNG, а не только setter.

Сократить уровни одного канала до двух и четырёх битСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/spectrum.ppm');$originalDepth=$source->getImageChannelDepth(Gmagick::CHANNEL_RED);
$two=clone $source;$two->setImageChannelDepth(Gmagick::CHANNEL_RED,2);
$four=clone $source;$four->setImageChannelDepth(Gmagick::CHANNEL_RED,4);
$depths=[$two->getImageChannelDepth(Gmagick::CHANNEL_RED),$four->getImageChannelDepth(Gmagick::CHANNEL_RED)];
$errors=['type'=>gmTry(fn()=>$source->setImageChannelDepth(Gmagick::CHANNEL_RED,[]))];
$two->setImageDepth(8);
$two->setImageFormat('PNG');
$two->writeImage(__DIR__.'/gm99-red-depth2.png');
$four->setImageDepth(8);
$four->setImageFormat('PNG');
$four->writeImage(__DIR__.'/gm99-red-depth4.png');

gmReport('gm99-channel-depth',["gmagick.construct", "gmagick.getimagechanneldepth", "gmagick.setimagechanneldepth", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-red-depth2.png", "gm99-red-depth4.png"],
    ['depths'=>$originalDepth===8&&$depths===[2,4],'type_rejected'=>$errors['type']['class']==='TypeError','size_gm99_red_depth2'=>gmInspect('gm99-red-depth2.png')['width']===320&&gmInspect('gm99-red-depth2.png')['height']===200,'size_gm99_red_depth4'=>gmInspect('gm99-red-depth4.png')['width']===320&&gmInspect('gm99-red-depth4.png')['height']===200],
    $errors ?? [], ['original'=>$originalDepth,'after'=>$depths]);
echo "gm99-red-depth2.png 320x200 gm99-red-depth4.png 320x200\n";
Ожидаемый результат
gm99-red-depth2.png 320x200 gm99-red-depth4.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-red-depth2.png 320x200 gm99-red-depth4.png 320x200

В разделе параметров PHP.net для getImageChannelDepth есть опечатка «нет параметров», но сигнатура, реализация и выполняемый код требуют CHANNEL_*. Массив вместо целого depth даёт TypeError. Уменьшение точности необратимо для потерянных промежуточных значений: последующее назначение 8 бит не восстановит исходный плавный переход.

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

Серый документ и двухцветный документ решают разные задачи. Полутона удобны для фотографии, а строго чёрное/белое может потребоваться простому устройству вывода. Рядом показаны оба результата на одном градиенте, чтобы потеря переходов была видна до выбора метода.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Тип Grayscale сохраняет множество серых уровней
Тип Grayscale сохраняет множество серых уровней — 320 × 200 px.
Тип Bilevel оставляет чёрное и белое
Тип Bilevel оставляет чёрное и белое — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$image->setImageType(Gmagick::IMGTYPE_BILEVEL);
$type = $image->getImageType();
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/two-colors.png');

IMGTYPE_BILEVEL — именованная константа типа; это не строка формата и не флаг «один байт». Для альтернативы полная программа вызывает IMGTYPE_GRAYSCALE в отдельной копии. getImageType возвращает потенциальный тип объекта; для сохранённой двухцветной версии дополнительно читается число цветов —2. Таким образом, полезное требование проверяется в выходном файле.

Выбрать серый или двухцветный вариант для печатиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source=new Gmagick(__DIR__.'/spectrum.ppm');$sourceType=$source->getImageType();
$gray=clone $source;$gray->setImageType(Gmagick::IMGTYPE_GRAYSCALE);
$binary=clone $source;$binary->setImageType(Gmagick::IMGTYPE_BILEVEL);
$types=[$gray->getImageType(),$binary->getImageType()];
$gray->setImageDepth(8);
$gray->setImageFormat('PNG');
$gray->writeImage(__DIR__.'/gm99-type-gray.png');
$binary->setImageDepth(8);
$binary->setImageFormat('PNG');
$binary->writeImage(__DIR__.'/gm99-type-bilevel.png');
$read=new Gmagick(__DIR__.'/gm99-type-bilevel.png');$colors=$read->getImageColors();

gmReport('gm99-image-types',["gmagick.construct", "gmagick.getimagetype", "gmagick.setimagetype", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.getimagecolors"],["gm99-type-gray.png", "gm99-type-bilevel.png"],
    ['types'=>$types===[Gmagick::IMGTYPE_GRAYSCALE,Gmagick::IMGTYPE_BILEVEL],'two_colors'=>$colors===2,'size_gm99_type_gray'=>gmInspect('gm99-type-gray.png')['width']===320&&gmInspect('gm99-type-gray.png')['height']===200,'size_gm99_type_bilevel'=>gmInspect('gm99-type-bilevel.png')['width']===320&&gmInspect('gm99-type-bilevel.png')['height']===200],
    $errors ?? [], ['source_type'=>$sourceType,'result_types'=>$types,'saved_binary_colors'=>$colors]);
echo "gm99-type-gray.png 320x200 gm99-type-bilevel.png 320x200\n";
Ожидаемый результат
gm99-type-gray.png 320x200 gm99-type-bilevel.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-type-gray.png 320x200 gm99-type-bilevel.png 320x200

SetImageType может менять данные. Нельзя выбрать Bilevel и ожидать сохранения мягких теней. Для палитры из заданного числа цветов подходит quantizeImage, для конкретных фирменных красок — mapImage. У файла с несколькими цветами getter после чтения PNG может показывать TrueColor; тип и набор уникальных значений не являются одним и тем же свойством.

Сделать проверяемую пробу выбранного канала

В обработке серии изображений удобно одинаково получать пробу выбранного канала. Функция принимает исходник, канал и точность, оставляет оригинал нетронутым и возвращает серый результат. На нашем примере остаются четыре ступени красной составляющей.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Красная составляющая после ограничения до двух бит снова представлена серыми уровнями
Красная составляющая после ограничения до двух бит снова представлена серыми уровнями — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$image->separateImageChannel(Gmagick::CHANNEL_RED);
$image->setImageChannelDepth(Gmagick::CHANNEL_RED, 2);
$image->separateImageChannel(Gmagick::CHANNEL_RED);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/proof.png');

Первое выделение превращает исходный R в серый растр. Setter глубины изменяет только красную составляющую этого растра, поэтому второй separateImageChannel снова распространяет её в серое представление. В полной функции перед ограничением явно задаётся тип Grayscale. function объявляет channelProof, параметры выбирают входные данные, return возвращает копию. Проверка if допускает 1…8 бит как правило нашей пробы.

Сделать проверяемую пробу выбранного каналаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
function channelProof(Gmagick $source,int $channel,int $bits):Gmagick {
    if($bits<1||$bits>8)throw new InvalidArgumentException('Proof depth must be in 1..8');
    $copy=clone $source;$copy->separateImageChannel($channel);
    $copy->setImageType(Gmagick::IMGTYPE_GRAYSCALE);
    $copy->setImageChannelDepth(Gmagick::CHANNEL_RED,$bits);
    $copy->separateImageChannel(Gmagick::CHANNEL_RED);
    return $copy;
}
$source=new Gmagick(__DIR__.'/spectrum.ppm');$proof=channelProof($source,Gmagick::CHANNEL_RED,2);
$depth=$proof->getImageChannelDepth(Gmagick::CHANNEL_RED);$range=$proof->getImageExtrema();
$errors=['range'=>gmTry(fn()=>channelProof($source,Gmagick::CHANNEL_RED,0)),'empty'=>gmTry(fn()=>(new Gmagick())->getImageExtrema())];
$proof->setImageDepth(8);
$proof->setImageFormat('PNG');
$proof->writeImage(__DIR__.'/gm99-channel-proof.png');

gmReport('gm99-channel-proof',["gmagick.construct", "gmagick.separateimagechannel", "gmagick.setimagetype", "gmagick.setimagechanneldepth", "gmagick.getimagechanneldepth", "gmagick.getimageextrema", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-channel-proof.png"],
    ['depth_two'=>$depth===2,'full_range'=>$range===['min'=>0,'max'=>65535],'bad_range'=>$errors['range']['class']==='InvalidArgumentException','empty_rejected'=>$errors['empty']['class']==='GmagickException','size_gm99_channel_proof'=>gmInspect('gm99-channel-proof.png')['width']===320&&gmInspect('gm99-channel-proof.png')['height']===200],
    $errors ?? [], ['depth'=>$depth,'extrema'=>$range]);
echo "gm99-channel-proof.png 320x200\n";
Ожидаемый результат
gm99-channel-proof.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-channel-proof.png 320x200

Ноль бит отвергается нашей InvalidArgumentException. Пустой Gmagick при чтении extrema даёт исключение библиотеки; это другой отказ, и он не маскируется словом «неверная глубина». Для полноценного контроля контраста можно дополнить пробу гистограммой. Здесь диапазон 0…65535 сохраняется, хотя промежуточных уровней стало меньше: одинаковые экстремумы не означают одинаковую картинку.

Обнаружить изменение цвета при неподходящем маршруте экспорта

Перед отправкой в печать легко случайно провести веб-изображение через неподходящий маршрут. Покажем такое последствие явно: переход в CMYK и затем сохранение PNG на этом runtime заметно затемняет градиент. Этот результат нужен как предупреждение о выборе процесса, а не как обещанная цветопроба.

Собственный RGB-градиент: 57 502 различных цвета
Собственный RGB-градиент: 57 502 различных цвета — 320 × 200 px.
Фактический PNG после перехода RGB→CMYK в этой сборке: заметное потемнение, не цветопроба типографии
Фактический PNG после перехода RGB→CMYK в этой сборке: заметное потемнение, не цветопроба типографии — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/spectrum.ppm');
$image->setImageColorspace(Gmagick::COLORSPACE_CMYK);
$space = $image->getImageColorspace();
$image->setImageFormat('PNG');
$image->writeImage(__DIR__ . '/web-preview.png');

RGB описывает световые составляющие, CMYK — модель цветоделения с чёрной составляющей. Числовые компоненты после смены пространства имеют другой смысл. Полная программа фиксирует CMYK/ColorSeparation до записи, затем повторно открывает PNG и получает RGB. Центр исходника 127,128,127 в этом маршруте стал 63,64,63. Сам факт успешной записи не доказывает правильность цвета.

Обнаружить изменение цвета при неподходящем маршруте экспортаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image=new Gmagick(__DIR__.'/spectrum.ppm');$originalSpace=$image->getImageColorspace();
$image->setImageColorspace(Gmagick::COLORSPACE_CMYK);
$cmykSpace=$image->getImageColorspace();$cmykType=$image->getImageType();$range=$image->getImageExtrema();
$image->setImageDepth(8);
$image->setImageFormat('PNG');
$image->writeImage(__DIR__.'/gm99-cmyk-web-preview.png');
$decoded=new Gmagick(__DIR__.'/gm99-cmyk-web-preview.png');$savedSpace=$decoded->getImageColorspace();

gmReport('gm99-cmyk-preview',["gmagick.construct", "gmagick.getimagecolorspace", "gmagick.setimagecolorspace", "gmagick.getimagetype", "gmagick.getimageextrema", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm99-cmyk-web-preview.png"],
    ['spaces'=>$originalSpace===Gmagick::COLORSPACE_RGB&&$cmykSpace===Gmagick::COLORSPACE_CMYK&&$savedSpace===Gmagick::COLORSPACE_RGB,'type_separation'=>$cmykType===Gmagick::IMGTYPE_COLORSEPARATION,'size_gm99_cmyk_web_preview'=>gmInspect('gm99-cmyk-web-preview.png')['width']===320&&gmInspect('gm99-cmyk-web-preview.png')['height']===200],
    $errors ?? [], ['cmyk_space'=>$cmykSpace,'cmyk_type'=>$cmykType,'cmyk_extrema'=>$range,'decoded_png_space'=>$savedSpace]);
echo "gm99-cmyk-web-preview.png 320x200\n";
Ожидаемый результат
gm99-cmyk-web-preview.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-cmyk-web-preview.png 320x200

Для веб-превью сохраняйте согласованный RGB-маршрут. Для типографии выясните требуемый профиль и формат; простое назначение CMYK не моделирует конкретные бумагу, краски и устройство. В этом уроке не обещается ICC-проверка. Объект исходника полезно хранить отдельно: необратимые потери при ошибочном преобразовании нельзя компенсировать возвращением прежнего названия пространства.

Упражнение: какой результат separateImageChannel(RED) — красная картинка или серые уровни? Ответ: серые уровни выбранного компонента. Сколько уровней в двух битах? Ответ:4. Доказывают ли одинаковые min/max одинаковую гистограмму? Ответ:нет. Числовой getter пространства не заменяет проверку растра. Следующий шаг — ограничение всех цветов. Проверка ошибок и создание функции опираются на исключения и функции PHP.

Практический вопрос, из которого вырос сценарий

Extract Red Channel from Image: Автор хочет получить изображение красного канала RGB и не понимает, как выглядит отдельная составляющая. На собственном двумерном градиенте выделяем R/G/B в независимых копиях. Объясняем, почему большой уровень становится светлым серым, а не красной краской, и сопоставляем направления переходов с формулой входа. Вопрос об Imagick служит задачей, а фактический контракт Gmagick проверен отдельно.

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

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

Gmagick::getimagechanneldepthУзнать необходимую глубину конкретного канала

PECL gmagick >= Unknown · gmagick

Gmagick::getimagechanneldepth(int $channel_type): int

Обязательный channel_type — int, выбирающий CHANNEL_*. В текущей странице PHP.net есть опечатка: раздел параметров говорит об их отсутствии, но сигнатура и C-реализация требуют канал. Возвращается int — глубина этого канала. У собственного RGB8 входа красный требует 8 бит, после ограничения получаются 2 или 4. Это не число цветов всего изображения и не способ определить число байтов на канал в произвольном raw-файле: сохранённые 16-битные значения, кратные 257, могут эффективно описываться 8 битами.

Gmagick::getimagechanneldepth(int $channel_type): int
АргументТипСмысл
channel_typeint — обязательныйОбязательная константа CHANNEL_*; фраза «нет параметров» в тексте PHP.net противоречит сигнатуре.

Возврат по PHP.net: int — целое число с указанным выше смыслом.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Сократить уровни одного канала до двух и четырёх бит; Сделать проверяемую пробу выбранного канала.

Gmagick::getimagecolorspaceПрочитать цветовое пространство текущего изображения

PECL gmagick >= Unknown · gmagick

Gmagick::getimagecolorspace(): int

Без аргументов; возвращается int, сравниваемый с Gmagick::COLORSPACE_*. Это идентификатор пространства, не строка RGB и не число цветов. Наш PPM имеет COLORSPACE_RGB, после явного перехода в памяти читается GRAY либо CMYK. При повторном чтении серого PNG эта сборка сообщает RGB, хотя пиксели остаются серыми и getImageType возвращает Grayscale. Поэтому одно поле пространства не заменяет проверку компонентов, типа и формата. Различайте состояние объекта до сохранения и описание уже записанного файла.

Gmagick::getimagecolorspace(): int

Аргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.

Возврат по PHP.net: int — целое число с указанным выше смыслом.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Получить серую версию цветного оригинала; Обнаружить изменение цвета при неподходящем маршруте экспорта.

Gmagick::getimageextremaПрочитать минимальный и максимальный уровень

PECL gmagick >= Unknown · gmagick

Gmagick::getimageextrema(): array

Без аргументов. Возвращает ассоциативный массив с ключами min и max. В Q16-сборке значения нашего входа лежат в 0…65535, хотя исходный PPM хранит RGB8; это внутренний диапазон, не координаты пикселей и не готовые числа 0…255. После separateImageChannel можно проверить диапазон выбранного компонента. Два экстремума не описывают распределение тонов: изображения с разными гистограммами могут иметь одинаковые min/max. Пустой объект вызывает GmagickException; наличие файла ещё не гарантирует полезные данные для конкретной пробы.

Gmagick::getimageextrema(): array

Аргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.

Возврат по PHP.net: array — массив с указанными выше ключами.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Посмотреть три составляющие одного изображения; Сделать проверяемую пробу выбранного канала.

Gmagick::getimagetypeОпределить потенциальный тип изображения

PECL gmagick >= Unknown · gmagick

Gmagick::getimagetype(): int

Аргументов нет; возвращается int — потенциальный тип, сравниваемый с IMGTYPE_*. Важно слово «потенциальный»: это характеристика изображения, а не гарантированный код упаковки будущего PNG. В примерах различаем Grayscale, Bilevel, TrueColor и ColorSeparation. После сохранения квантованного результата эта сборка может читать TrueColor при всего четырёх уникальных цветах. Нельзя по одному getter обещать индексный PNG определённого битового формата; для требований файла проверяют сам файл и его декодированные данные.

Gmagick::getimagetype(): int

Аргументов нет: пустые скобки обращаются к текущему изображению или настройке объекта, как пояснено выше.

Возврат по PHP.net: int — целое число с указанным выше смыслом.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Получить серую версию цветного оригинала; Выбрать серый или двухцветный вариант для печати.

Gmagick::separateimagechannelПолучить серое представление компонента

PECL gmagick >= Unknown · gmagick

Gmagick::separateimagechannel(int $channel): Gmagick

channel — одна из Gmagick::CHANNEL_*. Компонент — отдельное числовое значение каждого пикселя. Возвращается изменённый Gmagick с серым изображением выбранной составляющей: большой уровень красного показывается светлым, а не красной краской. Для трёх результатов нужны три копии исходника; последовательное выделение R, затем G в уже серой копии не извлечёт исходный зелёный. CHANNEL_* здесь отличается от COLOR_* в GmagickPixel. Каналы других цветовых моделей интерпретируются в контексте их пространства; наш пример — RGB.

Gmagick::separateimagechannel(int $channel): Gmagick
АргументТипСмысл
channelint — обязательныйКонстанта CHANNEL_* выбранной составляющей.

Возврат по PHP.net: Gmagick — изменённый объект изображения.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Посмотреть три составляющие одного изображения; Сделать проверяемую пробу выбранного канала.

Gmagick::setimagechanneldepthСократить точность выбранной составляющей

PECL gmagick >= Unknown · gmagick

Gmagick::setimagechanneldepth(int $channel, int $depth): Gmagick

channel — CHANNEL_*, depth — число бит; оба аргумента int, результат Gmagick. Для красного depth=2 оставляет четыре возможных уровня, depth=4 — шестнадцать. Это изменение данных компонента, а не только указание упаковки PNG. Остальные RGB-компоненты в прямом сравнении сохраняются, поэтому число цветов изображения может остаться большим. Приложение само проверяет допустимый диапазон задачи: в функции пробы 1…8; это не объявляется полным диапазоном всех сборок Gmagick. Массив вместо depth даёт TypeError. Повышение глубины позже не восстанавливает потерянные промежуточные значения.

Gmagick::setimagechanneldepth(int $channel, int $depth): Gmagick
АргументТипСмысл
channelint — обязательныйКонстанта CHANNEL_* выбранной составляющей.
depthint — обязательныйГлубина выбранного канала в битах.

Возврат по PHP.net: Gmagick — изменённый объект изображения.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Сократить уровни одного канала до двух и четырёх бит; Сделать проверяемую пробу выбранного канала.

Gmagick::setimagecolorspaceЗадать пространство и проверить реальное преобразование

PECL gmagick >= Unknown · gmagick

Gmagick::setimagecolorspace(int $colorspace): Gmagick

colorspace — одна целая константа COLORSPACE_*. Возвращается Gmagick. Краткий контракт PHP.net говорит об установке пространства; он не обещает ICC-преобразование для конкретной печатной машины. В этом runtime вызов GRAY действительно изменил RGB-пиксели на серые. Переносить сюда поведение одноимённого setter Imagick нельзя. Опыт с CMYK и последующей записью PNG дал заметное потемнение; это показанное ограничение проверенного маршрута, а не образец правильного цвета для типографии. Для согласованной печати отдельно согласуют профиль, входные данные и требования получателя.

Gmagick::setimagecolorspace(int $colorspace): Gmagick
АргументТипСмысл
colorspaceint — обязательныйКонстанта COLORSPACE_*; в quantizeImage выбирает пространство анализа цветов.

Возврат по PHP.net: Gmagick — изменённый объект изображения.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Получить серую версию цветного оригинала; Обнаружить изменение цвета при неподходящем маршруте экспорта.

Gmagick::setimagetypeВыбрать способ представления изображения

PECL gmagick >= Unknown · gmagick

Gmagick::setimagetype(int $imgType): Gmagick

imgType — целая константа Gmagick::IMGTYPE_*, возвращается Gmagick. Grayscale даёт серые уровни, Bilevel — чёрное и белое, Palette запрашивает палитровое представление; доступны и другие константы согласно установленному расширению. Пример подробно сравнивает первые два и показывает цену потери полутонов. Тип — не расширение файла: после преобразования отдельно выбирается PNG. Для управляемого числа цветов используйте quantizeImage, а для заранее заданных цветов mapImage. Одна операция изменения типа не обещает заданный печатный профиль.

Gmagick::setimagetype(int $imgType): Gmagick
АргументТипСмысл
imgTypeint — обязательныйКонстанта IMGTYPE_* требуемого типа.

Возврат по PHP.net: Gmagick — изменённый объект изображения.

Официальный отказ: GmagickException при ошибке операции. Неверный PHP-тип может быть отвергнут раньше как TypeError; проверка диапазона в наших функциях даёт отдельную InvalidArgumentException.

Требуется PECL Gmagick. Нижняя граница версии указана PHP.net как Unknown; её не заменяем датой страницы или номером PHP в новостном баннере. Результаты здесь проверяются на фиксированной Q16-сборке, другие версии могут отличаться.

Два применения: Выбрать серый или двухцветный вариант для печати; Сделать проверяемую пробу выбранного канала.

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

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

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

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

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