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

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

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

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

Глава 377 · После переменных, объектов, файлов и последовательностей Imagick

Imagick: оператор слоя и настоящее смешивание изображений

Получить три оформления PNG, прочитать и изменить оператор нужного слоя, отличить FLATTEN от явного compositeImage.

Получить три настоящих оформления одной иллюстрации

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

Один исходник и бирюзовая накладка: реальные результаты FLATTEN с OVER, MULTIPLY и SCREEN
Один исходник и бирюзовая накладка: реальные результаты FLATTEN с OVER, MULTIPLY и SCREEN

Оператор композиции — правило, по которому цвета накладываемого слоя соединяются с уже нарисованным фоном. Здесь слой — одно изображение в списке Imagick, а не PHP-класс. $image — переменная с объектом; -> вызывает его метод; круглые скобки содержат аргументы, точка с запятой заканчивает инструкцию. Imagick::COMPOSITE_MULTIPLY — именованная целочисленная константа, а не строка с названием эффекта. Метод getImageCompose читает правило текущего изображения, setImageCompose записывает его. Переменные, объекты и список изображений и выбор текущего кадра — связанные объяснения.

Собственный исходник имеет размер 400 × 320 пикселей. Helper сначала кладёт его OVER на белый холст: основа становится непрозрачной. Накладка того же размера содержит rgba(40,170,210,0.45): красную, зелёную и синюю компоненты и alpha 0.45. Это постоянный цвет с частичной непрозрачностью, а не маска и не произвольное удалённое изображение. Размеры, порядок двух слоёв и смещения 0,0 одинаковы; поэтому сравниваем именно оператор.

Собрать три оформления одной иллюстрации

Одна бирюзовая полупрозрачная накладка даёт три оформления: обычное наложение OVER, затемнение MULTIPLY и осветление SCREEN. Изображение создаёт mergeImageLayers; запись свойства сама не изменяет пиксели.

Собрать три оформления одной иллюстрацииПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
[$base, $overlay] = composeParts();
composeView($base, 'source-preview8.png');
$views = []; $observed = [];
$operators = ['over' => Imagick::COMPOSITE_OVER,
              'multiply' => Imagick::COMPOSITE_MULTIPLY,
              'screen' => Imagick::COMPOSITE_SCREEN];
foreach ($operators as $name => $wanted) {
    $layers = new Imagick();
    $layers->addImage($base);
    $layers->addImage($overlay);
    $layers->setIteratorIndex(1); // Choose the coloured source layer.
    $before = composeHash($layers);
    $ok = $layers->setImageCompose($wanted);
    $current = $layers->getImageCompose();
    $same = $before === composeHash($layers);
    // The PHP binding merges the complete list from its first image.
    $result = $layers->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
    composeView($result, $name.'-merge.png');
    $views[] = new Imagick(__DIR__.'/'.$name.'-merge.png');
    $observed[] = ['name'=>$name, 'requested'=>$wanted, 'current'=>$current,
        'setter_return'=>$ok, 'pixels_unchanged_by_setter'=>$same,
        'input_frames'=>$layers->getNumberImages(), 'output_frames'=>$result->getNumberImages(),
        'output'=>composePixels($result)];
}
$rects = composeCompare($views, 'compose-first.png');
composeDiagnostic('image-compose-first', ['cases'=>$observed, 'panel_geometry'=>$rects,
    'checks'=>['three_distinct_results'=>count(array_unique(array_map('composeHash',$views)))===3,
        'setter_keeps_pixels'=>!in_array(false,array_column($observed,'pixels_unchanged_by_setter'),true),
        'properties_match'=>array_column($observed,'requested')===array_column($observed,'current'),
        'each_result_is_one_image'=>array_column($observed,'output_frames')===[1,1,1]]]);
echo "compose-first.png\nsource-preview8.png\nover-merge.png\nmultiply-merge.png\nscreen-merge.png\nmetrics.json\noperators=3 setter-keeps-pixels=1\n";

Одна бирюзовая полупрозрачная накладка даёт три оформления: обычное наложение OVER, затемнение MULTIPLY и осветление SCREEN. Изображение создаёт mergeImageLayers; запись свойства сама не изменяет пиксели. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose-first.png
source-preview8.png
over-merge.png
multiply-merge.png
screen-merge.png
metrics.json
operators=3 setter-keeps-pixels=1

Проследить путь от свойства слоя к итоговому PNG

Правило хранится у выбранной накладки; пиксели результата создаёт объединение двух слоёв
Правило хранится у выбранной накладки; пиксели результата создаёт объединение двух слоёв

Удобная модель — инструкция, прикреплённая к плёнке поверх рисунка. Записать «смешивать через MULTIPLY» ещё не значит перекрасить плёнку или лист. При сборке программа берёт инструкцию каждого слоя и создаёт общий рисунок. Аналогия ограничена порядком действий: математические операторы и alpha — вычисления над компонентами, а не буквальная оптика настоящей плёнки.

ШагКонкретные данныеЧто меняется
Подготовить основуСлой 0, непрозрачный рисунок 400 × 320Получен исходный растр для оформления
Подготовить накладкуСлой 1, rgba(40,170,210,0.45)Получен отдельный полупрозрачный растр
Выбрать и настроить слой 1setIteratorIndex(1), setImageCompose(MULTIPLY)Записано свойство накладки; её RGBA прежние
ОбъединитьmergeImageLayers(LAYERMETHOD_FLATTEN)Создан новый Imagick с одним общим изображением
Сохранить и показатьwriteImage отдельного PNGФайл содержит видимый результат вычисления

