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

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

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

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

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

Imagick: rendering intent, настоящее ICC-преобразование и экспорт sRGB

Не потерять смысл цвета: прочитать и задать режим, преобразовать корректный P3-вход в sRGB и проверить сохранение состояния в файле.

Получить настоящий sRGB-файл для каталога и увидеть частую ошибку

Сервис принимает изображение с телефона в Display P3 и должен отдать предсказуемый sRGB-файл для каталога. Если просто удалить ICC, те же числа каналов начинают интерпретироваться иначе: цвет кружки в нашем диагностическом просмотре тускнеет. Установка rendering intent сама не исправляет такую ошибку. Справа показан файл после настоящего преобразования с сохранённым целевым профилем.

Слева: неверный просмотр P3-чисел без управления цветом; центр: один setter ничего не перекрасил; справа: actual ICC-преобразование в sRGB
Слева: неверный просмотр P3-чисел без управления цветом; центр: один setter ничего не перекрасил; справа: actual ICC-преобразование в sRGB

Это собственный учебный рисунок, а не сторонняя фотография. Известный sRGB-исходник сначала действительно преобразован в DisplayP3Compat-v4; полученный source-p3.png содержит именно этот профиль. Мы не присваивали случайному sRGB-файлу ярлык P3. В архиве находятся оба исходника и два точных CC0-профиля. Исходный профилированный P3-файл может корректно выглядеть в умеющем управление цветом просмотрщике; ошибочная левая панель специально показывает потерю такой информации.

$image->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$intent = $image->getImageRenderingIntent();
$image->profileImage('icc', $srgb);

$image — объект с изображением и верным встроенным P3-профилем; -> вызывает его метод. Imagick::RENDERINGINTENT_RELATIVE — именованная целочисленная константа, :: обращается к константе класса. Круглые скобки содержат аргументы; getter вызывается с пустыми скобками. $intent получает число, а не изменённую картинку. В третьей строке строка icc — имя типа профиля, $srgb — его бинарные байты, предварительно прочитанные file_get_contents. Именно profileImage выполняет последующую трансформацию; точка с запятой завершает каждую команду. Отдельная копия $export сохраняет настоящий PNG8: png:preserve-iCCP оставляет бинарный целевой профиль вместо замены метаданных, а повторное открытие $exported позволяет проверить фактически записанный файл. Объекты, переменные и чтение файлов разобраны отдельно.

Подготовить sRGB-превью из корректного P3-входа

Слева — ошибочный просмотр P3-чисел без исходного ICC, в центре — тот же результат после одного setter, справа — настоящий sRGB после profileImage. export-srgb.png сохраняет целевой ICC; диагностические PNG8 отдельно показывают разницу.

Подготовить sRGB-превью из корректного P3-входаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
$wrong=clone $input;
$wrong->removeImageProfile('icc');
$state=clone $wrong;
$set=$state->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$intent=$state->getImageRenderingIntent();
$converted=clone $input; // Keep the genuine embedded source ICC.
$converted->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$ok=$converted->profileImage('icc',$srgb);
$export=clone $converted;
$export->setImageFormat('png');$export->setImageDepth(8);
$export->setOption('png:bit-depth','8');$export->setOption('png:color-type','2');
$export->setOption('png:preserve-iCCP','true');
$export->writeImage(__DIR__.'/export-srgb.png');
$exported=new Imagick(__DIR__.'/export-srgb.png');
riFirstProof($input,$wrong,$state,$converted,$exported,$set,$ok,$intent,$before);
echo "rendering-intent-first.png\nsource-preview8.png\nwrong-stripped8.png\nsetter-only8.png\nconverted-srgb8.png\nexport-srgb.png\nmetrics.json\nset=true intent=4 setter-keeps-RGB=1 ICC-conversion=1\n";

Слева — ошибочный просмотр P3-чисел без исходного ICC, в центре — тот же результат после одного setter, справа — настоящий sRGB после profileImage. export-srgb.png сохраняет целевой ICC; диагностические PNG8 отдельно показывают разницу. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-first.png
source-preview8.png
wrong-stripped8.png
setter-only8.png
converted-srgb8.png
export-srgb.png
metrics.json
set=true intent=4 setter-keeps-RGB=1 ICC-conversion=1

Разделить числа RGB, исходный профиль, настройку и реальное преобразование

Поле intent задаёт режим; верный исходный ICC и целевой ICC участвуют в отдельном profileImage-преобразовании
Поле intent задаёт режим; верный исходный ICC и целевой ICC участвуют в отдельном profileImage-преобразовании
Часть изображенияЧто означает
RGB-пикселиЧисла каналов; без знания пространства недостаточны для однозначного смысла цвета.
Встроенный source ICCОписывает, как интерпретировать существующие числа. Его нельзя угадывать по расширению файла.
Rendering intentНастройка выбора способа отображения цветов при следующем управляемом преобразовании.
Целевой ICC и LCMSprofileImage использует их вместе с исходным профилем для вычисления новых чисел; целевой профиль связывается с результатом.
GetterЧитает текущее поле. Его число не доказывает, что предыдущий шаг был настоящей конверсией.

Удобная модель — числа, их словарь значений и правило перевода. Аналогия ограничена: ICC не простая таблица названий цветов, а профиль с характеристиками каналов и преобразований. Setter выбирает правило, а не запускает перевод. Назначить другой словарь старым числам и вычислить соответствующие новые числа — разные действия. Если source ICC уже удалён, первый profileImage с sRGB лишь назначает его без преобразования: библиотеке неоткуда узнать прежний смысл P3-чисел.

Perceptual обычно выбирают для передачи общего впечатления с учётом гамута, Relative — для относительной колориметрии, Absolute — когда важна абсолютная колориметрия, Saturation — для соответствующей цели насыщенности. Конкретное отображение определяется профилями и CMS. Эти названия не гарантируют четыре визуально разных результата; наша пара matrix/TRC-профилей дала одинаковые RGB во всех проверенных режимах. Чёрная точка и её компенсация — отдельная настройка, setter intent её не включает. Не обещаем сохранение всех цветов при сужении гамута или неизбежную обратимость преобразования.

Назначение пространства и его преобразование также различаются: настройки colorspace помогают отделить метаданные от вычисления пикселей. Повторный export и композиция требуют учитывать, в каком пространстве уже находятся данные; одинаковое имя RGB ещё не означает одинаковый профиль.

Установить режим коротким вызовом и прочитать его после реального сохранения

