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

Дерево руководства
Глава 351 · После фильтров и художественных эффектов
Imagick: вихрь, волна и радиальная деформация
От координатной модели и первого PNG до защищённого орнамента, полного wave и самостоятельной прозрачной ленты.
Зачем перемещать пиксели и что получится
Нужен оформительский постер: закрученный фон, волнистая лента и медальон с радиальной деформацией. Для такой задачи важно управлять координатами, размером файла и областью изменения. Собственная сетка, кольца, цветные метки и точная маркировка делают результат проверяемым. Это декоративные варианты; они не восстанавливают геометрию товара и не исправляют произвольную оптическую линзу.
Координаты (x,y) отсчитываются от верхнего левого угла: x вправо, y вниз; пиксель (0,0) — первый. Width/height — ширина/высота в пикселях, а центр whole-image операций здесь (200,160). Degrees — градусы swirl; amplitude A и length L — пиксели wave; amount implode — безразмерный коэффициент. R и r в модели обозначают нормализованный радиус/расстояние, а не PHP-аргумент implode с именем radius. Билинейная интерполяция смешивает ближайшие четыре отсчёта вокруг дробной координаты чтения; она может создать промежуточные цвета и ослабить тонкую линию. RGB0..255 — уровни сохранённого PNG8; Q означал бы внутренний максимум QuantumRange, здесь Q16=65535, но этим трём вызовам Q не нужен.


Все три модели идут от выходного пикселя к месту чтения исходника. Swirl меняет угол вокруг центра с затуханием к границе эллипса; wave выбирает вертикально смещённую строку для каждого x и добавляет место по высоте; implode меняет расстояние чтения от центра. Если координата дробная, bilinear смешивает ближайшие значения. Это не движение материальных точек и не гарантированно обратимая перестановка: мелкая надпись может потерять точность.