Точный Core MergeImageLayers использует image->compose каждого слоя вместе с его page-смещением. В PHP wrapper mergeImageLayers сам возвращает iterator к первому изображению и объединяет весь список: выбранный перед вызовом индекс 1 не означает «пропустить основу». Возвращённый объект нужно сохранить в переменную $result; один вызов без использования результата не заменяет исходную последовательность.

Прочитать оператор нужного слоя перед сборкой

Getter читает настройку выбранного слоя: сначала OVER основы, затем MULTIPLY накладки и результат объединения
Getter читает настройку выбранного слоя: сначала OVER основы, затем MULTIPLY накладки и результат объединения

Оператор композиции — правило, по которому цвета накладываемого слоя соединяются с уже нарисованным фоном. Здесь слой — одно изображение в списке Imagick, а не PHP-класс. $image — переменная с объектом; -> вызывает его метод; круглые скобки содержат аргументы, точка с запятой заканчивает инструкцию. Imagick::COMPOSITE_MULTIPLY — именованная целочисленная константа, а не строка с названием эффекта. Метод getImageCompose читает правило текущего изображения, setImageCompose записывает его. Переменные, объекты и список изображений и выбор текущего кадра — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::getImageCompose(): int
$operator = $image->getImageCompose();

Параметров нет. Возвращается int — оператор, сохранённый у текущего изображения. Сравнивайте его с Imagick::COMPOSITE_OVER, COMPOSITE_MULTIPLY и другими именованными константами. Getter не объединяет слои и не анализирует рисунок, чтобы угадать эффект. В последовательности сначала выберите нужный индекс: настройка основы и накладки может различаться.

В официальной записи есть неточность: сигнатура возвращает int, а абзац Return Values содержит общее обещание true при успехе. Оригинальный XML ниже сохранён полностью. Stub, PHP wrapper и реальный запуск подтверждают int с оператором, а не bool true. У известного собственного PNG в этих примерах прочитан OVER; не считайте это гарантией настроек любого загруженного документа.

Доступность: PECL imagick 2, PECL imagick 3. Официальные записи не содержат самостоятельных примеров кода; поле описания $compose в XML setter пустое. Setter официально объявляет ImagickException при ошибке. Текущий PHP wrapper проверяет наличие изображения у обоих методов: пустой new Imagick() приводит к ImagickException; ошибка чтения файла может возникнуть ещё в конструкторе. Ошибочный PHP-тип или число аргументов обрабатывает PHP binding. Точный Wand setter присваивает image->compose без проверки, принадлежит ли произвольный int поддерживаемому перечислению; для настроек сайта используйте свою разрешённую таблицу.

Именованный вариантПольза и граница
COMPOSITE_OVERОбычное наложение с учётом alpha накладки. Это не обещание сохранить первоначальный цвет при любой полупрозрачности.
COMPOSITE_MULTIPLYЗатемняющее смешивание: можно получить тонирование или смешать подготовленную тень с фоном.
COMPOSITE_SCREENОсветляющее смешивание: подходит для светлой художественной накладки.
Другие COMPOSITE_*Имеют собственную математику и требования к alpha/каналам. Оператор маски не заменяет обычное наложение автоматически.
Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagecompose">
 <refnamediv>
  <refname>Imagick::getImageCompose</refname>
  <refpurpose>Returns the composite operator associated with the image</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageCompose</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Returns the composite operator associated with the image.
  </para>
 </refsect1>

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

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </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
-->

Узнать оператор собственного исходника

Getter вернул int, равный именованной константе COMPOSITE_OVER у этого известного PNG. Число описывает настройку изображения, а не успешность чтения и не число слоёв.

Узнать оператор собственного исходникаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
$image = new Imagick(__DIR__.'/source.png');
$value = $image->getImageCompose();
$isOver = $value === Imagick::COMPOSITE_OVER;
printf("compose_is_over=%d type=%s\n", (int)$isOver, get_debug_type($value));
composeView($image, 'compose-get-minimal.png');
composeDiagnostic('image-compose-getimagecompose-minimal', ['value'=>$value,
    'value_type'=>get_debug_type($value), 'is_over'=>$isOver, 'pixels'=>composePixels($image),
    'checks'=>['getter_is_int'=>is_int($value), 'known_source_uses_over'=>$isOver]]);
echo "compose-get-minimal.png\nmetrics.json\n";

Getter вернул int, равный именованной константе COMPOSITE_OVER у этого известного PNG. Число описывает настройку изображения, а не успешность чтения и не число слоёв. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose_is_over=1 type=int
compose-get-minimal.png
metrics.json

Практическая задача чтения — проверить, почему макет получился слишком светлым или тёмным. Не угадывайте режим по числовому значению и не читайте только первый элемент списка. Следующая программа выбирает основу и накладку, записывает их настройки в metrics.json, затем получает один PNG. Две панели показывают исходную основу и готовый результат; название frame1-flattened.png здесь является именем выходного файла, а не утверждением, что второй слой сам содержит готовый рисунок.

Проверить настройки двух слоёв перед объединением