Setter сохраняет число без перекрашивания; PNG и MIFF после чтения могут вернуть разные поля при одинаковых пикселях и ICC
Setter сохраняет число без перекрашивания; PNG и MIFF после чтения могут вернуть разные поля при одинаковых пикселях и ICC

Сначала короткая операция: вход уже содержит известный P3 ICC, clone создаёт отдельную рабочую копию. riRestore восстанавливает проверенные файлы из base64, riInput открывает source-p3.png. riHash измеряет численные RGB через PIXEL_DOUBLE, riICC считает SHA встроенного профиля; они не конвертируют цвет. После setter эти измерения должны остаться прежними.

Установить именованный режим и прочитать его без перекрашивания

Setter вернул true, getter — 4, то есть RENDERINGINTENT_RELATIVE в этой сборке. Числа RGB и байты встроенного ICC остались прежними; режим ещё не выполнил преобразование.

Установить именованный режим и прочитать его без перекрашиванияПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
$image=clone $input;
$ok=$image->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$intent=$image->getImageRenderingIntent();
riSetProof($input,$image,$ok,$intent,$before,$icc);
echo "rendering-intent-set.png\nset-before8.png\nmetrics.json\nset=true intent=4 RGB-unchanged=1 ICC-unchanged=1\n";

Setter вернул true, getter — 4, то есть RENDERINGINTENT_RELATIVE в этой сборке. Числа RGB и байты встроенного ICC остались прежними; режим ещё не выполнил преобразование. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-set.png
set-before8.png
metrics.json
set=true intent=4 RGB-unchanged=1 ICC-unchanged=1
$intent = $image->getImageRenderingIntent();
echo $intent;

Это самый короткий смысл getter: прочитать int у уже существующего изображения. Теперь практическая причина действительно его прочитать — проверить состояние после сохранения и повторного открытия. В следующем примере до записи задан Relative=4. PNG с прежним ICC после декодирования вернул Perceptual=2, MIFF вернул 4; сравнение RGB и ICC при этом совпало. MIFF здесь контрольный собственный формат ImageMagick, не формат изображения для браузера. Его сохранение не является предложением отдавать MIFF пользователю сайта.

Прочитать режим после PNG и MIFF, сохранив проверку пикселей

Перед сохранением режим 4; после чтения PNG — 2, MIFF — 4. При этом измеренные RGB и встроенный ICC совпали. Getter отражает текущий объект после декодирования формата, а не обещает перенос произвольного поля через любой файл.

Прочитать режим после PNG и MIFF, сохранив проверку пикселейПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
$image=clone $input;
$image->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$beforeRead=$image->getImageRenderingIntent();
$savePNG=clone $image; $savePNG->setImageFormat('png');
$savePNG->writeImage(__DIR__.'/get-state.png');
$saveMIFF=clone $image; $saveMIFF->setImageFormat('miff');
$saveMIFF->writeImage(__DIR__.'/get-state.miff');
$png=new Imagick(__DIR__.'/get-state.png');
$miff=new Imagick(__DIR__.'/get-state.miff');
$pngRead=$png->getImageRenderingIntent();
$miffRead=$miff->getImageRenderingIntent();
riGetProof($input,$png,$miff,$beforeRead,$pngRead,$miffRead,$before,$icc);
echo "rendering-intent-get.png\nget-png8.png\nget-miff8.png\nget-state.png\nget-state.miff\nmetrics.json\nbefore=4 PNG=2 MIFF=4 RGB-same=1 ICC-same=1\n";

Перед сохранением режим 4; после чтения PNG — 2, MIFF — 4. При этом измеренные RGB и встроенный ICC совпали. Getter отражает текущий объект после декодирования формата, а не обещает перенос произвольного поля через любой файл. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-get.png
get-png8.png
get-miff8.png
get-state.png
get-state.miff
metrics.json
before=4 PNG=2 MIFF=4 RGB-same=1 ICC-same=1

get-state.png и get-state.miff — настоящие файлы сохранения. get-png8.png и get-miff8.png — отдельно изготовленные диагностические просмотры их чисел без ICC, оба подписаны как такие просмотры. Не нужно ждать разницы цветов от различного числа getter и нельзя считать эти PNG8 доказательством переноса режима. Вывод относится к проверенной сборке и точным файлам, а не ко всем PNG с любым набором chunks.

Собрать обработчик с реальной конверсией, политикой режима и понятными ошибками

Три настоящие ICC-конверсии здесь одинаковы; назначение sRGB после потери исходного ICC оставляет неправильные числа
Три настоящие ICC-конверсии здесь одинаковы; назначение sRGB после потери исходного ICC оставляет неправильные числа

В обработчике загрузки нужен предсказуемый вход: известный source ICC, явный режим, поддержка LCMS и отдельный выходной файл. chooseIntent ниже — собственная политика приложения, которая принимает четыре именованных режима. Мы намеренно показываем, что низкоуровневый setter допускает 999, поэтому его true не заменяет прикладную проверку. Контроль UNDEFINED в цикле нужен для изучения API; рабочая политика его не выбирает.

Выбрать режим, выполнить ICC-преобразование и не принять неправильный вход

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены.

Выбрать режим, выполнить ICC-преобразование и не принять неправильный входПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
function chooseIntent(int $intent):int {
    $allowed=[Imagick::RENDERINGINTENT_PERCEPTUAL,Imagick::RENDERINGINTENT_RELATIVE,
        Imagick::RENDERINGINTENT_SATURATION,Imagick::RENDERINGINTENT_ABSOLUTE];
    if(!in_array($intent,$allowed,true)){throw new InvalidArgumentException('Choose one of the four supported application modes');}
    return $intent;
}
$modes=['UNDEFINED'=>Imagick::RENDERINGINTENT_UNDEFINED,'PERCEPTUAL'=>Imagick::RENDERINGINTENT_PERCEPTUAL,
    'RELATIVE'=>Imagick::RENDERINGINTENT_RELATIVE,'SATURATION'=>Imagick::RENDERINGINTENT_SATURATION,'ABSOLUTE'=>Imagick::RENDERINGINTENT_ABSOLUTE];