Самая маленькая запись
В $image уже находится загруженная копия. 90 — градусы, не поворот всего файла. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая их отделяет, ; завершает команду.
$image->swirlImage(90);$image = clone $source; создаёт независимый объект; простое присваивание его не копирует. Метод изменяет текущую картинку и возвращает bool. Не присваивайте результат метода обратно в $image: вместо изображения получите true. В полной программе if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку, clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Весь ZIP распаковывают рядом: example.php — программа, geom-fixture.php — открытый помощник ниже, source.png.b64 — текстовые Base64-байты точного PNG. Require подключает файл относительно __DIR__, папки программы. LoadGeomSource проверяет SHA256, восстанавливает source.png и возвращает Imagick. SaveGeomComparison находит максимальную высоту, добавляет белые поля коротким панелям и сохраняет RGB PNG8 без изменения масштаба. Откройте напечатанный файл просмотрщиком: stdout — имя, не байты изображения.
Imagick::VIRTUALPIXELMETHOD_EDGE — константа продолжения крайних пикселей за рамку. :: без скобок читает константу класса. Выбор сделан до clone, но wave внутри Core всё равно принудительно использует background. SetImageBackgroundColor задаёт этот фон RGB(11,22,33); это не замена всех существующих белых пикселей картинки.
<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
if (!$image->swirlImage(90)) {
throw new RuntimeException('Не удалось применить swirlImage');
}
saveGeomComparison([$source, $image], 'geom-first.png');
$source->clear();
$image->clear();
Результат: Панели: исходник и swirl(90). Центральный эллипс закручен, внешняя область сохранена. Сетка и цветные метки показывают перемещение; текст внутри области тоже деформируется. Это оформление, не поворот целого кадра. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-first.png
Полный переносимый помощник geom-fixture.php
<?php
declare(strict_types=1);
function loadGeomSource(): Imagick
{
$encoded = file_get_contents(__DIR__ . '/source.png.b64');
if ($encoded === false) {
throw new RuntimeException('Распакуйте source.png.b64 рядом с программой');
}
$bytes = base64_decode($encoded, true);
if ($bytes === false || hash('sha256', $bytes) !== '3f10beb9b6376ebbf962d73ba57b1720c336bc28a8a43034b335989c98e1df65') {
throw new RuntimeException('Повреждён исходный PNG');
}
$path = __DIR__ . '/source.png';
if (file_put_contents($path, $bytes) !== strlen($bytes)) {
throw new RuntimeException('Не удалось восстановить source.png');
}
return new Imagick($path);
}
function saveGeomComparison(array $panels, string $filename): void
{
if ($panels === []) {
throw new InvalidArgumentException('Нужны панели');
}
$height = 0;
foreach ($panels as $panel) {
if (!$panel instanceof Imagick || $panel->getImageWidth() !== 400) {
throw new InvalidArgumentException('Ширина панели должна быть 400');
}
$height = max($height, $panel->getImageHeight());
}
$output = new Imagick();
$output->newImage(400 * count($panels), $height, 'white');
$output->setImageFormat('png');
foreach ($panels as $index => $panel) {
$top = intdiv($height - $panel->getImageHeight(), 2);
if (!$output->compositeImage($panel, Imagick::COMPOSITE_OVER, 400 * $index, $top)) {
throw new RuntimeException('Не удалось собрать сравнение');
}
}
$output->setImageDepth(8);
$output->setOption('png:color-type', '2');
if (!$output->writeImage(__DIR__ . '/' . $filename)) {
throw new RuntimeException('Не удалось сохранить сравнение');
}
$output->clear();
echo $filename, "\n";
}
Function объявляет функцию; тип после двоеточия описывает результат: Imagick у загрузчика и void у сохранения. Array $panels — список объектов, foreach перебирает панели, count считает их, max выбирает высоту. Intdiv делит нацело для верхнего padding: (344−320)/2=12. Composite размещает объекты, а не меняет их размер. ===/!== строго различают false и данные, strlen считает байты; проверки чтения/хеша/записи прекращают повреждённую цепочку. Подготовка: функции, массивы, foreach, чтение и запись.
Связать выходную точку с координатой чтения
У whole-image swirl/implode центр (200,160), а область действия — нормализованный эллипс внутри 400×320. Для квадратной вырезки 192×192 центр (96,96), после вставки это (128,200) исходного постера. Вне эллипса эти ветви Core копируют исходные каналы; весь внешний прямоугольник ROI дополнительно защищён самой композицией на clone.
У swirl формула угла затухает как (1−r/R)². Degrees=360 не означает возврат каждой точки: на разных радиусах используется разный угол. У implode amount входит со знаком минус в показатель степени; положительное значение приводит к чтению дальше от центра, а видимая метка сдвигается внутрь. У wave смещаются столбцы по y; x не меняется. Синусоидальная выборка отличается от перспективной или цилиндрической проекции.
Перед полной сравнительной программой: $image, $waved, $imploded — независимые clone $source. Ниже маленькие прямые вызовы: 90 — градусы, 12/100 — пиксельные амплитуда/период, 0.5 — безразмерный amount. Wave увеличит высоту, поэтому сравнение получает холст 1600×344; короткие панели размещаются с y=12, wave целиком с y=0. WriteImage дополнительно сохраняет полный wave-controls.png, а не уменьшенную копию.
$image->swirlImage(90);
$waved->waveImage(12, 100);
$imploded->implodeImage(0.5);<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
if (!$image->swirlImage(90)) {
throw new RuntimeException('Не удалось применить swirlImage');
}
$waved = clone $source;
if (!$waved->waveImage(12, 100)) {
throw new RuntimeException('Не удалось применить waveImage');
}
$waved->setImageFormat('png');
$waved->setImageDepth(8);
$waved->setOption('png:color-type', '2');
if (!$waved->writeImage(__DIR__ . '/wave-controls.png')) {
throw new RuntimeException('Не удалось сохранить полный PNG');
}
$imploded = clone $source;
if (!$imploded->implodeImage(0.5)) {
throw new RuntimeException('Не удалось применить implodeImage');
}
saveGeomComparison([$source, $image, $waved, $imploded], 'geom-controls.png');
$source->clear();
$image->clear();
$waved->clear();
$imploded->clear();
Результат: Панели: исходник, swirl90°, wave12/100, implode0.5. Полный wave-controls.png имеет 400×344; сравнение содержит его без обрезки и resize. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 1600×344, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-controls.png
Разобрать единицы и будущую геометрию
Координаты (x,y) отсчитываются от верхнего левого угла: x вправо, y вниз; пиксель (0,0) — первый. Width/height — ширина/высота в пикселях, а центр whole-image операций здесь (200,160). Degrees — градусы swirl; amplitude A и length L — пиксели wave; amount implode — безразмерный коэффициент. R и r в модели обозначают нормализованный радиус/расстояние, а не PHP-аргумент implode с именем radius. Билинейная интерполяция смешивает ближайшие четыре отсчёта вокруг дробной координаты чтения; она может создать промежуточные цвета и ослабить тонкую линию. RGB0..255 — уровни сохранённого PNG8; Q означал бы внутренний максимум QuantumRange, здесь Q16=65535, но этим трём вызовам Q не нужен.
| Вызов | Что задаёт число | Что проверить |
|---|---|---|
| swirlImage(90) | Угол в градусах, ослабевает к краю | Это не rotate всего изображения и не период 360. |
| waveImage(12,100) | Амплитуда 12 px, период 100 px | 400×320 становится 400×344; фон за рамкой. |
| waveImage(8,80) на 336×48 | Новая высота 48+16=64 | Полный RGBA 336×64, без trim/crop. |
| implodeImage(0.5) | Безразмерный amount | Не 0.5 px / не 0.5%; центр выбирает изображение. |
| crop 192×192 → effect → composite | Локальный центр (96,96) | Снаружи прямоугольника исходные значения точны. |
Все аргументы обязательны; ни channel, ни interpolation дописать к этим сигнатурам нельзя. В exact IM7-wrapper выбран BilinearInterpolatePixel; изменение настройки image-interpolate на объекте не переключает эти три вызова. Отдельные WithMethod не являются дополнительным аргументом обычного API. Для иной версии проверяйте wrapper, а не переносите догадку из CLI.
Сначала проверьте будущие размеры и ресурсы. У wave с A=12 высота увеличится на 24; дробная A=2.25 на контрольном H41 дала45, потому что41+4.5 преобразуется в целый размер. Не выдавайте это за округление к ближайшему. Для пользовательского подбора разумны конечные ограниченные числа и L>0; эти границы — политика приложения, не заявленный полный валидатор PHP.
Защитить точные надписи и выбрать локальный центр