При выборе индекса 0 прочитан OVER основы, при выборе 1 — MULTIPLY накладки. Полный список объединён в один результат; картинка справа показывает именно сохранённый результат FLATTEN, а не второй исходный слой.

Проверить настройки двух слоёв перед объединениемПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
[$base, $overlay] = composeParts();
$base->setImageCompose(Imagick::COMPOSITE_OVER);
$overlay->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
$layers = new Imagick();
$layers->addImage($base); $layers->addImage($overlay);
$observed = [];
foreach (['base', 'overlay'] as $index => $name) {
    $layers->setIteratorIndex($index);
    $value = $layers->getImageCompose();
    $observed[] = ['index'=>$index, 'name'=>$name, 'compose'=>$value,
        'is_over'=>$value===Imagick::COMPOSITE_OVER,
        'is_multiply'=>$value===Imagick::COMPOSITE_MULTIPLY];
}
// Index 1 was selected, but mergeImageLayers in PHP starts from the first layer.
$result = $layers->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($base, 'frame0-base.png');
composeView($result, 'frame1-flattened.png');
$views = [new Imagick(__DIR__.'/frame0-base.png'), new Imagick(__DIR__.'/frame1-flattened.png')];
$rects = composeCompare($views, 'compose-get-workflow.png');
composeDiagnostic('image-compose-getimagecompose-workflow', ['frames'=>$observed,
    'merge_method'=>'FLATTEN', 'input_frames'=>$layers->getNumberImages(),
    'output_frames'=>$result->getNumberImages(), 'panel_geometry'=>$rects,
    'checks'=>['getter_follows_current_layer'=>array_column($observed,'compose')===[Imagick::COMPOSITE_OVER,Imagick::COMPOSITE_MULTIPLY],
        'flatten_returns_one_image'=>$result->getNumberImages()===1,
        'result_differs_from_base'=>composeHash($views[0])!==composeHash($views[1])]]);
echo "compose-get-workflow.png\nframe0-base.png\nframe1-flattened.png\nmetrics.json\nframes=2 distinct-layer-operators=1 flattened-images=1\n";

При выборе индекса 0 прочитан OVER основы, при выборе 1 — MULTIPLY накладки. Полный список объединён в один результат; картинка справа показывает именно сохранённый результат FLATTEN, а не второй исходный слой. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose-get-workflow.png
frame0-base.png
frame1-flattened.png
metrics.json
frames=2 distinct-layer-operators=1 flattened-images=1

Применить выбранный стиль к накладке и избежать ошибки слоя

Setter не перекрашивает исходник; важен нужный слой, а явный OVER в compositeImage остаётся явным
Setter не перекрашивает исходник; важен нужный слой, а явный OVER в compositeImage остаётся явным

Оператор композиции — правило, по которому цвета накладываемого слоя соединяются с уже нарисованным фоном. Здесь слой — одно изображение в списке Imagick, а не PHP-класс. $image — переменная с объектом; -> вызывает его метод; круглые скобки содержат аргументы, точка с запятой заканчивает инструкцию. Imagick::COMPOSITE_MULTIPLY — именованная целочисленная константа, а не строка с названием эффекта. Метод getImageCompose читает правило текущего изображения, setImageCompose записывает его. Переменные, объекты и список изображений и выбор текущего кадра — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::setImageCompose(int $compose): bool
$ok = $image->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
Аргумент или результатЧто означает
$compose: int, обязательныйОператор семейства Imagick::COMPOSITE_*. Выбирайте именованную константу по задаче.
bool trueСвойство текущего изображения успешно записано.
Рисунок сразу после вызоваПиксели и размеры не изменились. Результат создаёт последующая операция, использующая оператор слоя.

Официальное описание отдельно называет применение при компоновке миниатюр через montageImage. Этот способ применения сохранён как часть базового контракта; здесь реальным запуском проверяется другой конкретный путь — mergeImageLayers с FLATTEN. Из одного setter нельзя вывести, что все методы монтажа, форматные кодеки или произвольные операции автоматически прочитают это свойство.

Доступность: PECL imagick 2, PECL imagick 3. Официальные записи не содержат самостоятельных примеров кода; поле описания $compose в XML setter пустое. Setter официально объявляет ImagickException при ошибке. Текущий PHP wrapper проверяет наличие изображения у обоих методов: пустой new Imagick() приводит к ImagickException; ошибка чтения файла может возникнуть ещё в конструкторе. Ошибочный PHP-тип или число аргументов обрабатывает PHP binding. Точный Wand setter присваивает image->compose без проверки, принадлежит ли произвольный int поддерживаемому перечислению; для настроек сайта используйте свою разрешённую таблицу.

Именованный вариантПольза и граница
COMPOSITE_OVERОбычное наложение с учётом alpha накладки. Это не обещание сохранить первоначальный цвет при любой полупрозрачности.
COMPOSITE_MULTIPLYЗатемняющее смешивание: можно получить тонирование или смешать подготовленную тень с фоном.
COMPOSITE_SCREENОсветляющее смешивание: подходит для светлой художественной накладки.
Другие COMPOSITE_*Имеют собственную математику и требования к alpha/каналам. Оператор маски не заменяет обычное наложение автоматически.
Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagecompose">
 <refnamediv>
  <refname>Imagick::setImageCompose</refname>
  <refpurpose>Sets the image composite operator</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageCompose</methodname>
   <methodparam><type>int</type><parameter>compose</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image composite operator, useful for specifying how
   to composite the image thumbnail when using the
   Imagick::montageImage() method.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>compose</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 вернул bool true; getter подтвердил MULTIPLY. Компоненты RGBA8 до и после совпали, а превью осталось прежним: сохранена настройка будущего объединения.