$cases=[];$outputs=[];
foreach($modes as $name=>$mode){
    $image=clone $input;
    $set=$image->setImageRenderingIntent($mode);$read=$image->getImageRenderingIntent();
    $sameRGB=riHash($image)===$before;$sameICC=riICC($image)===$icc;
    $ok=$image->profileImage('icc',$srgb);$outputs[$name]=$image;
    $cases[$name]=['setter'=>$set,'getter'=>$read,'RGB_unchanged_after_set'=>$sameRGB,'ICC_unchanged_after_set'=>$sameICC,
        'conversion_return'=>$ok,'converted_RGB_sha256'=>riHash($image),'converted_ICC_sha256'=>riICC($image),
        'conversion_error'=>riError($input,$image),'roundtrip_error'=>riError(riOriginal(),$image)];
}
$invalid=clone $input;$invalidSet=$invalid->setImageRenderingIntent(999);$invalidRead=$invalid->getImageRenderingIntent();
$policyRejected=false;try{chooseIntent(999);}catch(InvalidArgumentException $error){$policyRejected=true;}
$chosen=chooseIntent(Imagick::RENDERINGINTENT_RELATIVE);
$untagged=clone $input;$untagged->removeImageProfile('icc');$unprofiledBefore=riHash($untagged);
$assigned=$untagged->profileImage('icc',$srgb);$assignmentOnly=riHash($untagged)===$unprofiledBefore;
$errors=[];
foreach(['get_empty'=>fn()=>(new Imagick())->getImageRenderingIntent(),
    'set_empty'=>fn()=>(new Imagick())->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE),
    'bad_icc'=>fn()=>(clone $input)->profileImage('icc','not an ICC profile')] as $name=>$operation){
    try{$operation();$errors[$name]=['class'=>'not caught','message'=>''];}
    catch(Throwable $error){$errors[$name]=['class'=>get_class($error),'message'=>$error->getMessage()];}
}
foreach(['PERCEPTUAL','RELATIVE','SATURATION','ABSOLUTE'] as $name){riView($outputs[$name],'workflow-'.strtolower($name).'8.png');}
riView($untagged,'workflow-wrong-assigned8.png');
$rects=riCompare([$outputs['PERCEPTUAL'],$outputs['RELATIVE'],$outputs['SATURATION']],'rendering-intent-workflow.png');
$hashes=array_column($cases,'converted_RGB_sha256');$allEqual=count(array_unique($hashes))===1;
$allValid=true;foreach($cases as $name=>$case){$allValid=$allValid&&$case['setter']===true&&$case['getter']===$modes[$name]
    &&$case['RGB_unchanged_after_set']&&$case['ICC_unchanged_after_set']&&$case['conversion_return']===true
    &&$case['converted_ICC_sha256']===hash('sha256',$srgb)&&$case['conversion_error']['max']===51&&$case['roundtrip_error']['max']===5;}
riDiagnostic('rendering-intent-workflow',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],'cases'=>$cases,
    'all_converted_RGB_equal'=>$allEqual,'invalid_integer'=>['setter'=>$invalidSet,'getter'=>$invalidRead,'RGB_unchanged'=>riHash($invalid)===$before],
    'policy_rejects_999'=>$policyRejected,'chosen_policy_intent'=>$chosen,'missing_source_profile'=>['assignment_return'=>$assigned,'RGB_unchanged'=>$assignmentOnly],
    'errors'=>$errors,'source_unchanged'=>riHash($input)===$before,'panel_geometry'=>$rects,
    'checks'=>['five_modes_executed'=>$allValid,'same_real_result_for_this_profile_pair'=>$allEqual,
        'setter_accepts_invalid_integer'=>$invalidSet===true&&$invalidRead===999&&riHash($invalid)===$before,
        'application_policy_rejects_999'=>$policyRejected,'missing_source_does_not_convert'=>$assigned===true&&$assignmentOnly,
        'three_errors_caught'=>array_column($errors,'class')===['ImagickException','ImagickException','ImagickException'],
        'original_preserved'=>riHash($input)===$before]]);
echo "rendering-intent-workflow.png\nworkflow-perceptual8.png\nworkflow-relative8.png\nworkflow-saturation8.png\nworkflow-absolute8.png\nworkflow-wrong-assigned8.png\nmetrics.json\nmodes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3\n";

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-workflow.png
workflow-perceptual8.png
workflow-relative8.png
workflow-saturation8.png
workflow-absolute8.png
workflow-wrong-assigned8.png
metrics.json
modes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3

Все пять реальных преобразований дали одинаковый RGB-хэш для этой пары профилей. От P3-входа изменились 65 514 из 384 000 компонентов каналов, максимальная разница 51, RMSE 6.844484359; это изменение чисел при переводе между пространствами, не измерение визуального улучшения. С известным исходным sRGB после кругового преобразования получены max 5 и RMSE 0.389296909. Эти RGB через PIXEL_CHAR измерены до отдельного кодирования просмотров PNG8; значения не приравниваются к заново декодированным PNG8 без проверки округления. Хэши неизменности используют PIXEL_DOUBLE. Маленькая ошибка этой конкретной RGB-пары не обещает такой же результат для CMYK, другого гамута, JPEG или другой CMS.

СитуацияЧто фактически произошло
999 передано напрямую settertrue, getter=999, RGB прежние; chooseIntent отдельно отклонил это значение.
Удалён исходный ICC, затем назначен sRGBprofileImage вернул true, но численные RGB не изменились. Это назначение, не восстановление утраченного смысла исходного цвета.
Getter или setter на пустом ImagickImagickException: Can not process empty Imagick object.
Строка not an ICC profile вместо бинарного ICCImagickException: ColorspaceColorProfileMismatch. Полное сообщение сохранено в metrics.json.

Лицензия CC0 и provenance включены в каждый архив. Выбраны DisplayP3Compat-v4 и sRGB-v4 из Compact-ICC-Profiles, commit bdd84663061bc4ae95ca70decff54f581e27f702. Это не проприетарные Windows-профили и не обещание побитового совпадения с Apple Display P3. README отдельно предупреждает про отрицательный Z в Max-Correctness варианте; Compat рассчитан на совместимость.

Сохранить полный официальный контракт и воспроизвести запуск

Полный официальный базис

Imagick::getImageRenderingIntent(): int

Официальная доступность: PECL imagick 2 и 3; оба метода существуют в проверенной Imagick 3.8.1 с IM7 и не объявлены здесь устаревшими. Полная исходная запись с описанием, параметрами, результатом и исключениями сохранена ниже; официальных примеров на этих двух страницах нет.

