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

Дерево руководства
Глава 433 · После первых изображений, файлов и методов
Gmagick: ICC-профили, преобразование цвета и web-превью
Прочитать и восстановить профиль, отличить присвоение от конверсии, сделать sRGB-превью и безопасно удалить служебные данные.
Прочитать профиль: из PNG в отдельный ICC-файл
Фотография поставщика и её превью выглядят по-разному. Первым делом нужно узнать, как исходник описывает свой цвет. RGB — это три записанных числа для красного, зелёного и синего каналов. ICC-профиль объясняет, какой цвет означают эти числа в данном пространстве. Наша карточка с коробкой и кружкой имеет заранее известный Display P3. Программа извлекает её профиль в отдельный файл; сама карточка остаётся прежней.

Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$image = new Gmagick(__DIR__ . "/source-p3.png");
$bytes = $image->getImageProfile("icm");
echo strlen($bytes);
file_put_contents("extracted.icc", $bytes);new создаёт объект и читает изображение; -> вызывает его метод. Строка "icm" — имя цветового профиля внутри объекта, а не имя файла. $bytes получает возвращённую строку с бинарными данными: здесь 480 байт, поэтому echo strlen($bytes) выведет 480. echo $bytes не покажет изображение и даст нечитаемые символы. file_put_contents сохраняет именно эти байты, а hash("sha256", $bytes) позволяет сравнить их с известным профилем без печати бинарного содержимого. В используемой GraphicsMagick имя icm работает и для чтения, и для изменения ICC. Getter также принимает icc, но переносить этот псевдоним на запись нельзя: ниже показана граница версии. Отсутствующее имя вызывает GmagickException; исключение можно поймать и сообщить, что цветовая характеристика неизвестна.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
$image = new Gmagick(__DIR__ . '/source-p3.png');
$profile = $image->getImageProfile('icm');
file_put_contents(__DIR__ . '/gm103-profile-read-extracted.icc', $profile);
gmPng($image, 'gm103-profile-read-source.png');
$errors['missing'] = gmTry(fn() => $image->getImageProfile('no-such-profile'));
$info = ['bytes' => strlen($profile), 'sha256' => hash('sha256', $profile),
'meaning' => 'Known Display P3 source; binary profile, not an image'];
file_put_contents(__DIR__ . '/gm103-profile-read-receipt.json', json_encode($info, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
$checks = [
'profile_is_complete' => strlen($profile) === 480 && hash('sha256', $profile) === GM_INPUT_HASHES['source-p3.icc'],
'export_matches_input' => hash_file('sha256', __DIR__ . '/gm103-profile-read-extracted.icc') === GM_INPUT_HASHES['source-p3.icc'],
'source_pixels_kept' => gmSamePixels('source-p3.png', 'gm103-profile-read-source.png'),
'missing_profile_caught' => $errors['missing']['class'] === 'GmagickException'
];
gmReport('gm103-profile-read', ["gmagick.getimageprofile"], ["gm103-profile-read-source.png"], $checks, $errors ?? [], $info);
echo "profile-read: ICC=480 bytes extracted; image unchanged\n";
Ожидаемый результат
profile-read: ICC=480 bytes extracted; image unchanged
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Попробуйте заменить icm на no-such-profile. Результат — обработанная ошибка, а не пустой корректный ICC. Наличие 480 байт само по себе не подтверждает название профиля: мы узнаём конкретный файл по полному SHA256. Для чужих загрузок нужна отдельная политика приёма и исследование происхождения, а не угадывание по яркости.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Вернуть известный исходный профиль без пересчёта RGB
Генератор потерял цветовой профиль, но оригинал и точный рецепт сохранились. Это подходящий случай для восстановления метаданных. Чтобы ситуация была воспроизводимой, программа сама создаёт неисправность: убирает ICC из нашей известной P3-карточки. Затем возвращает копию исходного профиля. Ни один RGB-пиксель при этом не пересчитывается.


Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$known = file_get_contents(__DIR__ . "/source-p3.icc");
$image->setImageProfile("icm", $known);Две строки предполагают уже прочитанный $image с известными P3-числами. file_get_contents читает содержимое ICC-файла, а setImageProfile добавляет или заменяет профиль с указанным именем. Метод возвращает тот же Gmagick; он не возвращает PNG-строку и сам не сохраняет файл. clone в полной программе создаёт независимую копию, поэтому исходное состояние можно сравнить с исправленным. Удаление icm меняет интерпретацию цвета, но не превращает P3-числа в sRGB. Восстановление допустимо здесь потому, что происхождение известно. Для неизвестного JPEG нельзя выбирать профиль просто потому, что с ним картинка выглядит приятнее. Одинаковые RGB у двух PNG и разные ICC — измеримое различие между содержимым пикселей и описанием цвета. На этой сборке getter у живого объекта после удаления icm вернул строку, а не исключение. Поэтому реальное отсутствие ICC подтверждаем отсутствием iCCP в сохранённом PNG; не считаем успешный getter доказательством полного профиля.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
$source = new Gmagick(__DIR__ . '/source-p3.png');
$knownProfile = $source->getImageProfile('icm');
$unlabelled = clone $source;
$unlabelled->removeImageProfile('icm');
gmPng($unlabelled, 'gm103-profile-attach-unlabelled.png');
$fixed = clone $unlabelled;
$returned = $fixed->setImageProfile('icm', $knownProfile);
gmPng($fixed, 'gm103-profile-attach-restored.png');
$afterRemoval = gmTry(fn() => $unlabelled->getImageProfile('icm'));
$checks = [
'setter_returns_same_object' => $returned === $fixed,
'restored_full_profile' => $fixed->getImageProfile('icm') === $knownProfile,
'same_decoded_pixels' => gmSamePixels('gm103-profile-attach-unlabelled.png', 'gm103-profile-attach-restored.png'),
'post_removal_getter_observed' => $afterRemoval['ok'] === true && $afterRemoval['type'] === 'string'
];
gmReport('gm103-profile-attach', ["gmagick.getimageprofile", "gmagick.removeimageprofile", "gmagick.setimageprofile"], ["gm103-profile-attach-unlabelled.png", "gm103-profile-attach-restored.png"], $checks, $errors ?? [], ['getter_after_removal' => $afterRemoval]);
echo "profile-attach: known P3 restored; RGB unchanged\n";
Ожидаемый результат
profile-attach: known P3 restored; RGB unchanged
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Если исходник на самом деле Adobe RGB, подстановка нашего P3 будет неверной. Оставьте такой файл без автоматического «ремонта», сохраните оригинал и запросите достоверное описание источника. Упражнение: объяснить, почему добавление sRGB этим setter не является преобразованием P3 → sRGB. Ответ показывает следующий опыт.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Отличить замену этикетки от настоящего P3 → sRGB
Для сайта нужно sRGB-представление известного P3-оригинала. Внешне похожие вызовы решают разные задачи. Слева исходник, затем намеренно неверная замена профиля, затем настоящее преобразование. setImageProfile назначает новое описание старым числам. profileImage с действительным исходным ICC и целевым ICC запускает управление цветом и пересчитывает числа.
- Исходные P3-пиксели + достоверный P3 ICC.
- Назначить sRGB через setImageProfile: числа прежние, описание другое.
- Преобразовать через profileImage: CMS использует оба ICC и выбранный intent; выходные числа пересчитаны.



Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$image = new Gmagick(__DIR__ . "/source-p3.png");
$srgb = file_get_contents(__DIR__ . "/target-srgb.icc");
$image->setImageRenderingIntent(Gmagick::RENDERINGINTENT_RELATIVE);
$image->profileImage("icm", $srgb);
$image->writeImage("web.png");В нашем входе исходный P3 уже встроен; цель читается из файла как бинарная строка. Rendering intent — выбранное правило обработки цветовых различий; его подробно разбирает следующая глава. profileImage возвращает объект, а запись PNG выполняется отдельно. Программа доказывает пересчёт по декодированным RGB и проверяет встроенный целевой ICC по SHA256. У неверно размеченного варианта RGB совпадают с исходником; у преобразованного отличаются. В проверенной GraphicsMagick 1.3.42 используйте имя icm. Хотя getImageProfile("icc") прочитал ICC, set/profile/remove с "icc" не заменили нужный iCCP сохранённого PNG; это не универсальная взаимозаменяемость имён. Константа colorspace сама по себе тоже не описывает полный ICC и не заменяет этот маршрут. Изображение с отсутствующим исходным профилем требует сначала достоверного определения источника.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
$source = new Gmagick(__DIR__ . '/source-p3.png');
$target = file_get_contents(__DIR__ . '/target-srgb.icc');
gmPng($source, 'gm103-profile-convert-source.png');
$retagged = clone $source;
$retagged->setImageProfile('icm', $target);
gmPng($retagged, 'gm103-profile-convert-retagged.png');
$converted = clone $source;
$converted->setImageRenderingIntent(Gmagick::RENDERINGINTENT_RELATIVE);
$returned = $converted->profileImage('icm', $target);
gmPng($converted, 'gm103-profile-convert-converted.png');
$checks = [
'profile_returns_same_object' => $returned === $converted,
'retag_keeps_pixels' => gmSamePixels('gm103-profile-convert-source.png', 'gm103-profile-convert-retagged.png'),
'conversion_changes_pixels' => !gmSamePixels('gm103-profile-convert-source.png', 'gm103-profile-convert-converted.png'),
'target_profile_written' => $converted->getImageProfile('icm') === $target && $retagged->getImageProfile('icm') === $target,
'source_profile_kept' => hash('sha256', $source->getImageProfile('icm')) === GM_INPUT_HASHES['source-p3.icc']
];
gmReport('gm103-profile-convert', ["gmagick.getimageprofile", "gmagick.setimageprofile", "gmagick.profileimage", "gmagick.setimagerenderingintent"], ["gm103-profile-convert-source.png", "gm103-profile-convert-retagged.png", "gm103-profile-convert-converted.png"], $checks, $errors ?? [], []);
echo "profile-convert: retag=RGB unchanged; conversion=RGB changed, sRGB\n";
Ожидаемый результат
profile-convert: retag=RGB unchanged; conversion=RGB changed, sRGB
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Замените profileImage на setImageProfile и сравните результат с исходником по RGB. Новая метка sRGB без пересчёта не решает задачу. На некоторых мониторах различие будет небольшим; измерение не зависит от способности экрана показать весь охват P3. Преобразование из более широкого пространства также не обещает сохранить каждый цвет вне охвата sRGB.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Реальная задача разработчика
How Can I Use Imagick to Change the Color Profile to SRGB and Have it Preserve Colors Like `convert {file} -profile {iccfile} {file}. Автор получает менее насыщенные цвета при попытке перевести Display P3 в sRGB через setter и смену colorspace; CLI даёт иной результат. Разделяем назначение профиля и пересчёт по исходному и целевому ICC. Собственный Gmagick-пример сравнивает реальные RGB и iCCP, использует проверенное имя icm и не переносит команды Imagick как доказательство.
Сделать web-превью с проверенным целевым профилем
Теперь задача приложения: получить из P3-карточки небольшое sRGB-превью для каталога, а оригинал оставить для будущих экспортов. Результат программы — настоящий PNG 200 × 160 и JSON-квитанция. Имя файла, размер и SHA256 ICC дают получателю конкретный договор.


Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$preview = clone $source;
$preview->profileImage("icm", $targetProfileBytes);
$convertedProfile = $preview->getImageProfile("icm");
$preview->thumbnailImage(200, 160, true);
$preview->setImageProfile("icm", $convertedProfile);
$preview->writeImage("preview.png");Короткий фрагмент предполагает уже выбранный intent и проверенные источник/цель. Полная makeWebPreview принимает объект и байты целевого профиля, проверяет оба известных SHA256, создаёт clone, выбирает Relative, преобразует цвет и уменьшает изображение. В проверенной сборке thumbnailImage удалил ICC: сам пересчитанный цвет сохранился, но профиль перестал читаться, а PNG не содержал iCCP. Поэтому перед уменьшением сохраняем уже целевой профиль, а после возвращаем его через setImageProfile. Это восстановление описания уже преобразованных sRGB-чисел, а не повторная конверсия. true в thumbnailImage просит вписать картинку в пределы с сохранением пропорций. Источник 400 × 320 имеет ту же пропорцию, поэтому результат ровно 200 × 160. В реальной системе allowlist профилей заменяет эти два конкретных учебных хеша, а оригиналы сохраняют отдельно. Строка "target-srgb.icc" и URL не являются содержимым профиля. Прикладная функция отклоняет такую строку заранее; независимый ошибочный вызов библиотеки демонстрирует GmagickException. Это объясняет, почему наличие правильного пути в переменной ещё не означает, что преобразователь получил ICC.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
function makeWebPreview(Gmagick $source, string $target): Gmagick {
if (hash('sha256', $source->getImageProfile('icm')) !== GM_INPUT_HASHES['source-p3.icc']) {
throw new DomainException('Unknown source profile');
}
if (hash('sha256', $target) !== GM_INPUT_HASHES['target-srgb.icc']) {
throw new InvalidArgumentException('Target is not our approved sRGB profile');
}
$preview = clone $source;
$preview->setImageRenderingIntent(Gmagick::RENDERINGINTENT_RELATIVE);
$preview->profileImage('icm', $target);
$convertedProfile = $preview->getImageProfile('icm');
$preview->thumbnailImage(200, 160, true);
$preview->setImageProfile('icm', $convertedProfile);
return $preview;
}
$source = new Gmagick(__DIR__ . '/source-p3.png');
$target = file_get_contents(__DIR__ . '/target-srgb.icc');
$preview = makeWebPreview($source, $target);
gmPng($source, 'gm103-profile-web-source.png');
gmPng($preview, 'gm103-profile-web-preview.png');
$errors['filename_not_bytes'] = gmTry(fn() => makeWebPreview($source, 'target-srgb.icc'));
$bad = clone $source;
$errors['library_bad_profile'] = gmTry(fn() => $bad->profileImage('icm', 'target-srgb.icc'));
$receipt = ['file' => 'gm103-profile-web-preview.png', 'width' => 200, 'height' => 160,
'target_icc_sha256' => hash('sha256', $preview->getImageProfile('icm')),
'rendering_intent' => 'relative', 'input_preserved' => true];
file_put_contents(__DIR__ . '/gm103-profile-web-receipt.json', json_encode($receipt, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
$checks = [
'preview_dimensions' => $preview->getImageWidth() === 200 && $preview->getImageHeight() === 160,
'preview_profile' => $preview->getImageProfile('icm') === $target,
'original_profile' => hash('sha256', $source->getImageProfile('icm')) === GM_INPUT_HASHES['source-p3.icc'],
'path_rejected' => $errors['filename_not_bytes']['class'] === 'InvalidArgumentException' && $errors['library_bad_profile']['class'] === 'GmagickException'
];
gmReport('gm103-profile-web', ["gmagick.getimageprofile", "gmagick.profileimage", "gmagick.setimagerenderingintent", "gmagick.thumbnailimage", "gmagick.setimageprofile"], ["gm103-profile-web-source.png", "gm103-profile-web-preview.png"], $checks, $errors ?? [], $receipt);
echo "profile-web: preview=200x160 sRGB; path-not-bytes rejected; receipt saved\n";
Ожидаемый результат
profile-web: preview=200x160 sRGB; path-not-bytes rejected; receipt saved
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Откройте архив: example.php создаёт preview.png и receipt.json с именами, приведёнными в коде. Для браузера выводите PNG через <img>, а JSON используйте для учёта. Для печати нужны согласованные печатные профили и требования типографии; этот RGB-пример не заявляет проверенную конвертацию FOGRA/CMYK.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Реальная задача разработчика
How to resolve the “ColorspaceColorProfileMismatch 'icc'” conflict when creating an image?. Автор пытается получить CMYK TIFF из sRGB PNG и передаёт в profileImage адрес ICC-файла; возникает конфликт цвета и профиля. Показываем бинарные байты file_get_contents вместо пути/URL, проверку известных профилей и отдельную библиотечную ошибку. Наш реальный RGB web-пример не заявляет проверенное решение CMYK/FOGRA.
Удалить профиль с надёжной резервной копией и вернуть его
Перед временным снятием ICC нужна пригодная для восстановления копия. Наивное $backup = removeImageProfile(...) выглядит удобно, но на нашей версии возвращённая бинарная строка обрезалась до первого нулевого байта: для этого ICC получилось 0 байт вместо 480. Поэтому сначала читаем полный профиль, сохраняем его и лишь затем удаляем.


Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$backup = $image->getImageProfile("icm");
file_put_contents("backup.icc", $backup);
$image->removeImageProfile("icm");
// Позже, только для этих же известных RGB:
$image->setImageProfile("icm", $backup);Официальный контракт removeImageProfile обещает вернуть удалённый профиль строкой. Реализация Gmagick 2.0.6RC1 при формировании return использует строку до нулевого байта; полный getImageProfile использует длину. Это наблюдаемое ограничение сборки, а не свойство формата ICC и не причина считать каждый пустой return успешной резервной копией. Реальное удаление подтверждается отсутствием iCCP в PNG; восстановление — точным профилем и неизменными RGB. Повторное удаление только что удалённого icm в этой сборке вернуло строку, а не GmagickException. Вызов с никогда не существовавшим именем в discovery дал исключение; эти состояния нельзя молча считать одинаковыми. Удаление проверяем по отсутствию iCCP в записанном PNG. PHP.net также описывает удаление через profileImage("*", null), однако в нашей PHP 8.3.6-сборке второй аргумент string и null даёт TypeError. Для одного профиля пользуемся проверенным removeImageProfile, а не опираемся на противоречивую подсказку. Удаление цветового профиля не является обязательным «очищением» web-изображения.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
$image = new Gmagick(__DIR__ . '/source-p3.png');
$backup = $image->getImageProfile('icm');
file_put_contents(__DIR__ . '/gm103-profile-backup-remove-backup.icc', $backup);
$returned = $image->removeImageProfile('icm');
gmPng($image, 'gm103-profile-backup-remove-removed.png');
$secondRemoval = gmTry(fn() => $image->removeImageProfile('icm'));
$errors['null_not_supported'] = gmTry(fn() => $image->profileImage('*', null));
$restored = clone $image;
$restored->setImageProfile('icm', file_get_contents(__DIR__ . '/gm103-profile-backup-remove-backup.icc'));
gmPng($restored, 'gm103-profile-backup-remove-restored.png');
$receipt = ['backup_bytes' => strlen($backup), 'remove_return_bytes' => strlen($returned),
'binary_return_matches_backup' => $returned === $backup, 'second_removal' => $secondRemoval,
'backup_sha256' => hash('sha256', $backup)];
file_put_contents(__DIR__ . '/gm103-profile-backup-remove-receipt.json', json_encode($receipt, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
$checks = [
'complete_backup' => strlen($backup) === 480 && hash('sha256', $backup) === GM_INPUT_HASHES['source-p3.icc'],
'restored_profile' => $restored->getImageProfile('icm') === $backup,
'pixels_preserved' => gmSamePixels('gm103-profile-backup-remove-removed.png', 'gm103-profile-backup-remove-restored.png'),
'version_specific_binary_return' => is_string($returned) && strlen($returned) === 0,
'repeat_remove_returns_string_here' => $secondRemoval['ok'] === true && $secondRemoval['type'] === 'string',
'null_error_caught' => $errors['null_not_supported']['class'] === 'TypeError'
];
gmReport('gm103-profile-backup-remove', ["gmagick.getimageprofile", "gmagick.removeimageprofile", "gmagick.setimageprofile", "gmagick.profileimage"], ["gm103-profile-backup-remove-removed.png", "gm103-profile-backup-remove-restored.png"], $checks, $errors ?? [], $receipt);
echo "profile-remove: backup=480 bytes; remove-return=0 on this build; profile restored\n";
Ожидаемый результат
profile-remove: backup=480 bytes; remove-return=0 on this build; profile restored
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Упражнение: убрать профиль ради меньшего размера и назвать результат sRGB. Ошибка: числа остались P3. Для корректного web-выхода сначала выполните реальное преобразование, затем решайте отдельно, какие метаданные нужны получателю. Резервная копия ICC описывает только цвет, а не заменяет резервную копию исходной фотографии.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Передать служебную метку между шагами и убрать её перед экспортом
У профиля может быть и служебное назначение. Два шага собственного обработчика передают метку задания внутри объекта Gmagick; после работы метку нужно удалить, сохранив ICC цвета. Пример использует отдельное имя app-manual, показывает чтение, замену и удаление записи с резервной копией точного значения. Итоговая карточка выглядит как исходная, а job.json хранит историю.

Это настоящие PNG данной программы. Цвет на экране зависит от монитора и поддержки профилей браузером; утверждения о равенстве RGB и ICC проверяются по сохранённым файлам, а не только на глаз.
$image->setImageProfile("app-manual", "queue:catalog-v1");
$label = $image->getImageProfile("app-manual");
$image->setImageProfile("app-manual", "queue:catalog-v2");
$lastLabel = $image->getImageProfile("app-manual");
$image->removeImageProfile("app-manual");Первое значение $label — queue:catalog-v1, резервное $lastLabel — queue:catalog-v2. Точное значение берём getter-ом перед удалением. В реальном запуске removeImageProfile вернул ASCII-метку с лишним пробелом в конце; поэтому даже отсутствие нулевых байтов не делает его return надёжной копией на этой версии. Квитанция использует get до remove, а возвращаемые данные remove не сохраняет как полезную нагрузку. Имена разделяют служебную запись и icm; удаление app-manual не затрагивает цветовой профиль. Вызов get после удаления получает GmagickException, который программа ожидает и объясняет. Произвольный профиль объекта не обязательно переживёт кодирование в PNG или JPEG: поддержка зависит от формата. Поэтому постоянный идентификатор задания и историю сохраняем отдельно в JSON или базе, а не обещаем, что любой просмотрщик прочитает app-manual. Для обычного приложения отдельная PHP-переменная часто проще; данный пример полезен при передаче уже существующего объекта между собственными этапами.
<?php
declare(strict_types=1);
require __DIR__ . '/gm103-profile-fixture.php';
gmRestore();
$image = new Gmagick(__DIR__ . '/source-p3.png');
$colorProfile = $image->getImageProfile('icm');
$image->setImageProfile('app-manual', 'queue:catalog-v1');
$incoming = $image->getImageProfile('app-manual');
$image->setImageProfile('app-manual', 'queue:catalog-v2');
$lastLabel = $image->getImageProfile('app-manual');
$image->removeImageProfile('app-manual');
$errors['label_absent'] = gmTry(fn() => $image->getImageProfile('app-manual'));
gmPng($image, 'gm103-profile-work-label-export.png');
$receipt = ['received' => $incoming, 'removed_label_from_backup' => $lastLabel,
'color_profile_sha256' => hash('sha256', $image->getImageProfile('icm')),
'note' => 'Job metadata is persisted here, not assumed to survive image encoding'];
file_put_contents(__DIR__ . '/gm103-profile-work-label-job.json', json_encode($receipt, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
$checks = [
'read_then_replaced' => $incoming === 'queue:catalog-v1' && $lastLabel === 'queue:catalog-v2',
'color_profile_kept' => $image->getImageProfile('icm') === $colorProfile,
'decoded_pixels_kept' => gmSamePixels('source-p3.png', 'gm103-profile-work-label-export.png'),
'label_removed' => $errors['label_absent']['class'] === 'GmagickException'
];
gmReport('gm103-profile-work-label', ["gmagick.getimageprofile", "gmagick.setimageprofile", "gmagick.removeimageprofile"], ["gm103-profile-work-label-export.png"], $checks, $errors ?? [], $receipt);
echo "profile-label: v1 read, v2 removed; color profile preserved; job.json saved\n";
Ожидаемый результат
profile-label: v1 read, v2 removed; color profile preserved; job.json saved
Распакуйте пример и выполните php example.php с установленным Gmagick и поддержкой PNG/ICC в GraphicsMagick. В комплекте известные входы в base64, их SHA256, лицензия ICC и gm103-profile-fixture.php. Helper восстанавливает входы, пишет PNG 8 бит/канал и metrics.json; gmSamePixels сравнивает реально сохранённые пиксели. Код операции показан коротко выше; полный пример создаёт перечисленные PNG и квитанции самостоятельно. Сырые бинарные ICC не выводятся на экран.
Не помещайте токен доступа или личные данные клиента в изображение. Это не шифрование. Практическая проверка здесь предметная: служебная метка действительно удалена, известный ICC остался точным, декодированные RGB не изменились. Не заменяйте точечное удаление безусловным stripImage, если нужно сохранить управление цветом.
Опорные понятия: объект и вызов метода, параметр и возвращаемое значение, исключения, clone. Связанные задачи: пропорциональные превью, цветовые координаты.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Gmagick::getimageprofileПрочитать полные байты именованного профиля
PECL gmagick >= Unknown · gmagick
Gmagick::getimageprofile(string $name): stringgetImageProfile читает профиль текущего изображения по обязательному имени $name и возвращает string с его полными байтами. Для ICC это бинарная строка, а не путь, картинка или человекочитаемое название; strlen сообщает байты. В этой главе icm выбирает цветовой профиль GraphicsMagick, app-manual — собственную служебную запись. Чтение не меняет пиксели. Полные байты можно сохранить file_put_contents или сравнить по SHA256. Никогда не существовавшее имя и пустой объект дали GmagickException. После удаления icm в живом объекте getter этой сборки вернул строку; реальное отсутствие ICC подтверждается по записанному PNG, а не обязательным исключением. На странице PHP.net раздел Parameters ошибочно говорит об отсутствии параметров: сигнатура и проверенный вызов требуют $name. Для резервной копии бинарного ICC используйте этот getter до удаления, учитывая описанную особенность removeImageProfile.
Gmagick::getimageprofile(string $name): string| Параметр | Тип и обязательность | Для чего |
|---|---|---|
| $name | string; обязательный; без default | Имя профиля внутри изображения. В проверенном маршруте ICC: icm; это не имя файла. |
Официальная ошибка методов — GmagickException. TypeError и исключения прикладных функций названы отдельно в примерах; библиотечная ошибка не заменяет проверку происхождения профиля. PHP.net указывает PECL gmagick ≥ Unknown, поэтому точную минимальную версию не выдумываем. Наблюдаемые ограничения относятся к PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16; в другом окружении сверяйте реальные выходы.
Применения: Прочитать профиль: из PNG в отдельный ICC-файл; Удалить профиль с надёжной резервной копией и вернуть его; Передать служебную метку между шагами и убрать её перед экспортом.
Продолжение: намерение, выбор пользователя и рецепт, цветовые координаты и белая точка, договор экспорта и метаданные.
Gmagick::profileimageПрименить ICC при преобразовании известного источника
PECL gmagick >= Unknown · gmagick
Gmagick::profileimage(string $name, string $profile): GmagickprofileImage добавляет профиль; при работе с цветовым профилем и уже описанным источником применяет CMS-преобразование. В нашем проверенном маршруте исходный P3 хранится под icm, целевые sRGB-байты передаются вторым аргументом, RGB действительно меняются и PNG содержит целевой iCCP. Метод возвращает Gmagick. Наличие профиля и корректные байты существенны: он не угадывает пространство безымянного источника. Для обработки намерения используйте setImageRenderingIntent до преобразования. Официальное описание также охватывает ICC/IPTC/общие профили и обещает удаление при null, в том числе имени * для всех. Но официальная сигнатура string и проверенная PHP 8.3.6/Gmagick 2.0.6RC1 отвергает null с TypeError. Для удаления одного известного профиля показан removeImageProfile с предварительным backup; null-вызов не выдан за рабочий рецепт.
Gmagick::profileimage(string $name, string $profile): Gmagick| Параметр | Тип и обязательность | Для чего |
|---|---|---|
| $name | string; обязательный | Имя профиля; icm в нашем реально проверенном ICC-маршруте. |
| $profile | string; обязательный | Байты целевого профиля. Описанный в прозе null не принят этой сборкой. |
Официальная ошибка методов — GmagickException. TypeError и исключения прикладных функций названы отдельно в примерах; библиотечная ошибка не заменяет проверку происхождения профиля. PHP.net указывает PECL gmagick ≥ Unknown, поэтому точную минимальную версию не выдумываем. Наблюдаемые ограничения относятся к PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16; в другом окружении сверяйте реальные выходы.
Применения: Отличить замену этикетки от настоящего P3 → sRGB; Сделать web-превью с проверенным целевым профилем; Сравнить четыре намерения на одном известном источнике.
Продолжение: намерение, выбор пользователя и рецепт, цветовые координаты и белая точка, договор экспорта и метаданные.
Gmagick::removeimageprofileУдалить точную запись и сохранить пригодную копию
PECL gmagick >= Unknown · gmagick
Gmagick::removeimageprofile(string $name): stringremoveImageProfile удаляет профиль с обязательным именем $name. Официально возвращает string с удалённым профилем; никогда не существовавшее имя в discovery вызвало GmagickException. Повторный remove только что удалённого icm вернул строку; состояние подтверждается сохранённым PNG. Пиксели при снятии ICC не преобразуются. Существенная граница проверенной версии: бинарный ICC из 480 байт вернулся как пустая строка из-за обрезания на нулевом байте при формировании return; удаление реально произошло. Поэтому полный backup берём getImageProfile перед удалением, проверяем длину и SHA256 и сохраняем отдельно. Даже ASCII-метка app-manual в MAIN вернулась с лишним пробелом. Точное значение любого профиля для квитанции берём getter-ом перед remove; return удаления не используем как надёжный backup. Не используйте этот результат как универсальное обещание для любого бинарного профиля. Для web-конверсии снятие ICC само по себе не заменяет profileImage.
Gmagick::removeimageprofile(string $name): string| Параметр | Тип и обязательность | Для чего |
|---|---|---|
| $name | string; обязательный; без default | Точное имя удаляемого профиля. Удаляется выбранная запись, а не все метаданные. |
Официальная ошибка методов — GmagickException. TypeError и исключения прикладных функций названы отдельно в примерах; библиотечная ошибка не заменяет проверку происхождения профиля. PHP.net указывает PECL gmagick ≥ Unknown, поэтому точную минимальную версию не выдумываем. Наблюдаемые ограничения относятся к PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16; в другом окружении сверяйте реальные выходы.
Применения: Удалить профиль с надёжной резервной копией и вернуть его; Передать служебную метку между шагами и убрать её перед экспортом.
Продолжение: намерение, выбор пользователя и рецепт, цветовые координаты и белая точка, договор экспорта и метаданные.
Gmagick::setimageprofileДобавить или заменить профиль без CMS-преобразования
PECL gmagick >= Unknown · gmagick
Gmagick::setimageprofile(string $name, string $profile): GmagicksetImageProfile добавляет именованный профиль или заменяет существующий. Обязательные строки $name и $profile задают имя записи и её полные байты. Возвращает Gmagick, в наших вызовах тот же объект; файл записывается отдельно. В отличие от profileImage, setter не применяет CMS-преобразование цвета. Применяйте его для подтверждённого исходного профиля при известных RGB или для служебных профилей. Назначить sRGB старым P3-числам недостаточно для конверсии. Путь/URL не равны ICC-байтам: прочитайте файл. В используемой GraphicsMagick изменяем цветовой профиль именем icm; чтение через icc не доказывает взаимозаменяемость при записи. Произвольные профили поддерживаются объектом, но их сохранение зависит от формата. thumbnailImage этой сборки удалил ICC; примеры сохраняют уже целевой профиль до уменьшения и возвращают его этим setter после, не выполняя повторную конверсию.
Gmagick::setimageprofile(string $name, string $profile): Gmagick| Параметр | Тип и обязательность | Для чего |
|---|---|---|
| $name | string; обязательный | Имя ICC/IPTC/общего профиля; для наших ICC используется icm. |
| $profile | string; обязательный | Полное бинарное содержимое либо данные служебного профиля. Не путь к файлу. |
Официальная ошибка методов — GmagickException. TypeError и исключения прикладных функций названы отдельно в примерах; библиотечная ошибка не заменяет проверку происхождения профиля. PHP.net указывает PECL gmagick ≥ Unknown, поэтому точную минимальную версию не выдумываем. Наблюдаемые ограничения относятся к PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16; в другом окружении сверяйте реальные выходы.
Применения: Вернуть известный исходный профиль без пересчёта RGB; Отличить замену этикетки от настоящего P3 → sRGB; Передать служебную метку между шагами и убрать её перед экспортом.
Продолжение: намерение, выбор пользователя и рецепт, цветовые координаты и белая точка, договор экспорта и метаданные.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