Полный кадр и вырезка имеют разные центры и нормализованные радиусы. Простое ограничение видимой части уже обработанного whole-image результата не равно обработке отдельного crop. Наши локальные сценарии используют ровно x=32..223,y=104..295, поэтому лента, заголовок и SKU снаружи остаются точными. Внутри вырезки работает центральный круг; его внешние углы также копируются соответствующими ветвями Core.
Надписи A/B/C/D и координаты на входе — часть растра; эффект перемещает и сглаживает эти пиксели, а не пересчитывает подписи. Измерять движение нужно по фактическому положению цветных меток или проверенной выборке координат. Swirl360 не тождественен; implode0.5 затем-0.5 не обещает восстановить оригинал. Схема обратной выборки объясняет направление, но не является независимым воспроизведением всего resampler.
В сохранённых PNG8 центр красной метки A исходно (176,200), то есть на расстоянии 48 от центра орнамента. У локального swirl180° центр её пикселей с R>190,G<100,B<90 стал примерно (162.01,166.38), расстояние 47.82: видно угловое перемещение. У локальных implode+0.5/−0.5 расстояния стали 35.84/54.41. Это центры пороговых множеств пикселей конкретной метки после интерполяции, не точные траектории каждой материальной точки; порог не распознаёт произвольный предмет.
Сохранить полный размер wave и настоящий прозрачный слой

У wave (12,100) каждый столбец имеет собственное dy от 0 до 24 пикселей; полный выход 400×344 сохраняется отдельным файлом. Обрамляющий тёмный фон задаётся image-background, а белые 12 строк над/под исходником в сравнении — только padding помощника. Менять canvas для обзора можно явно; подменять полный результат crop 320 или необъяснённым resize нельзя.
В ленте (8,80) выход 336×64, alpha имеет и 0, и 255; дробные координаты на краю могут дать промежуточное покрытие. Добавленный фон прозрачен. После сохранения PNG вновь открывается через new Imagick(path); COMPOSITE_OVER накладывает именно прочитанный слой с этим покрытием на исходный макет. Полупрозрачный край смешивается с нижними значениями. Самостоятельный RGBA и итоговый непрозрачный RGB нужны для разных задач; просмотр на белом фоне не доказывает отсутствия alpha.
В фактически сохранённой ленте 5057 пикселей полностью прозрачны, 15809 непрозрачны и 638 имеют промежуточную alpha. На вставке прозрачные места сохранили нижний слой, непрозрачные дали значения ленты; полупрозрачные совпали с моделью покрытия в пределах одного уровня PNG8. В полном wave пять столбцов x=0,25,50,75,100 проверены на целых фазах: смещения 12,24,12,0,12 пикселей. Эти отдельные свойства подтверждают геометрию и фон, а не весь независимый алгоритм ресэмплинга.
Проверить факты, потери и стоимость преобразования
Все восемь программ выполнены на PHP 8.5.11, Imagick 3.8.1, ImageMagick 7.1.1-46 Q16. Основные сравнения — RGB PNG8, полный wave тоже RGB8; лента — RGBA8. Внутренние значения при сохранении квантуются. Проверяются исходные байты, фактические размеры, stdout/stderr, padding, внешний ROI, фон и alpha; возвращаемое true и похожая картинка сами по себе этого не доказывают.
Ограниченный градиент 41×41 подтвердил нулевые swirl/wave/implode как RGBA identity в нашей сборке, swirl 360 как nonidentity, разные радиальные направления и фактическую высоту волны. Изменение image-interpolate NEAREST_PIXEL/CATROM не поменяло результаты обычных трёх методов: wrapper жёстко выбрал bilinear. Это наблюдения конкретного непрозрачного контроля, не гарантия произвольного ICC/CMYK/HDR/alpha, нескольких кадров или всех версий.
Перед внешним файлом ограничьте формат, площадь и число кадров; перед wave рассчитайте новую высоту. Вырезки, копии и новые растры требуют native-памяти. Проверяйте чтение, native-операцию и запись как отдельные отказы, не раскрывайте внутренние пути в HTTP-ошибке. Скорость относительно других эффектов не измерялась. Детали, потерянные при интерполяции, не возвращаются последующим противоположным вызовом.
Выбрать преобразование и сделать собственную вставку