getImageRenderingIntent не принимает аргументов и возвращает int — текущий rendering intent изображения. Это значение настройки, не изображение, не профиль и не признак успешного ICC-преобразования. Возможен RENDERINGINTENT_UNDEFINED. После чтения файла значение зависит также от декодера и формата; наш PNG вернул 2, хотя перед сохранением поле было 4, а MIFF сохранил 4.

Именованные значения этой сборки: UNDEFINED=0, SATURATION=1, PERCEPTUAL=2, ABSOLUTE=3, RELATIVE=4. Это enum Imagick, не нумерация rendering intent в бинарном заголовке ICC. Переносимый код использует имена констант. Для реального profileImage-преобразования текущий Core передаёт выбранный режим LCMS; Undefined и неизвестные значения в этой конкретной ветке переходят к Perceptual. Это поведение реализации, а не рекомендация пропускать проверку входа.

Официальный раздел ошибок указывает ImagickException. Оба метода требуют непустого текущего изображения; в реальном запуске пустой объект дал Can not process empty Imagick object. Отдельные ошибки чтения ICC или создания цветовой трансформации относятся к profileImage, а не к getter. В рабочем сценарии заранее проверяют наличие правильного исходного профиля, выбирают разрешённый intent и сохраняют целевой профиль вместе с преобразованными пикселями.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagerenderingintent">
 <refnamediv>
  <refname>Imagick::getImageRenderingIntent</refname>
  <refpurpose>Gets the image rendering intent</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageRenderingIntent</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Gets the image rendering intent.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns the image <link
   linkend="imagick.constants.renderingintent">rendering intent</link>.
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Полный официальный базис

Imagick::setImageRenderingIntent(int $rendering_intent): bool

Официальная доступность: PECL imagick 2 и 3; оба метода существуют в проверенной Imagick 3.8.1 с IM7 и не объявлены здесь устаревшими. Полная исходная запись с описанием, параметрами, результатом и исключениями сохранена ниже; официальных примеров на этих двух страницах нет.

setImageRenderingIntent принимает обязательный int $rendering_intent и возвращает true при успехе. Используйте именованные константы, выбирая политику предстоящего цветового преобразования. Сам setter меняет поле текущего изображения, не преобразует RGB и не переписывает байты существующего ICC. В этой реализации число 999 тоже сохраняется — return=true не является проверкой допустимого режима.

Именованные значения этой сборки: UNDEFINED=0, SATURATION=1, PERCEPTUAL=2, ABSOLUTE=3, RELATIVE=4. Это enum Imagick, не нумерация rendering intent в бинарном заголовке ICC. Переносимый код использует имена констант. Для реального profileImage-преобразования текущий Core передаёт выбранный режим LCMS; Undefined и неизвестные значения в этой конкретной ветке переходят к Perceptual. Это поведение реализации, а не рекомендация пропускать проверку входа.

Официальный раздел ошибок указывает ImagickException. Оба метода требуют непустого текущего изображения; в реальном запуске пустой объект дал Can not process empty Imagick object. Отдельные ошибки чтения ICC или создания цветовой трансформации относятся к profileImage, а не к getter. В рабочем сценарии заранее проверяют наличие правильного исходного профиля, выбирают разрешённый intent и сохраняют целевой профиль вместе с преобразованными пикселями.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagerenderingintent">
 <refnamediv>
  <refname>Imagick::setImageRenderingIntent</refname>
  <refpurpose>Sets the image rendering intent</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageRenderingIntent</methodname>
   <methodparam><type>int</type><parameter>rendering_intent</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image rendering intent.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>rendering_intent</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Для запуска нужны PHP CLI, расширение Imagick, связанный ImageMagick с LCMS и поддержкой используемых PNG/MIFF. В нашем запуске библиотека реально выполнила преобразование: одно наличие методов или return=true этого не доказывает. Файлы примера локальны, внешние сервисы не вызываются. PNG для HTTP отправляют отдельным ответом с Content-Type: image/png; диагностический текст не смешивают с бинарным телом.

Весь исполняемый fixture, отдельно от коротких вызовов