Изменить оператор без немедленного изменения рисункаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
$image = new Imagick(__DIR__.'/source.png');
$before = composeHash($image);
$ok = $image->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
$value = $image->getImageCompose();
$same = $before === composeHash($image);
printf("set=%s compose_is_multiply=%d pixels_unchanged=%d\n",
    $ok ? 'true' : 'false', (int)($value===Imagick::COMPOSITE_MULTIPLY), (int)$same);
composeView($image, 'compose-set-minimal.png');
composeDiagnostic('image-compose-setimagecompose-minimal', ['return_value'=>$ok,
    'return_type'=>get_debug_type($ok), 'value'=>$value,
    'before_hash'=>$before, 'after_hash'=>composeHash($image),
    'checks'=>['setter_true'=>$ok===true, 'property_is_multiply'=>$value===Imagick::COMPOSITE_MULTIPLY,
        'pixels_unchanged'=>$same]]);
echo "compose-set-minimal.png\nmetrics.json\n";

Setter вернул bool true; getter подтвердил MULTIPLY. Компоненты RGBA8 до и после совпали, а превью осталось прежним: сохранена настройка будущего объединения. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
set=true compose_is_multiply=1 pixels_unchanged=1
compose-set-minimal.png
metrics.json

Требование выросло: редактор выбирает стиль over, multiply или screen. Таблица связывает эти понятные названия с разрешёнными константами; неизвестное название отклоняется. Первая панель показывает ошибку — MULTIPLY записан только в основу, а у накладки остался OVER. На этой конкретной непрозрачной основе и белом начальном холсте результат совпадает с обычным OVER; для других операторов и фонов такое совпадение не обещается. Вторая показывает настройку накладки. В последних двух случаях сохранённое свойство основы различается, но compositeImage получает один и тот же явный COMPOSITE_OVER: ожидаемо получаются одинаковые изображения.

Применить политику к накладке и разобрать ошибку выбора слоя

Строковая политика multiply проверяется по таблице разрешённых операторов. Правильная настройка накладки меняет результат FLATTEN. Последние две картинки совпадают: compositeImage использует явно переданный OVER, а не сохранённое свойство основы.

Применить политику к накладке и разобрать ошибку выбора слояПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
[$base, $overlay] = composeParts();
$policy = 'multiply';
$allowed = ['over'=>Imagick::COMPOSITE_OVER,
            'multiply'=>Imagick::COMPOSITE_MULTIPLY, 'screen'=>Imagick::COMPOSITE_SCREEN];
if (!array_key_exists($policy, $allowed)) {
    throw new InvalidArgumentException('Unknown overlay policy');
}
$wanted = $allowed[$policy];
$wrong = new Imagick(); $wrong->addImage($base); $wrong->addImage($overlay);
$wrong->setIteratorIndex(0); $wrong->setImageCompose($wanted);
$wrongLayer = $wrong->getImageCompose();
$wrong->setIteratorIndex(1); $wrongOverlay = $wrong->getImageCompose();
$wrongResult = $wrong->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($wrongResult, 'wrong-layer.png');
$correct = new Imagick(); $correct->addImage($base); $correct->addImage($overlay);
$correct->setIteratorIndex(1); $before = composeHash($correct);
$ok = $correct->setImageCompose($wanted); $selected = $correct->getImageCompose();
$same = $before === composeHash($correct);
$result = $correct->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($result, 'correct-layer.png');
$views = [new Imagick(__DIR__.'/wrong-layer.png'), new Imagick(__DIR__.'/correct-layer.png')];
$direct = [];
foreach (['over'=>Imagick::COMPOSITE_OVER, 'multiply'=>Imagick::COMPOSITE_MULTIPLY] as $name=>$property) {
    $copy = clone $base;
    $copy->setImageCompose($property);
    // Explicit OVER is the actual operator of this call, regardless of stored compose.
    $copy->compositeImage($overlay, Imagick::COMPOSITE_OVER, 0, 0);
    $filename = $name==='over' ? 'explicit-over.png' : 'explicit-multiply-property.png';
    composeView($copy, $filename); $direct[] = new Imagick(__DIR__.'/'.$filename);
    $views[] = end($direct);
}
$rects = composeCompare($views, 'compose-set-workflow.png');
$mergeChanged = composeHash($views[0]) !== composeHash($views[1]);
$explicitSame = composeHash($direct[0]) === composeHash($direct[1]);
composeDiagnostic('image-compose-setimagecompose-workflow', ['policy'=>$policy, 'wanted'=>$wanted,
    'wrong_layer_compose'=>$wrongLayer, 'wrong_overlay_compose'=>$wrongOverlay,
    'selected_layer_compose'=>$selected, 'setter_return'=>$ok, 'property_pixels_unchanged'=>$same,
    'merge_changed'=>$mergeChanged, 'explicit_same'=>$explicitSame, 'panel_geometry'=>$rects,
    'checks'=>['policy_on_overlay'=>$selected===$wanted,
        'wrong_overlay_remains_over'=>$wrongOverlay===Imagick::COMPOSITE_OVER,
        'explicit_argument_wins'=>$explicitSame, 'setter_true_and_keeps_pixels'=>$ok===true&&$same]]);