- Нужен вихревой фон: swirl; точный текст добавить после или защитить область.
- Нужна волнистая лента: wave; сохранить полную новую высоту и фон/alpha.
- Нужен условный медальон: implode; amount безразмерный, центр задаётся обрабатываемым изображением.
- Нужно измерение или исправление оптики: выбрать другую модель, не выдавать декоративную деформацию за калибровку.
Упражнение: сохранить прозрачную ленту 336×64 из входа 336×48 при A=8/L=80, затем разместить в (32,32), сохранив внешний макет. Решение: clone; cropImage(336,48,32,40); setImagePage(0,0,0,0); background transparent; waveImage(8,80); PNG color-type6; writeImage; повторное чтение; COMPOSITE_OVER. Полный код — прозрачная лента. Объясните, почему белый padding основного сравнения не является фоном этого RGBA-файла.
Продолжение: художественные варианты, контуры и рельеф, локальные статистики, работа с готовыми файлами. Следующий макет начинайте с назначенного размера, маски/области и одной проверяемой цели.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Imagick::swirlImageЗакрутить фон либо только выбранный орнамент, сохранив служебные надписи.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::swirlImage(float $degrees): boolЗакрутить фон либо только выбранный орнамент, сохранив служебные надписи.
Координаты (x,y) отсчитываются от верхнего левого угла: x вправо, y вниз; пиксель (0,0) — первый. Width/height — ширина/высота в пикселях, а центр whole-image операций здесь (200,160). Degrees — градусы swirl; amplitude A и length L — пиксели wave; amount implode — безразмерный коэффициент. R и r в модели обозначают нормализованный радиус/расстояние, а не PHP-аргумент implode с именем radius. Билинейная интерполяция смешивает ближайшие четыре отсчёта вокруг дробной координаты чтения; она может создать промежуточные цвета и ослабить тонкую линию. RGB0..255 — уровни сохранённого PNG8; Q означал бы внутренний максимум QuantumRange, здесь Q16=65535, но этим трём вызовам Q не нужен.
Для каждой выходной точки внутри центрального эллипса Core вычисляет координату чтения из исходника. Угол зависит от расстояния до центра: degrees×(1−r/R)², где r — нормализованное расстояние, R — нормализованный радиус эллипса. Вне эллипса каналы копируются. Это обратная выборка, не единый поворот всех точек.

Самая маленькая запись
В $image уже находится загруженная копия. 90 — градусы, не поворот всего файла. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая их отделяет, ; завершает команду.
$image->swirlImage(90);$image = clone $source; создаёт независимый объект; простое присваивание его не копирует. Метод изменяет текущую картинку и возвращает bool. Не присваивайте результат метода обратно в $image: вместо изображения получите true. В полной программе if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку, clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::swirlImage(float $degrees): boolДля каждой выходной точки внутри центрального эллипса Core вычисляет координату чтения из исходника. Угол зависит от расстояния до центра: degrees×(1−r/R)², где r — нормализованное расстояние, R — нормализованный радиус эллипса. Вне эллипса каналы копируются. Это обратная выборка, не единый поворот всех точек.
| Аргумент | Смысл, единицы и обязательность |
|---|---|
| $degrees | Единственный обязательный float, угол в градусах. В примерах 90 и 180. Manual описывает усиление эффекта от 1 до 360, но это не жёсткая валидация диапазона и не периодичность: 360 не является тождественным преобразованием всего кадра. |
Все аргументы обязательны, default-значений нет. Channel и interpolation в этих сигнатурах отсутствуют. Возврат true при успехе, текущая картинка заменяется результатом внутри объекта. Пустой объект и native-отказ вызывают ImagickException; это расшифровка исходного [imagick.imagick.throws]. Доступность: PECL imagick 2, PECL imagick 3. Исходный XML не содержит дополнительных записей changelog.
Для внешнего ввода ограничивайте конечность параметров, площадь и будущую высоту; length>0 — наша политика разумного периода. Для implode допустим умеренный отрицательный amount: это направление деформации, а не отрицательный пиксельный радиус ядра. Не обещаем пригодность неограниченных чисел или обратимость после интерполяции.
Полный официальный XML, включая исходные описания и пример
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.swirlimage">
<refnamediv>
<refname>Imagick::swirlImage</refname>
<refpurpose>Swirls the pixels about the center of the image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<type>bool</type><methodname>Imagick::swirlImage</methodname>
<methodparam><type>float</type><parameter>degrees</parameter></methodparam>
</methodsynopsis>
<para>
Swirls the pixels about the center of the image, where degrees indicates
the sweep of the arc through which each pixel is moved. You get a more
dramatic effect as the degrees move from 1 to 360.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>degrees</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>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::swirlImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function swirlImage($imagePath, $swirl) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->swirlImage($swirl);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
]]>
</programlisting>
</example>
</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
-->
Официальный веб-пример оформлен функцией: new Imagick(realpath(path)) читает файл, метод меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Его выполняют как HTTP-ответ без постороннего вывода. Наши программы создают локальные PNG, а не проверяют сетевую выдачу. Полный исходный пример сохранён выше; функции и файлы объясняются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
if (!$image->swirlImage(90)) {
throw new RuntimeException('Не удалось применить swirlImage');
}
saveGeomComparison([$source, $image], 'geom-swirl-basic.png');
$source->clear();
$image->clear();
Результат: Панели: исходник и swirl(90). Центральный эллипс закручен, внешняя область сохранена. Сетка и цветные метки показывают перемещение; текст внутри области тоже деформируется. Это оформление, не поворот целого кадра. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-swirl-basic.png
Когда меняется требование
Для макета нужно изменить один орнамент со своим центром (128,200), не затрагивая ленту, заголовок и правую маркировку. Вырезка 192×192 переносит центр операции в середину орнамента, затем возвращается в исходное место.
CropImage(width,height,x,y) вырезает известную область; setImagePage(0,0,0,0) сбрасывает виртуальное смещение. После эффекта compositeImage(...,COMPOSITE_OVER,x,y) размещает слой на независимом исходнике. При непрозрачной вырезке меняется только её прямоугольник, при прозрачной часть исходного слоя видна сквозь alpha. Это не автоматическое распознавание объекта и не мягкая маска по его границе.