<?php
declare(strict_types=1);
function riRestore():void {
    $hashes=['source.png'=>'f51e5780445e0f5130a7f23112b2a00618035afd5545b8e3042c7ccff09b617c','source-p3.png'=>'8d17f52b840975ce18149cd08ceb0c488dc29878cb61ed8eb2ebb99b8e488eb1','source-p3.icc'=>'231752984cd4a5278e1b8d2390fe496767d4511fc81f54e1a5c69ae9ab4c42b5','target-srgb.icc'=>'c56e1685d888f5edb92fe07f2750f387f8fe8e91b32ff8fb0b56bfbbb9458353'];
    foreach($hashes as $name=>$hash){
        $raw=base64_decode((string)file_get_contents(__DIR__.'/'.$name.'.b64'),true);
        if($raw===false||hash('sha256',$raw)!==$hash||file_put_contents(__DIR__.'/'.$name,$raw)===false){throw new RuntimeException('Known image or ICC fixture missing/changed: '.$name);}
    }
}
function riInput():Imagick {return new Imagick(__DIR__.'/source-p3.png');}
function riOriginal():Imagick {
    $input=new Imagick(__DIR__.'/source.png');$base=new Imagick();$base->newImage(400,320,'white','png');
    $base->compositeImage($input,Imagick::COMPOSITE_OVER,0,0);$base->setImageAlphaChannel(Imagick::ALPHACHANNEL_OFF);return $base;
}
function riHash(Imagick $image):string {return hash('sha256',json_encode($image->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_DOUBLE),JSON_THROW_ON_ERROR));}
function riICC(Imagick $image):string {return hash('sha256',$image->getImageProfile('icc'));}
function riError(Imagick $a,Imagick $b):array {
    $x=$a->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_CHAR);$y=$b->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_CHAR);
    $max=0;$sum=0;$changed=0;foreach($x as $i=>$v){$d=abs($v-$y[$i]);$max=max($max,$d);$sum+=$d*$d;$changed+=(int)($d!==0);}
    return ['max'=>$max,'RMSE'=>sqrt($sum/count($x)),'changed_components'=>$changed,'components'=>count($x)];
}
function riView(Imagick $image,string $name):void {
    // This deliberately unmanaged PNG8 is a diagnostic view, not an ICC transform.
    $copy=clone $image;$copy->stripImage();$copy->setImageFormat('png');$copy->setImageDepth(8);
    $copy->setOption('png:bit-depth','8');$copy->setOption('png:color-type','2');$copy->setOption('png:exclude-chunk','all');
    if(!$copy->writeImage(__DIR__.'/'.$name)){throw new RuntimeException('Cannot write display PNG');}
}
function riCompare(array $images,string $name):array {
    $board=new Imagick();$board->newImage(400*count($images),320,'white');$rects=[];
    foreach($images as $i=>$image){
        if($image->getImageWidth()!==400||$image->getImageHeight()!==320){throw new RuntimeException('Expected 400x320 panel');}
        $raw=clone $image;$raw->stripImage();$board->compositeImage($raw,Imagick::COMPOSITE_OVER,400*$i,0);
        $rects[]=['x'=>400*$i,'y'=>0,'width'=>400,'height'=>320];
    }
    riView($board,$name);return $rects;
}
function riDiagnostic(string $id,array $data):void {
    $doc=['schema'=>'aen-rendering-intent-program-diagnostics-v1','example_id'=>$id,'runtime'=>['php'=>PHP_VERSION,'imagick'=>phpversion('imagick'),'image_magick'=>Imagick::getVersion()]]+$data;
    if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)."\n")===false){throw new RuntimeException('Diagnostic write failed');}
}
function riFirstProof(Imagick $input,Imagick $wrong,Imagick $state,Imagick $converted,Imagick $exported,bool $set,bool $ok,int $intent,string $before):void {
    $change=riError($input,$converted);$roundtrip=riError(riOriginal(),$converted);
    riView(riOriginal(),'source-preview8.png');riView($wrong,'wrong-stripped8.png');riView($state,'setter-only8.png');riView($converted,'converted-srgb8.png');
    $rects=riCompare([$wrong,$state,$converted],'rendering-intent-first.png');
    riDiagnostic('rendering-intent-first',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],'setter_return'=>$set,'getter'=>$intent,
        'conversion_return'=>$ok,'setter_RGB_unchanged'=>riHash($wrong)===riHash($state),'conversion_error'=>$change,'roundtrip_error'=>$roundtrip,
        'target_ICC_sha256'=>riICC($converted),'export_ICC_sha256'=>riICC($exported),'export_RGB_error'=>riError($converted,$exported),'source_unchanged'=>riHash($input)===$before,'panel_geometry'=>$rects,
        'checks'=>['setter_true'=>$set===true,'getter_relative'=>$intent===Imagick::RENDERINGINTENT_RELATIVE,'setter_keeps_RGB'=>riHash($wrong)===riHash($state),
            'real_conversion'=>$ok===true&&$change['max']===51&&$change['changed_components']===65514,'target_ICC'=>riICC($converted)==='c56e1685d888f5edb92fe07f2750f387f8fe8e91b32ff8fb0b56bfbbb9458353',
            'bounded_roundtrip'=>$roundtrip['max']===5,'production_ICC_preserved'=>riICC($exported)==='c56e1685d888f5edb92fe07f2750f387f8fe8e91b32ff8fb0b56bfbbb9458353','production_quantization_bounded'=>riError($converted,$exported)['max']<=1,'source_preserved'=>riHash($input)===$before]]);
}
function riSetProof(Imagick $input,Imagick $image,bool $ok,int $intent,string $before,string $icc):void {
    riView($input,'set-before8.png');riView($image,'rendering-intent-set.png');
    riDiagnostic('rendering-intent-set-minimal',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],'setter_return'=>$ok,'getter'=>$intent,
        'RGB_unchanged_after_set'=>riHash($image)===$before,'ICC_unchanged_after_set'=>riICC($image)===$icc,'source_unchanged'=>riHash($input)===$before,
        'checks'=>['setter_true'=>$ok===true,'named_mode_read'=>$intent===Imagick::RENDERINGINTENT_RELATIVE,'RGB_unchanged'=>riHash($image)===$before,
            'ICC_unchanged'=>riICC($image)===$icc,'source_preserved'=>riHash($input)===$before]]);
}
function riGetProof(Imagick $input,Imagick $png,Imagick $miff,int $beforeRead,int $pngRead,int $miffRead,string $before,string $icc):void {
    riView($png,'get-png8.png');riView($miff,'get-miff8.png');$rects=riCompare([$png,$miff],'rendering-intent-get.png');
    riDiagnostic('rendering-intent-get-minimal',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],
        'before_save'=>$beforeRead,'png_getter'=>$pngRead,'miff_getter'=>$miffRead,'png_RGB_error'=>riError($input,$png),'miff_RGB_error'=>riError($input,$miff),
        'png_ICC_sha256'=>riICC($png),'miff_ICC_sha256'=>riICC($miff),'source_unchanged'=>riHash($input)===$before,'panel_geometry'=>$rects,
        'checks'=>['before_relative'=>$beforeRead===Imagick::RENDERINGINTENT_RELATIVE,'png_actual_perceptual'=>$pngRead===Imagick::RENDERINGINTENT_PERCEPTUAL,
            'miff_preserves_relative'=>$miffRead===Imagick::RENDERINGINTENT_RELATIVE,'png_RGB_preserved'=>riError($input,$png)['max']===0,
            'miff_RGB_preserved'=>riError($input,$miff)['max']===0,'ICCs_preserved'=>riICC($png)===$icc&&riICC($miff)===$icc,'source_preserved'=>riHash($input)===$before]]);
}

riRestore проверяет четыре точных входа по SHA; riOriginal создаёт белую непрозрачную основу исходного собственного PNG, а riView удаляет метаданные только у отдельной диагностической копии и сохраняет PNG8. riCompare собирает натуральные панели 400 × 320 без масштабирования. riError сравнивает численные RGB, riDiagnostic записывает измерения; ни один helper не подменяет изучаемые вызовы setter/getter. Упражнение: замените рабочую политику Relative на Perceptual и объясните, почему равенство результата для этих профилей не делает режимы универсально одинаковыми. Решение: setter сохранит другое поле, profileImage передаст другой intent CMS, но выбранные профили вправе дать те же числа. Следующий шаг — обработка ошибок, собственные функции и различие назначения и преобразования пространства.

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

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

Imagick::getImageRenderingIntentПрочитать или выбрать режим перед настоящим ICC-преобразованием, различать поле и цвет пикселей

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageRenderingIntent(): int

Полный официальный базис

Imagick::getImageRenderingIntent(): int