echo "compose-set-workflow.png\nwrong-layer.png\ncorrect-layer.png\nexplicit-over.png\nexplicit-multiply-property.png\nmetrics.json\n";
printf("policy=%s merge-changes=%d explicit-over-unchanged=%d\n", $policy, (int)$mergeChanged, (int)$explicitSame);

Строковая политика multiply проверяется по таблице разрешённых операторов. Правильная настройка накладки меняет результат FLATTEN. Последние две картинки совпадают: compositeImage использует явно переданный OVER, а не сохранённое свойство основы. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose-set-workflow.png
wrong-layer.png
correct-layer.png
explicit-over.png
explicit-multiply-property.png
metrics.json
policy=multiply merge-changes=1 explicit-over-unchanged=1

Выбрать оператор, прозрачность и границы применения

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

Реальная потребностьКак выбрать путь
Несколько слоёв с разными правиламиНастроить compose каждого нужного слоя и использовать операцию, которая их читает; здесь проверен FLATTEN
Разовое наложение одного PNGПередать оператор явным аргументом compositeImage; сохранённое image-compose его не заменяет
Прозрачный PNG стал чёрным в JPEGЯвно решить, на какой непрозрачный фон его положить: JPEG не хранит alpha
Цвет логотипа побледнелПроверить alpha и оператор, а не обещать исходный цвет при любом смешивании
Логотип должен повторять тканьОдного MULTIPLY недостаточно для формы складок; могут понадобиться маски и геометрическое смещение
Страницы PDF нужно сохранить отдельноНе объединять все страницы FLATTEN как будто это слои одной сцены; обрабатывать выбранные страницы отдельно

Упражнение: измените $policy с multiply на screen. Решение уже разрешено таблицей: выбранный слой 1 получит COMPOSITE_SCREEN и FLATTEN создаст осветлённый вариант. Последние две панели остаются одинаковыми, поскольку там оператор OVER передан явно. При политике over первая и вторая панели могут совпасть: сравнение зависит от задачи, а не гарантирует изменение от любого setter. Для более сильного эффекта меняют ещё и alpha накладки, но тогда сравниваются уже два параметра.

Getter и setter работают со свойством, а объединение создаёт новый растровый холст и проходит по слоям. Стоимость этих действий различается; держите размеры и число слоёв под контролем и не делайте обещаний скорости без измерений. Для вывода в браузер сформированный PNG отправляется отдельным ответом с Content-Type: image/png, без текстовой диагностики перед бинарными байтами.

Полный helper подготовки и просмотра

<?php
declare(strict_types=1);
function composeRestore():void {$raw=base64_decode((string)file_get_contents(__DIR__.'/source.png.b64'),true);if($raw===false||hash('sha256',$raw)!=='f51e5780445e0f5130a7f23112b2a00618035afd5545b8e3042c7ccff09b617c'||file_put_contents(__DIR__.'/source.png',$raw)===false){throw new RuntimeException('Own source missing or changed');}}
function composeHash(Imagick $image):string {return hash('sha256',json_encode($image->exportImagePixels(0,0,$image->getImageWidth(),$image->getImageHeight(),'RGBA',Imagick::PIXEL_CHAR),JSON_THROW_ON_ERROR));}
function composePixels(Imagick $image):array {return ['width'=>$image->getImageWidth(),'height'=>$image->getImageHeight(),'RGBA8_hash'=>composeHash($image)];}
function composeOpaque(Imagick $image):Imagick {$view=new Imagick();$view->newImage($image->getImageWidth(),$image->getImageHeight(),'white');$view->compositeImage($image,Imagick::COMPOSITE_OVER,0,0);$view->setImageType(Imagick::IMGTYPE_TRUECOLOR);return $view;}
function composeView(Imagick $image,string $filename):void {$view=composeOpaque($image);$view->setImageFormat('png');$view->setImageDepth(8);$view->setOption('png:bit-depth','8');$view->setOption('png:color-type','2');$view->setOption('png:exclude-chunk','all');if(!$view->writeImage(__DIR__.'/'.$filename)){throw new RuntimeException('PNG preview write failed');}}
function composeParts():array {
 $source=new Imagick(__DIR__.'/source.png');$base=new Imagick();$base->newImage(400,320,'white');$base->compositeImage($source,Imagick::COMPOSITE_OVER,0,0);$base->setImagePage(0,0,0,0);
 $overlay=new Imagick();$overlay->newImage(400,320,'rgba(40,170,210,0.45)');$overlay->setImagePage(0,0,0,0);
 return [$base,$overlay];
}
function composeCompare(array $images,string $filename):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 a complete 400x320 panel');}$board->compositeImage($image,Imagick::COMPOSITE_OVER,400*$i,0);$rects[]=['x'=>400*$i,'y'=>0,'width'=>400,'height'=>320];}composeView($board,$filename);return $rects;}
function composeDiagnostic(string $id,array $data):void {$doc=['schema'=>'aen-image-compose-program-diagnostics-v1','example_id'=>$id]+$data;if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION|JSON_THROW_ON_ERROR)."\n")===false){throw new RuntimeException('Diagnostic write failed');}}