<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
$region = clone $source;
$region->cropImage(192, 192, 32, 104);
$region->setImagePage(0, 0, 0, 0);
if (!$region->swirlImage(180)) {
throw new RuntimeException('Не удалось применить swirlImage');
}
if (!$image->compositeImage($region, Imagick::COMPOSITE_OVER, 32, 104)) {
throw new RuntimeException('Не удалось вернуть орнамент');
}
$region->clear();
saveGeomComparison([$source, $image], 'geom-swirl-protected.png');
$source->clear();
$image->clear();
Результат: Справа изменён только прямоугольник x=32..223,y=104..295; все внешние пиксели точны. В нём swirl(180) закручивает круг вокруг локального центра (96,96). Внешний квадрат вырезки не является круглой маской смешивания; внутри неё есть собственный эллипс swirl. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-swirl-protected.png
Проверка и следующий выбор
Сохраняйте исходник и проверяйте маркировку в реальном размере. Интерполяция меняет значения и может ослабить текст/штрихкод; геометрический эффект не восстанавливает деталь. Если нужно сохранить надпись, задайте область до обработки или наложите текст после неё. Цвет, alpha и размеры файла проверяются отдельно. Для художественной фактуры есть уголь/скетч/масляный эффект, для тональной коррекции — растяжение диапазона.
Связанные варианты: waveImage · implodeImage.
Imagick::waveImageСохранить полный волнистый PNG и отдельную прозрачную ленту для компоновки.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::waveImage(float $amplitude, float $length): boolСохранить полный волнистый PNG и отдельную прозрачную ленту для компоновки.
Координаты (x,y) отсчитываются от верхнего левого угла: x вправо, y вниз; пиксель (0,0) — первый. Width/height — ширина/высота в пикселях, а центр whole-image операций здесь (200,160). Degrees — градусы swirl; amplitude A и length L — пиксели wave; amount implode — безразмерный коэффициент. R и r в модели обозначают нормализованный радиус/расстояние, а не PHP-аргумент implode с именем radius. Билинейная интерполяция смешивает ближайшие четыре отсчёта вокруг дробной координаты чтения; она может создать промежуточные цвета и ослабить тонкую линию. RGB0..255 — уровни сохранённого PNG8; Q означал бы внутренний максимум QuantumRange, здесь Q16=65535, но этим трём вызовам Q не нужен.
Каждый столбец смещается вертикально по синусоиде. При амплитуде A и периоде L источник читается в (x,y−dy), где dy=abs(A)+A×sin(2πx/L). Abs — модуль, sin — синус, π — математическая константа. Ширина прежняя; высота size_t(H+2×abs(A)), то есть дробная часть при положительном размере отбрасывается. Core принудительно использует background за рамкой.