Официальная доступность: PECL imagick 2 и 3; оба метода существуют в проверенной Imagick 3.8.1 с IM7 и не объявлены здесь устаревшими. Полная исходная запись с описанием, параметрами, результатом и исключениями сохранена ниже; официальных примеров на этих двух страницах нет.

getImageRenderingIntent не принимает аргументов и возвращает int — текущий rendering intent изображения. Это значение настройки, не изображение, не профиль и не признак успешного ICC-преобразования. Возможен RENDERINGINTENT_UNDEFINED. После чтения файла значение зависит также от декодера и формата; наш PNG вернул 2, хотя перед сохранением поле было 4, а MIFF сохранил 4.

Именованные значения этой сборки: UNDEFINED=0, SATURATION=1, PERCEPTUAL=2, ABSOLUTE=3, RELATIVE=4. Это enum Imagick, не нумерация rendering intent в бинарном заголовке ICC. Переносимый код использует имена констант. Для реального profileImage-преобразования текущий Core передаёт выбранный режим LCMS; Undefined и неизвестные значения в этой конкретной ветке переходят к Perceptual. Это поведение реализации, а не рекомендация пропускать проверку входа.

Официальный раздел ошибок указывает ImagickException. Оба метода требуют непустого текущего изображения; в реальном запуске пустой объект дал Can not process empty Imagick object. Отдельные ошибки чтения ICC или создания цветовой трансформации относятся к profileImage, а не к getter. В рабочем сценарии заранее проверяют наличие правильного исходного профиля, выбирают разрешённый intent и сохраняют целевой профиль вместе с преобразованными пикселями.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagerenderingintent">
 <refnamediv>
  <refname>Imagick::getImageRenderingIntent</refname>
  <refpurpose>Gets the image rendering intent</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageRenderingIntent</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Gets the image rendering intent.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns the image <link
   linkend="imagick.constants.renderingintent">rendering intent</link>.
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Прочитать режим после PNG и MIFF, сохранив проверку пикселей

Перед сохранением режим 4; после чтения PNG — 2, MIFF — 4. При этом измеренные RGB и встроенный ICC совпали. Getter отражает текущий объект после декодирования формата, а не обещает перенос произвольного поля через любой файл.

Прочитать режим после PNG и MIFF, сохранив проверку пикселейПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
$image=clone $input;
$image->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$beforeRead=$image->getImageRenderingIntent();
$savePNG=clone $image; $savePNG->setImageFormat('png');
$savePNG->writeImage(__DIR__.'/get-state.png');
$saveMIFF=clone $image; $saveMIFF->setImageFormat('miff');
$saveMIFF->writeImage(__DIR__.'/get-state.miff');
$png=new Imagick(__DIR__.'/get-state.png');
$miff=new Imagick(__DIR__.'/get-state.miff');
$pngRead=$png->getImageRenderingIntent();
$miffRead=$miff->getImageRenderingIntent();
riGetProof($input,$png,$miff,$beforeRead,$pngRead,$miffRead,$before,$icc);
echo "rendering-intent-get.png\nget-png8.png\nget-miff8.png\nget-state.png\nget-state.miff\nmetrics.json\nbefore=4 PNG=2 MIFF=4 RGB-same=1 ICC-same=1\n";

Перед сохранением режим 4; после чтения PNG — 2, MIFF — 4. При этом измеренные RGB и встроенный ICC совпали. Getter отражает текущий объект после декодирования формата, а не обещает перенос произвольного поля через любой файл. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-get.png
get-png8.png
get-miff8.png
get-state.png
get-state.miff
metrics.json
before=4 PNG=2 MIFF=4 RGB-same=1 ICC-same=1

Выбрать режим, выполнить ICC-преобразование и не принять неправильный вход

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены.

Выбрать режим, выполнить ICC-преобразование и не принять неправильный входПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
function chooseIntent(int $intent):int {
    $allowed=[Imagick::RENDERINGINTENT_PERCEPTUAL,Imagick::RENDERINGINTENT_RELATIVE,
        Imagick::RENDERINGINTENT_SATURATION,Imagick::RENDERINGINTENT_ABSOLUTE];
    if(!in_array($intent,$allowed,true)){throw new InvalidArgumentException('Choose one of the four supported application modes');}
    return $intent;
}
$modes=['UNDEFINED'=>Imagick::RENDERINGINTENT_UNDEFINED,'PERCEPTUAL'=>Imagick::RENDERINGINTENT_PERCEPTUAL,
    'RELATIVE'=>Imagick::RENDERINGINTENT_RELATIVE,'SATURATION'=>Imagick::RENDERINGINTENT_SATURATION,'ABSOLUTE'=>Imagick::RENDERINGINTENT_ABSOLUTE];
$cases=[];$outputs=[];
foreach($modes as $name=>$mode){
    $image=clone $input;
    $set=$image->setImageRenderingIntent($mode);$read=$image->getImageRenderingIntent();
    $sameRGB=riHash($image)===$before;$sameICC=riICC($image)===$icc;
    $ok=$image->profileImage('icc',$srgb);$outputs[$name]=$image;
    $cases[$name]=['setter'=>$set,'getter'=>$read,'RGB_unchanged_after_set'=>$sameRGB,'ICC_unchanged_after_set'=>$sameICC,
        'conversion_return'=>$ok,'converted_RGB_sha256'=>riHash($image),'converted_ICC_sha256'=>riICC($image),
        'conversion_error'=>riError($input,$image),'roundtrip_error'=>riError(riOriginal(),$image)];
}
$invalid=clone $input;$invalidSet=$invalid->setImageRenderingIntent(999);$invalidRead=$invalid->getImageRenderingIntent();
$policyRejected=false;try{chooseIntent(999);}catch(InvalidArgumentException $error){$policyRejected=true;}
$chosen=chooseIntent(Imagick::RENDERINGINTENT_RELATIVE);
$untagged=clone $input;$untagged->removeImageProfile('icc');$unprofiledBefore=riHash($untagged);
$assigned=$untagged->profileImage('icc',$srgb);$assignmentOnly=riHash($untagged)===$unprofiledBefore;
$errors=[];
foreach(['get_empty'=>fn()=>(new Imagick())->getImageRenderingIntent(),
    'set_empty'=>fn()=>(new Imagick())->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE),
    'bad_icc'=>fn()=>(clone $input)->profileImage('icc','not an ICC profile')] as $name=>$operation){
    try{$operation();$errors[$name]=['class'=>'not caught','message'=>''];}
    catch(Throwable $error){$errors[$name]=['class'=>get_class($error),'message'=>$error->getMessage()];}
}
foreach(['PERCEPTUAL','RELATIVE','SATURATION','ABSOLUTE'] as $name){riView($outputs[$name],'workflow-'.strtolower($name).'8.png');}
riView($untagged,'workflow-wrong-assigned8.png');
$rects=riCompare([$outputs['PERCEPTUAL'],$outputs['RELATIVE'],$outputs['SATURATION']],'rendering-intent-workflow.png');
$hashes=array_column($cases,'converted_RGB_sha256');$allEqual=count(array_unique($hashes))===1;
$allValid=true;foreach($cases as $name=>$case){$allValid=$allValid&&$case['setter']===true&&$case['getter']===$modes[$name]
    &&$case['RGB_unchanged_after_set']&&$case['ICC_unchanged_after_set']&&$case['conversion_return']===true
    &&$case['converted_ICC_sha256']===hash('sha256',$srgb)&&$case['conversion_error']['max']===51&&$case['roundtrip_error']['max']===5;}