Helper не скрывает target getter/setter или FLATTEN: они находятся в программах. Превью сохраняются RGB8 на белом фоне, поэтому они объясняют оформление, но не сертифицируют сохранение прозрачности исходного RGBA. Следующие шаги: наложение и тени, правило привязки кадра, последовательности изображений и работа с файлами.

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

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

Imagick::getImageComposeОператор текущего слоя: чтение

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageCompose(): int

Оператор композиции — правило, по которому цвета накладываемого слоя соединяются с уже нарисованным фоном. Здесь слой — одно изображение в списке Imagick, а не PHP-класс. $image — переменная с объектом; -> вызывает его метод; круглые скобки содержат аргументы, точка с запятой заканчивает инструкцию. Imagick::COMPOSITE_MULTIPLY — именованная целочисленная константа, а не строка с названием эффекта. Метод getImageCompose читает правило текущего изображения, setImageCompose записывает его. Переменные, объекты и список изображений и выбор текущего кадра — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::getImageCompose(): int
$operator = $image->getImageCompose();

Параметров нет. Возвращается int — оператор, сохранённый у текущего изображения. Сравнивайте его с Imagick::COMPOSITE_OVER, COMPOSITE_MULTIPLY и другими именованными константами. Getter не объединяет слои и не анализирует рисунок, чтобы угадать эффект. В последовательности сначала выберите нужный индекс: настройка основы и накладки может различаться.

В официальной записи есть неточность: сигнатура возвращает int, а абзац Return Values содержит общее обещание true при успехе. Оригинальный XML ниже сохранён полностью. Stub, PHP wrapper и реальный запуск подтверждают int с оператором, а не bool true. У известного собственного PNG в этих примерах прочитан OVER; не считайте это гарантией настроек любого загруженного документа.

Доступность: PECL imagick 2, PECL imagick 3. Официальные записи не содержат самостоятельных примеров кода; поле описания $compose в XML setter пустое. Setter официально объявляет ImagickException при ошибке. Текущий PHP wrapper проверяет наличие изображения у обоих методов: пустой new Imagick() приводит к ImagickException; ошибка чтения файла может возникнуть ещё в конструкторе. Ошибочный PHP-тип или число аргументов обрабатывает PHP binding. Точный Wand setter присваивает image->compose без проверки, принадлежит ли произвольный int поддерживаемому перечислению; для настроек сайта используйте свою разрешённую таблицу.

Именованный вариантПольза и граница
COMPOSITE_OVERОбычное наложение с учётом alpha накладки. Это не обещание сохранить первоначальный цвет при любой полупрозрачности.
COMPOSITE_MULTIPLYЗатемняющее смешивание: можно получить тонирование или смешать подготовленную тень с фоном.
COMPOSITE_SCREENОсветляющее смешивание: подходит для светлой художественной накладки.
Другие COMPOSITE_*Имеют собственную математику и требования к alpha/каналам. Оператор маски не заменяет обычное наложение автоматически.
Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.getimagecompose">
 <refnamediv>
  <refname>Imagick::getImageCompose</refname>
  <refpurpose>Returns the composite operator associated with the image</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>int</type><methodname>Imagick::getImageCompose</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Returns the composite operator associated with the image.
  </para>
 </refsect1>

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

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </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
-->

Узнать оператор собственного исходника

Getter вернул int, равный именованной константе COMPOSITE_OVER у этого известного PNG. Число описывает настройку изображения, а не успешность чтения и не число слоёв.

Узнать оператор собственного исходникаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
$image = new Imagick(__DIR__.'/source.png');
$value = $image->getImageCompose();
$isOver = $value === Imagick::COMPOSITE_OVER;
printf("compose_is_over=%d type=%s\n", (int)$isOver, get_debug_type($value));
composeView($image, 'compose-get-minimal.png');
composeDiagnostic('image-compose-getimagecompose-minimal', ['value'=>$value,
    'value_type'=>get_debug_type($value), 'is_over'=>$isOver, 'pixels'=>composePixels($image),
    'checks'=>['getter_is_int'=>is_int($value), 'known_source_uses_over'=>$isOver]]);
echo "compose-get-minimal.png\nmetrics.json\n";

Getter вернул int, равный именованной константе COMPOSITE_OVER у этого известного PNG. Число описывает настройку изображения, а не успешность чтения и не число слоёв. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose_is_over=1 type=int
compose-get-minimal.png
metrics.json

Проверить настройки двух слоёв перед объединением

При выборе индекса 0 прочитан OVER основы, при выборе 1 — MULTIPLY накладки. Полный список объединён в один результат; картинка справа показывает именно сохранённый результат FLATTEN, а не второй исходный слой.