Самая маленькая запись
В $image уже находится загруженная копия. 12 — амплитуда, 100 — горизонтальный период, оба в пикселях; итоговая высота увеличится. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая их отделяет, ; завершает команду.
$image->waveImage(12, 100);$image = clone $source; создаёт независимый объект; простое присваивание его не копирует. Метод изменяет текущую картинку и возвращает bool. Не присваивайте результат метода обратно в $image: вместо изображения получите true. В полной программе if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку, clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::waveImage(float $amplitude, float $length): boolКаждый столбец смещается вертикально по синусоиде. При амплитуде A и периоде L источник читается в (x,y−dy), где dy=abs(A)+A×sin(2πx/L). Abs — модуль, sin — синус, π — математическая константа. Ширина прежняя; высота size_t(H+2×abs(A)), то есть дробная часть при положительном размере отбрасывается. Core принудительно использует background за рамкой.
| Аргумент | Смысл, единицы и обязательность |
|---|---|
| $amplitude | Обязательный float, вертикальная амплитуда в пикселях. В примерах 12 для полного кадра и 8 для ленты. 0 не увеличивает высоту; отрицательное значение меняет фазу, а высота всё равно использует модуль. |
| $length | Обязательный float, горизонтальная длина одного периода в пикселях. В примерах 100 и 80. Это не итоговая ширина файла. Политика приложения требует length>0 и разумные конечные числа; не учим нулевой период как полезный ввод. |
Все аргументы обязательны, default-значений нет. Channel и interpolation в этих сигнатурах отсутствуют. Возврат true при успехе, текущая картинка заменяется результатом внутри объекта. Пустой объект и native-отказ вызывают ImagickException; это расшифровка исходного [imagick.imagick.throws]. Доступность: PECL imagick 2, PECL imagick 3. Исходный XML не содержит дополнительных записей changelog.
Условие исходного XML [imagick.method.available.0x629] означает ImageMagick 6.2.9 или новее. В официальном примере также предупреждение: wave может работать довольно медленно; наше время относительно других методов не измерялось. В исходном See also сохранены solarizeImage, oilpaintImage, embossImage, addNoiseImage и swirlImage: это соседние эффекты, а не обязательные шаги wave.
Для внешнего ввода ограничивайте конечность параметров, площадь и будущую высоту; length>0 — наша политика разумного периода. Для implode допустим умеренный отрицательный amount: это направление деформации, а не отрицательный пиксельный радиус ядра. Не обещаем пригодность неограниченных чисел или обратимость после интерполяции.
Полный официальный XML, включая исходные описания и пример
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.waveimage">
<refnamediv>
<refname>Imagick::waveImage</refname>
<refpurpose>Applies wave filter to the image</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::waveImage</methodname>
<methodparam><type>float</type><parameter>amplitude</parameter></methodparam>
<methodparam><type>float</type><parameter>length</parameter></methodparam>
</methodsynopsis>
<para>
Applies a wave filter to the image.
&imagick.method.available.0x629;
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>amplitude</parameter></term>
<listitem>
<para>
The amplitude of the wave.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>length</parameter></term>
<listitem>
<para>
The length of the wave.
</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>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title>WaveImage can be quite slow <function>Imagick::waveImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function waveImage($imagePath, $amplitude, $length) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->waveImage($amplitude, $length);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
]]>
</programlisting>
</example>
</para>
</refsect1>
<refsect1 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>Imagick::solarizeImage</function></member>
<member><function>Imagick::oilpaintImage</function></member>
<member><function>Imagick::embossImage</function></member>
<member><function>Imagick::addNoiseImage</function></member>
<member><function>Imagick::swirlImage</function></member>
</simplelist>
</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
-->
Официальный веб-пример оформлен функцией: new Imagick(realpath(path)) читает файл, метод меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Его выполняют как HTTP-ответ без постороннего вывода. Наши программы создают локальные PNG, а не проверяют сетевую выдачу. Полный исходный пример сохранён выше; функции и файлы объясняются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
if (!$image->waveImage(12, 100)) {
throw new RuntimeException('Не удалось применить waveImage');
}
$image->setImageFormat('png');
$image->setImageDepth(8);
$image->setOption('png:color-type', '2');
if (!$image->writeImage(__DIR__ . '/wave-full.png')) {
throw new RuntimeException('Не удалось сохранить полный PNG');
}
saveGeomComparison([$source, $image], 'geom-wave-full.png');
$source->clear();
$image->clear();
Результат: Полный wave-full.png имеет 400×344: исходные 320 строк плюс 24 строки при amplitude=12. Сравнение 800×344: исходник размещён с y=12 на белой подложке, wave — с y=0 без обрезки и resize. Тёмные добавленные области принадлежат wave-background RGB(11,22,33), белые поля слева — только comparison-padding. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×344, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-wave-full.png
Когда меняется требование
Нужна самостоятельная лента для последующей компоновки. Вырезаем цветную полосу 336×48, задаём transparent для новых областей, применяем wave(8,80) и сохраняем полный RGBA PNG 336×64. Затем COMPOSITE_OVER размещает её поверх исходного макета в (32,32).
CropImage(width,height,x,y) вырезает известную область; setImagePage(0,0,0,0) сбрасывает виртуальное смещение. После эффекта compositeImage(...,COMPOSITE_OVER,x,y) размещает слой на независимом исходнике. При непрозрачной вырезке меняется только её прямоугольник, при прозрачной часть исходного слоя видна сквозь alpha. Это не автоматическое распознавание объекта и не мягкая маска по его границе.
Transparent — полностью прозрачный цвет фона новых отсчётов, а не удаление похожего цвета существующей ленты. SetImageFormat(png), depth8 и png:color-type6 сохраняют RGBA PNG8 с alpha. RGB comparison использует color-type2 и белую подложку; самостоятельный wave-ribbon.png сохраняет прозрачность. Заголовок выше y=32 остаётся точным; прежняя прямая полоса под прозрачными краями специально не удаляется.
<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
$ribbon = clone $source;
$ribbon->cropImage(336, 48, 32, 40);
$ribbon->setImagePage(0, 0, 0, 0);
$ribbon->setImageBackgroundColor('transparent');
if (!$ribbon->waveImage(8, 80)) {
throw new RuntimeException('Не удалось применить waveImage');
}
$ribbon->setImageFormat('png');
$ribbon->setImageDepth(8);
$ribbon->setOption('png:color-type', '6');
if (!$ribbon->writeImage(__DIR__ . '/wave-ribbon.png')) {
throw new RuntimeException('Не удалось сохранить полный PNG');
}
$ribbon->clear();
$ribbon = new Imagick(__DIR__ . '/wave-ribbon.png');
if (!$image->compositeImage($ribbon, Imagick::COMPOSITE_OVER, 32, 32)) {
throw new RuntimeException('Не удалось разместить ленту');
}
$ribbon->clear();
saveGeomComparison([$source, $image], 'geom-wave-ribbon.png');
$source->clear();
$image->clear();
Результат: Wave-ribbon.png имеет реальные прозрачные края и непрозрачную цветную полосу. Сравнение показывает исходник и локальную вставку: снаружи её bbox x=32..367,y=32..95 пиксели точны. Transparent означает отсутствие покрытия; белый фон comparison и фон самостоятельной ленты — разные вещи. Под прозрачной частью вставки остаётся исходный макет, в том числе прежняя полоса; это размещение слоя, а не автоматическое удаление старого объекта. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-wave-ribbon.png
Проверка и следующий выбор
Сохраняйте исходник и проверяйте маркировку в реальном размере. Интерполяция меняет значения и может ослабить текст/штрихкод; геометрический эффект не восстанавливает деталь. Если нужно сохранить надпись, задайте область до обработки или наложите текст после неё. Цвет, alpha и размеры файла проверяются отдельно. Для художественной фактуры есть уголь/скетч/масляный эффект, для тональной коррекции — растяжение диапазона.
Связанные варианты: swirlImage · implodeImage.
Imagick::implodeImageПодобрать радиальное втягивание/раздувание декоративного медальона.
PECL imagick 2, PECL imagick 3 · imagick
Imagick::implodeImage(float $radius): boolПодобрать радиальное втягивание/раздувание декоративного медальона.
Координаты (x,y) отсчитываются от верхнего левого угла: x вправо, y вниз; пиксель (0,0) — первый. Width/height — ширина/высота в пикселях, а центр whole-image операций здесь (200,160). Degrees — градусы swirl; amplitude A и length L — пиксели wave; amount implode — безразмерный коэффициент. R и r в модели обозначают нормализованный радиус/расстояние, а не PHP-аргумент implode с именем radius. Билинейная интерполяция смешивает ближайшие четыре отсчёта вокруг дробной координаты чтения; она может создать промежуточные цвета и ослабить тонкую линию. RGB0..255 — уровни сохранённого PNG8; Q означал бы внутренний максимум QuantumRange, здесь Q16=65535, но этим трём вызовам Q не нужен.
PHP-аргумент с именем radius поступает в Core как amount. Для каждой выходной точки внутри центрального эллипса вычисляется factor=sin(πr/(2R))^(−amount), затем исходная координата center+factor×delta. Factor — безразмерный множитель расстояния; delta — смещение от центра. При положительном amount выходная точка читает дальше от центра, и видимый рисунок втягивается; при отрицательном — раздувается. Это не физическая линза и не исправление её аберраций.