riDiagnostic('rendering-intent-workflow',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],'cases'=>$cases,
    'all_converted_RGB_equal'=>$allEqual,'invalid_integer'=>['setter'=>$invalidSet,'getter'=>$invalidRead,'RGB_unchanged'=>riHash($invalid)===$before],
    'policy_rejects_999'=>$policyRejected,'chosen_policy_intent'=>$chosen,'missing_source_profile'=>['assignment_return'=>$assigned,'RGB_unchanged'=>$assignmentOnly],
    'errors'=>$errors,'source_unchanged'=>riHash($input)===$before,'panel_geometry'=>$rects,
    'checks'=>['five_modes_executed'=>$allValid,'same_real_result_for_this_profile_pair'=>$allEqual,
        'setter_accepts_invalid_integer'=>$invalidSet===true&&$invalidRead===999&&riHash($invalid)===$before,
        'application_policy_rejects_999'=>$policyRejected,'missing_source_does_not_convert'=>$assigned===true&&$assignmentOnly,
        'three_errors_caught'=>array_column($errors,'class')===['ImagickException','ImagickException','ImagickException'],
        'original_preserved'=>riHash($input)===$before]]);
echo "rendering-intent-workflow.png\nworkflow-perceptual8.png\nworkflow-relative8.png\nworkflow-saturation8.png\nworkflow-absolute8.png\nworkflow-wrong-assigned8.png\nmetrics.json\nmodes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3\n";

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-workflow.png
workflow-perceptual8.png
workflow-relative8.png
workflow-saturation8.png
workflow-absolute8.png
workflow-wrong-assigned8.png
metrics.json
modes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3
Imagick::setImageRenderingIntentПрочитать или выбрать режим перед настоящим ICC-преобразованием, различать поле и цвет пикселей

PECL imagick 2, PECL imagick 3 · imagick

Imagick::setImageRenderingIntent(int $rendering_intent): bool

Полный официальный базис

Imagick::setImageRenderingIntent(int $rendering_intent): bool

Официальная доступность: PECL imagick 2 и 3; оба метода существуют в проверенной Imagick 3.8.1 с IM7 и не объявлены здесь устаревшими. Полная исходная запись с описанием, параметрами, результатом и исключениями сохранена ниже; официальных примеров на этих двух страницах нет.

setImageRenderingIntent принимает обязательный int $rendering_intent и возвращает true при успехе. Используйте именованные константы, выбирая политику предстоящего цветового преобразования. Сам setter меняет поле текущего изображения, не преобразует RGB и не переписывает байты существующего ICC. В этой реализации число 999 тоже сохраняется — return=true не является проверкой допустимого режима.

Именованные значения этой сборки: UNDEFINED=0, SATURATION=1, PERCEPTUAL=2, ABSOLUTE=3, RELATIVE=4. Это enum Imagick, не нумерация rendering intent в бинарном заголовке ICC. Переносимый код использует имена констант. Для реального profileImage-преобразования текущий Core передаёт выбранный режим LCMS; Undefined и неизвестные значения в этой конкретной ветке переходят к Perceptual. Это поведение реализации, а не рекомендация пропускать проверку входа.

Официальный раздел ошибок указывает ImagickException. Оба метода требуют непустого текущего изображения; в реальном запуске пустой объект дал Can not process empty Imagick object. Отдельные ошибки чтения ICC или создания цветовой трансформации относятся к profileImage, а не к getter. В рабочем сценарии заранее проверяют наличие правильного исходного профиля, выбирают разрешённый intent и сохраняют целевой профиль вместе с преобразованными пикселями.

Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagerenderingintent">
 <refnamediv>
  <refname>Imagick::setImageRenderingIntent</refname>
  <refpurpose>Sets the image rendering intent</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageRenderingIntent</methodname>
   <methodparam><type>int</type><parameter>rendering_intent</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image rendering intent.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>rendering_intent</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Установить именованный режим и прочитать его без перекрашивания

Setter вернул true, getter — 4, то есть RENDERINGINTENT_RELATIVE в этой сборке. Числа RGB и байты встроенного ICC остались прежними; режим ещё не выполнил преобразование.

Установить именованный режим и прочитать его без перекрашиванияПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
$image=clone $input;
$ok=$image->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE);
$intent=$image->getImageRenderingIntent();
riSetProof($input,$image,$ok,$intent,$before,$icc);
echo "rendering-intent-set.png\nset-before8.png\nmetrics.json\nset=true intent=4 RGB-unchanged=1 ICC-unchanged=1\n";

Setter вернул true, getter — 4, то есть RENDERINGINTENT_RELATIVE в этой сборке. Числа RGB и байты встроенного ICC остались прежними; режим ещё не выполнил преобразование. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-set.png
set-before8.png
metrics.json
set=true intent=4 RGB-unchanged=1 ICC-unchanged=1

Выбрать режим, выполнить ICC-преобразование и не принять неправильный вход

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены.