Проверить настройки двух слоёв перед объединениемПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
[$base, $overlay] = composeParts();
$base->setImageCompose(Imagick::COMPOSITE_OVER);
$overlay->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
$layers = new Imagick();
$layers->addImage($base); $layers->addImage($overlay);
$observed = [];
foreach (['base', 'overlay'] as $index => $name) {
    $layers->setIteratorIndex($index);
    $value = $layers->getImageCompose();
    $observed[] = ['index'=>$index, 'name'=>$name, 'compose'=>$value,
        'is_over'=>$value===Imagick::COMPOSITE_OVER,
        'is_multiply'=>$value===Imagick::COMPOSITE_MULTIPLY];
}
// Index 1 was selected, but mergeImageLayers in PHP starts from the first layer.
$result = $layers->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($base, 'frame0-base.png');
composeView($result, 'frame1-flattened.png');
$views = [new Imagick(__DIR__.'/frame0-base.png'), new Imagick(__DIR__.'/frame1-flattened.png')];
$rects = composeCompare($views, 'compose-get-workflow.png');
composeDiagnostic('image-compose-getimagecompose-workflow', ['frames'=>$observed,
    'merge_method'=>'FLATTEN', 'input_frames'=>$layers->getNumberImages(),
    'output_frames'=>$result->getNumberImages(), 'panel_geometry'=>$rects,
    'checks'=>['getter_follows_current_layer'=>array_column($observed,'compose')===[Imagick::COMPOSITE_OVER,Imagick::COMPOSITE_MULTIPLY],
        'flatten_returns_one_image'=>$result->getNumberImages()===1,
        'result_differs_from_base'=>composeHash($views[0])!==composeHash($views[1])]]);
echo "compose-get-workflow.png\nframe0-base.png\nframe1-flattened.png\nmetrics.json\nframes=2 distinct-layer-operators=1 flattened-images=1\n";

При выборе индекса 0 прочитан OVER основы, при выборе 1 — MULTIPLY накладки. Полный список объединён в один результат; картинка справа показывает именно сохранённый результат FLATTEN, а не второй исходный слой. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose-get-workflow.png
frame0-base.png
frame1-flattened.png
metrics.json
frames=2 distinct-layer-operators=1 flattened-images=1
Imagick::setImageComposeОператор текущего слоя: запись

PECL imagick 2, PECL imagick 3 · imagick

Imagick::setImageCompose(int $compose): bool

Оператор композиции — правило, по которому цвета накладываемого слоя соединяются с уже нарисованным фоном. Здесь слой — одно изображение в списке Imagick, а не PHP-класс. $image — переменная с объектом; -> вызывает его метод; круглые скобки содержат аргументы, точка с запятой заканчивает инструкцию. Imagick::COMPOSITE_MULTIPLY — именованная целочисленная константа, а не строка с названием эффекта. Метод getImageCompose читает правило текущего изображения, setImageCompose записывает его. Переменные, объекты и список изображений и выбор текущего кадра — связанные объяснения.

Минимальная запись и полный официальный контракт

Imagick::setImageCompose(int $compose): bool
$ok = $image->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
Аргумент или результатЧто означает
$compose: int, обязательныйОператор семейства Imagick::COMPOSITE_*. Выбирайте именованную константу по задаче.
bool trueСвойство текущего изображения успешно записано.
Рисунок сразу после вызоваПиксели и размеры не изменились. Результат создаёт последующая операция, использующая оператор слоя.

Официальное описание отдельно называет применение при компоновке миниатюр через montageImage. Этот способ применения сохранён как часть базового контракта; здесь реальным запуском проверяется другой конкретный путь — mergeImageLayers с FLATTEN. Из одного setter нельзя вывести, что все методы монтажа, форматные кодеки или произвольные операции автоматически прочитают это свойство.

Доступность: PECL imagick 2, PECL imagick 3. Официальные записи не содержат самостоятельных примеров кода; поле описания $compose в XML setter пустое. Setter официально объявляет ImagickException при ошибке. Текущий PHP wrapper проверяет наличие изображения у обоих методов: пустой new Imagick() приводит к ImagickException; ошибка чтения файла может возникнуть ещё в конструкторе. Ошибочный PHP-тип или число аргументов обрабатывает PHP binding. Точный Wand setter присваивает image->compose без проверки, принадлежит ли произвольный int поддерживаемому перечислению; для настроек сайта используйте свою разрешённую таблицу.

Именованный вариантПольза и граница
COMPOSITE_OVERОбычное наложение с учётом alpha накладки. Это не обещание сохранить первоначальный цвет при любой полупрозрачности.
COMPOSITE_MULTIPLYЗатемняющее смешивание: можно получить тонирование или смешать подготовленную тень с фоном.
COMPOSITE_SCREENОсветляющее смешивание: подходит для светлой художественной накладки.
Другие COMPOSITE_*Имеют собственную математику и требования к alpha/каналам. Оператор маски не заменяет обычное наложение автоматически.
Полный официальный XML без сокращений
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.setimagecompose">
 <refnamediv>
  <refname>Imagick::setImageCompose</refname>
  <refpurpose>Sets the image composite operator</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::setImageCompose</methodname>
   <methodparam><type>int</type><parameter>compose</parameter></methodparam>
  </methodsynopsis>
  <para>
   Sets the image composite operator, useful for specifying how
   to composite the image thumbnail when using the
   Imagick::montageImage() method.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>compose</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 вернул bool true; getter подтвердил MULTIPLY. Компоненты RGBA8 до и после совпали, а превью осталось прежним: сохранена настройка будущего объединения.

Изменить оператор без немедленного изменения рисункаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
$image = new Imagick(__DIR__.'/source.png');
$before = composeHash($image);
$ok = $image->setImageCompose(Imagick::COMPOSITE_MULTIPLY);
$value = $image->getImageCompose();
$same = $before === composeHash($image);
printf("set=%s compose_is_multiply=%d pixels_unchanged=%d\n",
    $ok ? 'true' : 'false', (int)($value===Imagick::COMPOSITE_MULTIPLY), (int)$same);