Самая маленькая запись
В $image уже находится загруженная копия. 0.5 — безразмерный amount, хотя PHP-параметр называется radius. Стрелка -> вызывает метод объекта; скобки содержат аргументы, запятая их отделяет, ; завершает команду.
$image->implodeImage(0.5);$image = clone $source; создаёт независимый объект; простое присваивание его не копирует. Метод изменяет текущую картинку и возвращает bool. Не присваивайте результат метода обратно в $image: вместо изображения получите true. В полной программе if с ! проверяет false, throw new RuntimeException останавливает отказавшую цепочку, clear освобождает native-ресурсы после сохранения. Подготовка: объекты и методы, clone, исключения.
Сигнатура и все параметры
Imagick::implodeImage(float $radius): boolPHP-аргумент с именем radius поступает в Core как amount. Для каждой выходной точки внутри центрального эллипса вычисляется factor=sin(πr/(2R))^(−amount), затем исходная координата center+factor×delta. Factor — безразмерный множитель расстояния; delta — смещение от центра. При положительном amount выходная точка читает дальше от центра, и видимый рисунок втягивается; при отрицательном — раздувается. Это не физическая линза и не исправление её аберраций.
| Аргумент | Смысл, единицы и обязательность |
|---|---|
| $radius | Единственный обязательный float в официальной PHP-сигнатуре. В точном wrapper передаётся без масштабирования в Core amount. Используем умеренные 0.5 и -0.5; единицы безразмерные, не пиксели и не проценты/100. Геометрический радиус области выбирается Core по размеру изображения и отдельно этим параметром не задаётся. |
Все аргументы обязательны, default-значений нет. Channel и interpolation в этих сигнатурах отсутствуют. Возврат true при успехе, текущая картинка заменяется результатом внутри объекта. Пустой объект и native-отказ вызывают ImagickException; это расшифровка исходного [imagick.imagick.throws]. Доступность: PECL imagick 2, PECL imagick 3. Исходный XML не содержит дополнительных записей changelog.
Для внешнего ввода ограничивайте конечность параметров, площадь и будущую высоту; length>0 — наша политика разумного периода. Для implode допустим умеренный отрицательный amount: это направление деформации, а не отрицательный пиксельный радиус ядра. Не обещаем пригодность неограниченных чисел или обратимость после интерполяции.
Полный официальный XML, включая исходные описания и пример
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.implodeimage">
<refnamediv>
<refname>Imagick::implodeImage</refname>
<refpurpose>Creates a new image as a copy</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<modifier>public</modifier> <type>bool</type><methodname>Imagick::implodeImage</methodname>
<methodparam><type>float</type><parameter>radius</parameter></methodparam>
</methodsynopsis>
<para>
Creates a new image that is a copy of an existing one with the image pixels
"imploded" by the specified percentage.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>radius</parameter></term>
<listitem>
<para>
The radius of the implode
</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>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title> <function>Imagick::implodeImage</function></title>
<programlisting role="php">
<![CDATA[
<?php
function implodeImage($imagePath) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->implodeImage(0.0001);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
]]>
</programlisting>
</example>
</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
-->
Официальный веб-пример оформлен функцией: new Imagick(realpath(path)) читает файл, метод меняет объект, header задаёт Content-Type, getImageBlob возвращает двоичные данные для echo. Его выполняют как HTTP-ответ без постороннего вывода. Наши программы создают локальные PNG, а не проверяют сетевую выдачу. Полный исходный пример сохранён выше; функции и файлы объясняются отдельно.