Выбрать режим, выполнить ICC-преобразование и не принять неправильный входПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/rendering-intent-fixture.php';
riRestore();
$input=riInput(); $before=riHash($input);
$icc=riICC($input); $srgb=file_get_contents(__DIR__.'/target-srgb.icc');
function chooseIntent(int $intent):int {
    $allowed=[Imagick::RENDERINGINTENT_PERCEPTUAL,Imagick::RENDERINGINTENT_RELATIVE,
        Imagick::RENDERINGINTENT_SATURATION,Imagick::RENDERINGINTENT_ABSOLUTE];
    if(!in_array($intent,$allowed,true)){throw new InvalidArgumentException('Choose one of the four supported application modes');}
    return $intent;
}
$modes=['UNDEFINED'=>Imagick::RENDERINGINTENT_UNDEFINED,'PERCEPTUAL'=>Imagick::RENDERINGINTENT_PERCEPTUAL,
    'RELATIVE'=>Imagick::RENDERINGINTENT_RELATIVE,'SATURATION'=>Imagick::RENDERINGINTENT_SATURATION,'ABSOLUTE'=>Imagick::RENDERINGINTENT_ABSOLUTE];
$cases=[];$outputs=[];
foreach($modes as $name=>$mode){
    $image=clone $input;
    $set=$image->setImageRenderingIntent($mode);$read=$image->getImageRenderingIntent();
    $sameRGB=riHash($image)===$before;$sameICC=riICC($image)===$icc;
    $ok=$image->profileImage('icc',$srgb);$outputs[$name]=$image;
    $cases[$name]=['setter'=>$set,'getter'=>$read,'RGB_unchanged_after_set'=>$sameRGB,'ICC_unchanged_after_set'=>$sameICC,
        'conversion_return'=>$ok,'converted_RGB_sha256'=>riHash($image),'converted_ICC_sha256'=>riICC($image),
        'conversion_error'=>riError($input,$image),'roundtrip_error'=>riError(riOriginal(),$image)];
}
$invalid=clone $input;$invalidSet=$invalid->setImageRenderingIntent(999);$invalidRead=$invalid->getImageRenderingIntent();
$policyRejected=false;try{chooseIntent(999);}catch(InvalidArgumentException $error){$policyRejected=true;}
$chosen=chooseIntent(Imagick::RENDERINGINTENT_RELATIVE);
$untagged=clone $input;$untagged->removeImageProfile('icc');$unprofiledBefore=riHash($untagged);
$assigned=$untagged->profileImage('icc',$srgb);$assignmentOnly=riHash($untagged)===$unprofiledBefore;
$errors=[];
foreach(['get_empty'=>fn()=>(new Imagick())->getImageRenderingIntent(),
    'set_empty'=>fn()=>(new Imagick())->setImageRenderingIntent(Imagick::RENDERINGINTENT_RELATIVE),
    'bad_icc'=>fn()=>(clone $input)->profileImage('icc','not an ICC profile')] as $name=>$operation){
    try{$operation();$errors[$name]=['class'=>'not caught','message'=>''];}
    catch(Throwable $error){$errors[$name]=['class'=>get_class($error),'message'=>$error->getMessage()];}
}
foreach(['PERCEPTUAL','RELATIVE','SATURATION','ABSOLUTE'] as $name){riView($outputs[$name],'workflow-'.strtolower($name).'8.png');}
riView($untagged,'workflow-wrong-assigned8.png');
$rects=riCompare([$outputs['PERCEPTUAL'],$outputs['RELATIVE'],$outputs['SATURATION']],'rendering-intent-workflow.png');
$hashes=array_column($cases,'converted_RGB_sha256');$allEqual=count(array_unique($hashes))===1;
$allValid=true;foreach($cases as $name=>$case){$allValid=$allValid&&$case['setter']===true&&$case['getter']===$modes[$name]
    &&$case['RGB_unchanged_after_set']&&$case['ICC_unchanged_after_set']&&$case['conversion_return']===true
    &&$case['converted_ICC_sha256']===hash('sha256',$srgb)&&$case['conversion_error']['max']===51&&$case['roundtrip_error']['max']===5;}
riDiagnostic('rendering-intent-workflow',['executed_apis'=>['setImageRenderingIntent','getImageRenderingIntent'],'cases'=>$cases,
    'all_converted_RGB_equal'=>$allEqual,'invalid_integer'=>['setter'=>$invalidSet,'getter'=>$invalidRead,'RGB_unchanged'=>riHash($invalid)===$before],
    'policy_rejects_999'=>$policyRejected,'chosen_policy_intent'=>$chosen,'missing_source_profile'=>['assignment_return'=>$assigned,'RGB_unchanged'=>$assignmentOnly],
    'errors'=>$errors,'source_unchanged'=>riHash($input)===$before,'panel_geometry'=>$rects,
    'checks'=>['five_modes_executed'=>$allValid,'same_real_result_for_this_profile_pair'=>$allEqual,
        'setter_accepts_invalid_integer'=>$invalidSet===true&&$invalidRead===999&&riHash($invalid)===$before,
        'application_policy_rejects_999'=>$policyRejected,'missing_source_does_not_convert'=>$assigned===true&&$assignmentOnly,
        'three_errors_caught'=>array_column($errors,'class')===['ImagickException','ImagickException','ImagickException'],
        'original_preserved'=>riHash($input)===$before]]);
echo "rendering-intent-workflow.png\nworkflow-perceptual8.png\nworkflow-relative8.png\nworkflow-saturation8.png\nworkflow-absolute8.png\nworkflow-wrong-assigned8.png\nmetrics.json\nmodes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3\n";

Для этой пары matrix/TRC-профилей пять проверенных режимов дали одинаковый реальный RGB-результат. Произвольное 999 API принимает, но явная политика приложения отклоняет. На входе без исходного ICC новый sRGB только назначился; три намеренные ошибки перехвачены. Самостоятельный архив содержит четыре base64-входа: собственный исходный PNG, полученный настоящим преобразованием P3 PNG и два ICC; рядом лежат rendering-intent-fixture.php и исходная CC0-лицензия. Распакуйте в отдельный каталог и выполните php example.php. Проверено: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16 без HDRI, с LCMS, PNG и MIFF. riRestore декодирует точные входные байты и проверяет SHA. Вызовы изучаемых методов видны в основной программе; helper только готовит вход, записывает диагностические просмотры и измерения. Просмотры riView намеренно удаляют профили на копии: они не являются скрытым ICC-преобразованием и не выдаются за правильное отображение P3.

Ожидаемый вывод в проверенной сборке
rendering-intent-workflow.png
workflow-perceptual8.png
workflow-relative8.png
workflow-saturation8.png
workflow-absolute8.png
workflow-wrong-assigned8.png
metrics.json
modes=5 converted-RGB-equal=1 API-accepts-999=1 policy-rejects-999=1 errors=3
Источники и обсуждения

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

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

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

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