composeView($image, 'compose-set-minimal.png');
composeDiagnostic('image-compose-setimagecompose-minimal', ['return_value'=>$ok,
    'return_type'=>get_debug_type($ok), 'value'=>$value,
    'before_hash'=>$before, 'after_hash'=>composeHash($image),
    'checks'=>['setter_true'=>$ok===true, 'property_is_multiply'=>$value===Imagick::COMPOSITE_MULTIPLY,
        'pixels_unchanged'=>$same]]);
echo "compose-set-minimal.png\nmetrics.json\n";

Setter вернул bool true; getter подтвердил MULTIPLY. Компоненты RGBA8 до и после совпали, а превью осталось прежним: сохранена настройка будущего объединения. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
set=true compose_is_multiply=1 pixels_unchanged=1
compose-set-minimal.png
metrics.json

Применить политику к накладке и разобрать ошибку выбора слоя

Строковая политика multiply проверяется по таблице разрешённых операторов. Правильная настройка накладки меняет результат FLATTEN. Последние две картинки совпадают: compositeImage использует явно переданный OVER, а не сохранённое свойство основы.

Применить политику к накладке и разобрать ошибку выбора слояПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/compose-fixture.php';
composeRestore();
[$base, $overlay] = composeParts();
$policy = 'multiply';
$allowed = ['over'=>Imagick::COMPOSITE_OVER,
            'multiply'=>Imagick::COMPOSITE_MULTIPLY, 'screen'=>Imagick::COMPOSITE_SCREEN];
if (!array_key_exists($policy, $allowed)) {
    throw new InvalidArgumentException('Unknown overlay policy');
}
$wanted = $allowed[$policy];
$wrong = new Imagick(); $wrong->addImage($base); $wrong->addImage($overlay);
$wrong->setIteratorIndex(0); $wrong->setImageCompose($wanted);
$wrongLayer = $wrong->getImageCompose();
$wrong->setIteratorIndex(1); $wrongOverlay = $wrong->getImageCompose();
$wrongResult = $wrong->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($wrongResult, 'wrong-layer.png');
$correct = new Imagick(); $correct->addImage($base); $correct->addImage($overlay);
$correct->setIteratorIndex(1); $before = composeHash($correct);
$ok = $correct->setImageCompose($wanted); $selected = $correct->getImageCompose();
$same = $before === composeHash($correct);
$result = $correct->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
composeView($result, 'correct-layer.png');
$views = [new Imagick(__DIR__.'/wrong-layer.png'), new Imagick(__DIR__.'/correct-layer.png')];
$direct = [];
foreach (['over'=>Imagick::COMPOSITE_OVER, 'multiply'=>Imagick::COMPOSITE_MULTIPLY] as $name=>$property) {
    $copy = clone $base;
    $copy->setImageCompose($property);
    // Explicit OVER is the actual operator of this call, regardless of stored compose.
    $copy->compositeImage($overlay, Imagick::COMPOSITE_OVER, 0, 0);
    $filename = $name==='over' ? 'explicit-over.png' : 'explicit-multiply-property.png';
    composeView($copy, $filename); $direct[] = new Imagick(__DIR__.'/'.$filename);
    $views[] = end($direct);
}
$rects = composeCompare($views, 'compose-set-workflow.png');
$mergeChanged = composeHash($views[0]) !== composeHash($views[1]);
$explicitSame = composeHash($direct[0]) === composeHash($direct[1]);
composeDiagnostic('image-compose-setimagecompose-workflow', ['policy'=>$policy, 'wanted'=>$wanted,
    'wrong_layer_compose'=>$wrongLayer, 'wrong_overlay_compose'=>$wrongOverlay,
    'selected_layer_compose'=>$selected, 'setter_return'=>$ok, 'property_pixels_unchanged'=>$same,
    'merge_changed'=>$mergeChanged, 'explicit_same'=>$explicitSame, 'panel_geometry'=>$rects,
    'checks'=>['policy_on_overlay'=>$selected===$wanted,
        'wrong_overlay_remains_over'=>$wrongOverlay===Imagick::COMPOSITE_OVER,
        'explicit_argument_wins'=>$explicitSame, 'setter_true_and_keeps_pixels'=>$ok===true&&$same]]);
echo "compose-set-workflow.png\nwrong-layer.png\ncorrect-layer.png\nexplicit-over.png\nexplicit-multiply-property.png\nmetrics.json\n";
printf("policy=%s merge-changes=%d explicit-over-unchanged=%d\n", $policy, (int)$mergeChanged, (int)$explicitSame);

Строковая политика multiply проверяется по таблице разрешённых операторов. Правильная настройка накладки меняет результат FLATTEN. Последние две картинки совпадают: compositeImage использует явно переданный OVER, а не сохранённое свойство основы. Сохраните example.php и два дополнительных текстовых файла архива рядом; запустите php example.php с расширением Imagick, поддержкой PNG и правом записи в папку. Helper восстанавливает собственный исходник с проверкой SHA, готовит непрозрачную основу и накладку, сохраняет RGB8-просмотры на белом фоне и metrics.json. Изучаемые вызовы и настоящее объединение слоёв остаются в программе.

Ожидаемый вывод
compose-set-workflow.png
wrong-layer.png
correct-layer.png
explicit-over.png
explicit-multiply-property.png
metrics.json
policy=multiply merge-changes=1 explicit-over-unchanged=1
Источники и обсуждения

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

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

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

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