<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
if (!$image->implodeImage(0.5)) {
throw new RuntimeException('Не удалось применить implodeImage');
}
saveGeomComparison([$source, $image], 'geom-implode-basic.png');
$source->clear();
$image->clear();
Результат: Панели: исходник и implode(0.5). Размер остаётся 400×320; внутри центрального эллипса меняется радиальное расположение деталей. 0.5 — безразмерный amount, не радиус 0.5 пикселя и не команда изменить размер файла на 0.5 процента. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 800×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-implode-basic.png
Когда меняется требование
Нужно сравнить две формы декоративного медальона в его собственном центре. На независимых копиях одной вырезки применим amount 0.5 и -0.5, вставим в одинаковые места и проверим защищённую внешнюю область.
CropImage(width,height,x,y) вырезает известную область; setImagePage(0,0,0,0) сбрасывает виртуальное смещение. После эффекта compositeImage(...,COMPOSITE_OVER,x,y) размещает слой на независимом исходнике. При непрозрачной вырезке меняется только её прямоугольник, при прозрачной часть исходного слоя видна сквозь alpha. Это не автоматическое распознавание объекта и не мягкая маска по его границе.
У второй копии amount=-0.5 задаёт противоположную радиальную подачу. Это знак безразмерного коэффициента, а не отрицательный радиус свёртки. Обе картинки получены из одного исходника; второй эффект не применяется поверх первого. || означает «или»: отказ любой вставки прекращает цепочку.
<?php
declare(strict_types=1);
require __DIR__ . '/geom-fixture.php';
$source = loadGeomSource();
$source->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_EDGE);
$source->setImageBackgroundColor('rgb(11,22,33)');
$image = clone $source;
$region = clone $source;
$region->cropImage(192, 192, 32, 104);
$region->setImagePage(0, 0, 0, 0);
$outward = clone $region;
if (!$region->implodeImage(0.5)) {
throw new RuntimeException('Не удалось применить implodeImage');
}
if (!$outward->implodeImage(-0.5)) {
throw new RuntimeException('Не удалось применить implodeImage');
}
$expanded = clone $source;
if (!$image->compositeImage($region, Imagick::COMPOSITE_OVER, 32, 104) || !$expanded->compositeImage($outward, Imagick::COMPOSITE_OVER, 32, 104)) {
throw new RuntimeException('Не удалось вернуть вариант медальона');
}
$region->clear();
$outward->clear();
saveGeomComparison([$source, $image, $expanded], 'geom-implode-medallion.png');
$source->clear();
$image->clear();
$expanded->clear();
Результат: Панели: исходник, локальный implode(0.5), локальный implode(-0.5). Радиальные метки показывают втягивание и раздувание. Вне прямоугольника 192×192 обе панели точны; это не доказательство взаимной обратимости: интерполяция теряет детали, а повторная операция не восстанавливает исходные пиксели. Архив содержит example.php, geom-fixture.php и source.png.b64. Распакуйте все три рядом и выполните php example.php в папке с правом записи и PHP/Imagick. Помощник проверит SHA256 и восстановит точный source.png без интернета и шрифтов при запуске. Выход откройте просмотрщиком; stdout содержит фиксированное имя сравнения. Холст 1200×320, каждая колонка шириной 400; реальная картинка центрируется по высоте на белом фоне без масштабирования. Надписи внутри исходного растра описывают вход и не пересчитываются методом.
Ожидаемый вывод
geom-implode-medallion.png
Проверка и следующий выбор
Сохраняйте исходник и проверяйте маркировку в реальном размере. Интерполяция меняет значения и может ослабить текст/штрихкод; геометрический эффект не восстанавливает деталь. Если нужно сохранить надпись, задайте область до обработки или наложите текст после неё. Цвет, alpha и размеры файла проверяются отдельно. Для художественной фактуры есть уголь/скетч/масляный эффект, для тональной коррекции — растяжение диапазона.
Связанные варианты: swirlImage · waveImage.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


