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

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

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

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

Глава 322 · От одной контрольной точки до ограниченного pixel pipeline

Imagick: пиксели, каналы, палитра, текст и метрики

25 официальных методов: точка и область пикселей, iterator, import/export, статистика каналов, histogram, colormap, текст и видимый артефакт.

Сначала результат: что должно измениться и как это доказать

Пиксельный API нужен, когда задача уже не описывается одним resize: проверить фон в углу, перекрасить ROI, передать полосу чисел алгоритму, измерить отличие от эталона или рассчитать место под подпись.

Маршрут одной операции
  1. ограничить вход: coder, width, height, число кадров и decoded cost
  2. сделать маленький несимметричный контрольный пример и назвать ожидаемый эффект
  3. выполнить один новый метод, проверить его return и фактическое состояние объекта
  4. для мутирующей операции записать отдельный PNG-кандидат и проверить размер файла
  5. освободить iterator, draw, reference и image в finally; исходник не перезаписывать

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Выбирать уровень доступа по объёму данных

НужноИнструментЦена
1–10 контрольных точекgetImagePixelColorодин ImagickPixel на точку
прямоугольная областьgetPixelRegionIteratorобъекты только для ROI; sync после изменения
последовательный проходgetPixelIteratorстроки ImagickPixel, освобождение iterator
числовой массивexportImagePixels полосамиPHP-массив намного тяжелее raw bytes
статистика/палитраchannel statistics / histogramсначала уменьшить или quantize рабочую копию

Векторные команды, текст и метрики

Координата y у текста — baseline. Шрифт, размер, antialias и padding входят в воспроизводимый контракт.

Отдельные карточки: annotateImage, drawImage, queryFontMetrics, render. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Импорт и экспорт пиксельных областей

Map определяет порядок каналов, storage — представление числа, а размер массива вычисляется до выделения памяти.

Отдельные карточки: exportImagePixels, importImagePixels. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Статистика каналов

Метрика получает смысл только вместе с channel, quantum scale, входом и порогом решения.

Отдельные карточки: getImageChannelDepth, getImageChannelKurtosis, getImageChannelMean, getImageChannelRange, getImageChannelStatistics. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Сравнение с эталоном

Reference должен иметь совместимую geometry; название metric сохраняют рядом со значением.

Отдельные карточки: getImageChannelDistortion, getImageChannelDistortions. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Устаревшие геометрические методы

Deprecated-контракт сохраняется для поддержки старого кода, но новый маршрут показывает современную замену.

Отдельные карточки: getImageChannelExtrema, getImageExtrema. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Палитра, histogram и уникальные цвета

Truecolor pixels и colormap index — разные модели. Перед доступом по индексу изображение переводят в ограниченную палитру.

Отдельные карточки: getImageColormapColor, getImageColors, getImageHistogram, setImageColormapColor, uniqueImageColors. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Преобразование цветового пространства

Метка, профиль и реальное преобразование чисел каналов — разные действия.

Отдельные карточки: getImageColorspace. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Одна контрольная точка

Точечный getter удобен для нескольких координат, но не для миллионов пикселей.

Отдельные карточки: getImagePixelColor. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Построчный и региональный iterator

После изменения ImagickPixel вызывают syncIterator; iterator освобождают в finally.

Отдельные карточки: getPixelIterator, getPixelRegionIterator. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Отделение канала

Разрушительную операцию выполняют на clone и сравнивают со source.

Отдельные карточки: separateImageChannel. Каждая содержит точную сигнатуру, параметры, два входа, отказ, альтернативу и проверку результата.

Граница доказательств и следующий прогон

  • Каждая официальная API-страница этого владельца представлена отдельной карточкой с frozen SHA.
  • У каждой карточки ровно два различающихся самодостаточных примера: синтетический и файловый.
  • Каждый пример проверяет return-контракт и реальный effect; мутирующий workflow пишет отдельный PNG-кандидат.
  • Локальный PHP 8.5.11 не загружает imagick, поэтому заявляется только php -l, а не runtime или visual pass.
  • Кандидат не подключён к shared writers, content, plugin или WordPress.

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

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

Imagick::annotateImageНанести цену, номер заказа или подпись на уже созданный холст.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::annotateImage(ImagickDraw $draw_settings, float $x, float $y, float $angle, string $text): bool

Реальная потребность. Нанести цену, номер заказа или подпись на уже созданный холст.

Что получится. Отрисовать text с настройками imagickdraw относительно baseline x,y.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::annotateImage(ImagickDraw $draw_settings, float $x, float $y, float $angle, string $text): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::annotateImage(ImagickDraw $draw_settings, float $x, float $y, float $angle, string $text): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
$draw_settingsImagickDraw; обязательныйImagickDraw со шрифтом, размером, цветом и сглаживанием
Official: The ImagickDraw object that contains settings for drawing the text
$xfloat; обязательныйгоризонтальная координата от левого края текущего raster
Official: Horizontal offset in pixels to the left of text
$yfloat; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: Vertical offset in pixels to the baseline of text
$anglefloat; обязательныйугол текста в градусах
Official: The angle at which to write the text
$textstring; обязательныйстрока для измерения или отрисовки
Official: The string to draw

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Не найденный font, неверная кодировка или слишком маленький холст обрезают текст. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Y задаёт baseline, а не верх символов; метрики шрифта отличаются.

Что выбрать рядом. Queryfontmetrics перед созданием холста; drawimage для фигур.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: нанести цену, номер заказа или подпись на уже созданный холстПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $fonts = Imagick::queryFonts('DejaVu*');
    if ($fonts === []) { $fonts = Imagick::queryFonts('*'); }
    if ($fonts === []) { throw new RuntimeException('На сервере не найден доступный шрифт'); }
    $draw = new ImagickDraw();
    $draw->setFont($fonts[0]);
    $draw->setFontSize(6.0);
    $draw->setFillColor(new ImagickPixel('#102a43'));
    $draw->setTextAntialias(true);
    $image->clear();
    $image->newImage(40, 14, new ImagickPixel('#f7fafc'));
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->annotateImage($draw, 1.0, 6.0, 0.0, 'A');
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'annotateimage-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::annotateImage',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: отрисовать text с настройками ImagickDraw относительно baseline x,yПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $fonts = Imagick::queryFonts('DejaVu*');
    if ($fonts === []) { $fonts = Imagick::queryFonts('*'); }
    if ($fonts === []) { throw new RuntimeException('На сервере не найден доступный шрифт'); }
    $draw = new ImagickDraw();
    $draw->setFont($fonts[0]);
    $draw->setFontSize(7.0);
    $draw->setFillColor(new ImagickPixel('#102a43'));
    $draw->setTextAntialias(true);
    $image->clear();
    $image->newImage(96, 24, new ImagickPixel('#f7fafc'));
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->annotateImage($draw, 1.0, 7.0, 0.0, 'SKU 42');
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'annotateimage-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::annotateImage',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$draw_settingsImagickDraw; обязательныйImagickDraw со шрифтом, размером, цветом и сглаживанием
Official: The ImagickDraw object that contains settings for drawing the text
$xfloat; обязательныйгоризонтальная координата от левого края текущего raster
Official: Horizontal offset in pixels to the left of text
$yfloat; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: Vertical offset in pixels to the baseline of text
$anglefloat; обязательныйугол текста в градусах
Official: The angle at which to write the text
$textstring; обязательныйстрока для измерения или отрисовки
Official: The string to draw
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Annotates an image with text

Description: Annotates an image with text.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: 5365e83b1b2b8ce64d231471c69e7c4d407bc34c1b0afc9d0f5233e64901252c; SHA XML: 52921317d75a0d9b215d0bc575f88f92fb57ca89213c1c274f96332674e57a98.

Связи официальной страницы. ImagickDraw::annotation, ImagickDraw::setFont. Ссылки внутри geometry/pixels уже ведут к точной карточке; внешние получат маршрут при общей интеграции.

Imagick::drawImageНарисовать рамку, линию или векторный маркер поверх изображения.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::drawImage(ImagickDraw $draw): bool

Реальная потребность. Нарисовать рамку, линию или векторный маркер поверх изображения.

Что получится. Выполнить накопленные команды imagickdraw на текущем кадре.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::drawImage(ImagickDraw $draw): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::drawImage(ImagickDraw $draw): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
$drawImagickDraw; обязательныйImagickDraw с непустым набором команд рисования
Official: The drawing operations to render on the image.

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Пустой draw-контекст возвращает успех без видимого изменения. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Координаты, stroke/fill и alpha должны быть заданы явно.

Что выбрать рядом. Annotateimage для текста; compositeimage для готового слоя.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: нарисовать рамку, линию или векторный маркер поверх изображенияПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $draw = new ImagickDraw();
    $draw->setFillColor(new ImagickPixel('#ffcc33'));
    $draw->setStrokeColor(new ImagickPixel('#102a43'));
    $draw->setStrokeWidth(1.0);
    $draw->rectangle(2.0, 2.0, 8.0, 6.0);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->drawImage($draw);
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'drawimage-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::drawImage',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: выполнить накопленные команды ImagickDraw на текущем кадреПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $draw = new ImagickDraw();
    $draw->setFillColor(new ImagickPixel('#38b2ac'));
    $draw->setStrokeColor(new ImagickPixel('#102a43'));
    $draw->setStrokeWidth(1.0);
    $draw->rectangle(2.0, 2.0, 10.0, 7.0);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->drawImage($draw);
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'drawimage-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::drawImage',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$drawImagickDraw; обязательныйImagickDraw с непустым набором команд рисования
Official: The drawing operations to render on the image.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Renders the ImagickDraw object on the current image

Description: Renders the ImagickDraw object on the current image.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: ed0a19602b0eb0876e661099b7c1fc6cc67139adaf6b5f8a7dee52a867ff77c8; SHA XML: f6c8f1c1dec3db4d76a0a041c40ee43b5bab841e9779d2e08127aa3b810980d0.

Imagick::exportImagePixelsПередать небольшую полосу пикселей алгоритму php или внешней модели.

PECL imagick 2 >=2.3.0, PECL imagick 3 · imagick

Imagick::exportImagePixels(int $x, int $y, int $width, int $height, string $map, int $STORAGE): array

Реальная потребность. Передать небольшую полосу пикселей алгоритму php или внешней модели.

Что получится. Вернуть плоский массив каналов в порядке map и типе storage.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::exportImagePixels(int $x, int $y, int $width, int $height, string $map, int $STORAGE): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::exportImagePixels(int $x, int $y, int $width, int $height, string $map, int $STORAGE): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: X-coordinate of the exported area
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: Y-coordinate of the exported area
$widthint; обязательныйширина прямоугольника/холста в пикселях
Official: Width of the exported aread
$heightint; обязательныйвысота прямоугольника/холста в пикселях
Official: Height of the exported area
$mapstring; обязательныйпорядок каналов, например RGB или RGBA
Official: Ordering of the exported pixels. For example "RGB" . Valid characters for the map are R, G, B, A, O, C, Y, M, K, I and P.
$STORAGEint; обязательныйконстанта Imagick::PIXEL_* типа возвращаемых значений
Official: Refer to this list of pixel type constants

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Экспорт всей большой rgba-картинки раздувает память из-за стоимости php-массива. При ошибке выбрасывается ImagickException.

Граница. Число элементов равно width*height*strlen(map); обрабатывайте полосами.

Что выбрать рядом. Getpixeliterator для потокового прохода или getimagepixelcolor для одной точки.

Доступность. PECL imagick 2 >=2.3.0, PECL imagick 3.

Минимальный контрольный пример: передать небольшую полосу пикселей алгоритму PHP или внешней моделиПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->exportImagePixels(0, 0, 2, 2, 'RGB', Imagick::PIXEL_CHAR);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['values' => count($result), 'first' => array_slice($result, 0, 12)];
    $checks['element_count'] = count($result) === 12;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::exportImagePixels',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть плоский массив каналов в порядке map и типе STORAGEПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->exportImagePixels(1, 1, 4, 2, 'RGBA', Imagick::PIXEL_CHAR);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['values' => count($result), 'first' => array_slice($result, 0, 12)];
    $checks['element_count'] = count($result) === 32;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::exportImagePixels',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: X-coordinate of the exported area
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: Y-coordinate of the exported area
$widthint; обязательныйширина прямоугольника/холста в пикселях
Official: Width of the exported aread
$heightint; обязательныйвысота прямоугольника/холста в пикселях
Official: Height of the exported area
$mapstring; обязательныйпорядок каналов, например RGB или RGBA
Official: Ordering of the exported pixels. For example "RGB" . Valid characters for the map are R, G, B, A, O, C, Y, M, K, I and P.
$STORAGEint; обязательныйконстанта Imagick::PIXEL_* типа возвращаемых значений
Official: Refer to this list of pixel type constants
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Exports raw image pixels

Description: Exports image pixels into an array. The map defines the ordering of the exported pixels. The size of the returned array is width * height * strlen(map) . Доступность зависит от версии ImageMagick не ниже 6.4.7.

Return: Returns an array containing the pixels values.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 9851ea110d29db3ac2ef6251eb97cf58c17ef006b800cec1ebbb217f749bbb19; SHA XML: 349c25acca27668aa92d7969157d3fed72f9fb4422d7d4fdcf7a6dd176d01a56.

Imagick::getImageChannelDepthПроверить фактическую глубину выбранного канала перед снижением качества.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageChannelDepth(int $channel): int

Реальная потребность. Проверить фактическую глубину выбранного канала перед снижением качества.

Что получится. Вернуть число значимых бит канала.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelDepth(int $channel): int либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelDepth(int $channel): int; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.

Возврат: int. Возвращается целое число; его единицы и границы названы в карточке.

Когда ломается. Официальный старый текст говорит true, но сигнатура возвращает int. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Depth кадра не равна quantum depth сборки.

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

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: проверить фактическую глубину выбранного канала перед снижением качестваПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDepth(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDepth',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть число значимых бит каналаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDepth(Imagick::CHANNEL_GREEN);
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDepth',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the depth for a particular image channel

Description: Gets the depth for a particular image channel.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: d5f80b9561a603d7c937254e0400ec25c4c3f1656123f754c332ded343c61bf9; SHA XML: 699dc730e4a061e2d163245097460783d33f94460584d1bbe4c20b4215a2e59f.

Imagick::getImageChannelDistortionИзмерить отличие одного канала результата от эталона.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageChannelDistortion(Imagick $reference, int $channel, int $metric): float

Реальная потребность. Измерить отличие одного канала результата от эталона.

Что получится. Вернуть distortion по выбранной metric и channel.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelDistortion(Imagick $reference, int $channel, int $metric): float либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelDistortion(Imagick $reference, int $channel, int $metric): float; модификаторы: public.

ПараметрТип и обязательностьКак читать
$referenceImagick; обязательныйImagick-эталон совместимой геометрии
Official: Imagick object to compare to.
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .
$metricint; обязательныйконстанта Imagick::METRIC_*; имя сохраняют вместе с числом
Official: One of the metric type constants .

Возврат: float. Возвращается число метрики; сохраняйте рядом имя metric/channel и согласованный порог.

Когда ломается. Число без имени metric и порога ничего не говорит о визуальном качестве. При ошибке выбрасывается ImagickException.

Граница. Разные метрики несопоставимы; геометрия изображений должна совпадать.

Что выбрать рядом. Getimagedistortion для общего сравнения или getimagechanneldistortions для набора каналов.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: измерить отличие одного канала результата от эталонаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $reference = clone $image;
    $reference->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [0, 0, 0]);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDistortion($reference, Imagick::CHANNEL_RED, Imagick::METRIC_ABSOLUTEERROR);
    $checks = ['return_contract' => is_float($result)];
    $effect = ['metric_value' => $result, 'metric_is_finite' => is_finite($result)];
    $checks['finite_metric'] = is_finite($result) && $result >= 0.0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDistortion',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть distortion по выбранной metric и channelПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $reference = clone $image;
    $reference->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 255, 255]);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDistortion($reference, Imagick::CHANNEL_BLUE, Imagick::METRIC_ROOTMEANSQUAREDERROR);
    $checks = ['return_contract' => is_float($result)];
    $effect = ['metric_value' => $result, 'metric_is_finite' => is_finite($result)];
    $checks['finite_metric'] = is_finite($result) && $result >= 0.0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDistortion',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$referenceImagick; обязательныйImagick-эталон совместимой геометрии
Official: Imagick object to compare to.
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .
$metricint; обязательныйконстанта Imagick::METRIC_*; имя сохраняют вместе с числом
Official: One of the metric type constants .
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Compares image channels of an image to a reconstructed image

Description: Compares one or more image channels of an image to a reconstructed image and returns the specified distortion metric.

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: ccbf80ccde77747a76bb2edbb5ab242b034b5bf07ccb4c89a263b3c4b6c7655e; SHA XML: 06143257dec05c84b19f389aba6007e930a67c401f25e7d190bf7b577d323c09.

Imagick::getImageChannelDistortionsОценить отличие нескольких каналов результата от reference одним вызовом.

PECL imagick 2 >= 2.3.0, PECL imagick 3 · imagick

Imagick::getImageChannelDistortions(Imagick $reference, int $metric, int $channel = Imagick::CHANNEL_DEFAULT): float

Реальная потребность. Оценить отличие нескольких каналов результата от reference одним вызовом.

Что получится. Вернуть агрегированное float-значение по metric и channel mask.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelDistortions(Imagick $reference, int $metric, int $channel = Imagick::CHANNEL_DEFAULT): float либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelDistortions(Imagick $reference, int $metric, int $channel = Imagick::CHANNEL_DEFAULT): float; модификаторы: public.

ПараметрТип и обязательностьКак читать
$referenceImagick; обязательныйImagick-эталон совместимой геометрии
Official: Imagick object containing the reference image
$metricint; обязательныйконстанта Imagick::METRIC_*; имя сохраняют вместе с числом
Official: Refer to this list of metric type constants .
$channelint; по умолчанию Imagick::CHANNEL_DEFAULTконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.

Возврат: float. Возвращается число метрики; сохраняйте рядом имя metric/channel и согласованный порог.

Когда ломается. Неверный channel mask скрывает изменение alpha или цвета. При ошибке выбрасывается ImagickException.

Граница. Порог настраивается на контрольном наборе, а не берётся универсальным.

Что выбрать рядом. Getimagechanneldistortion для одного явно названного канала.

Доступность. PECL imagick 2 >= 2.3.0, PECL imagick 3.

Минимальный контрольный пример: оценить отличие нескольких каналов результата от reference одним вызовомПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $reference = clone $image;
    $reference->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [0, 0, 0]);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDistortions($reference, Imagick::METRIC_ABSOLUTEERROR, Imagick::CHANNEL_ALL);
    $checks = ['return_contract' => is_float($result)];
    $effect = ['metric_value' => $result, 'metric_is_finite' => is_finite($result)];
    $checks['finite_metric'] = is_finite($result) && $result >= 0.0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDistortions',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть агрегированное float-значение по metric и channel maskПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $reference = clone $image;
    $reference->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 255, 255]);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelDistortions($reference, Imagick::METRIC_ROOTMEANSQUAREDERROR, Imagick::CHANNEL_ALL);
    $checks = ['return_contract' => is_float($result)];
    $effect = ['metric_value' => $result, 'metric_is_finite' => is_finite($result)];
    $checks['finite_metric'] = is_finite($result) && $result >= 0.0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelDistortions',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$referenceImagick; обязательныйImagick-эталон совместимой геометрии
Official: Imagick object containing the reference image
$metricint; обязательныйконстанта Imagick::METRIC_*; имя сохраняют вместе с числом
Official: Refer to this list of metric type constants .
$channelint; по умолчанию Imagick::CHANNEL_DEFAULTконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets channel distortions

Description: Compares one or more image channels of an image to a reconstructed image and returns the specified distortion metrics Доступность зависит от версии ImageMagick не ниже 6.4.4.

Return: Returns a float describing the channel distortion.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 119a859dc3e46fb8cf22a6610c75a31e187c6106d4e88f31d45198950a66e4aa; SHA XML: 6ff846feb583a0f1ca610666350367ecd45bb0dbeca1176390bc0cf7a35671cd.

Imagick::getImageChannelExtremaНайти минимум и максимум канала в legacy-коде.

PECL imagick 2, PECL imagick 3; deprecated: PECL imagick 3.4.4 · imagick

Imagick::getImageChannelExtrema(int $channel): array

Реальная потребность. Найти минимум и максимум канала в legacy-коде.

Что получится. Вернуть границы значений выбранного канала.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelExtrema(int $channel): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelExtrema(int $channel): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Метод deprecated и официальный return-текст не соответствует array-сигнатуре. При ошибке выбрасывается ImagickException.

Граница. Новый код не должен зависеть от устаревшего имени/формата.

Что выбрать рядом. Getimagechannelrange.

Доступность. PECL imagick 2, PECL imagick 3; deprecated: PECL imagick 3.4.4.

Минимальный контрольный пример: найти минимум и максимум канала в legacy-кодеПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelExtrema(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelExtrema',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть границы значений выбранного каналаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelExtrema(Imagick::CHANNEL_BLUE);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelExtrema',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the extrema for one or more image channels

Description: Gets the extrema for one or more image channels. Return value is an associative array with the keys "minima" and "maxima".

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 0ea2f648df213760923d3833f98004c45be835430f9239cf0995ab1ad983a612; SHA XML: d33e3eb3dd6eeafcee5a7250780d9c62285423a981f2a0b36effd5a2433a9c78.

Imagick::getImageChannelKurtosisОбнаружить необычно тяжёлые хвосты и асимметрию распределения яркости.

PECL imagick 2 >= 2.3.0, PECL imagick 3 · imagick

Imagick::getImageChannelKurtosis(int $channel = Imagick::CHANNEL_DEFAULT): array

Реальная потребность. Обнаружить необычно тяжёлые хвосты и асимметрию распределения яркости.

Что получится. Вернуть kurtosis и skewness выбранного канала.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelKurtosis(int $channel = Imagick::CHANNEL_DEFAULT): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelKurtosis(int $channel = Imagick::CHANNEL_DEFAULT): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; по умолчанию Imagick::CHANNEL_DEFAULTконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Статистика на маленьком/одноцветном кадре нестабильна и не объясняет причину. При ошибке выбрасывается ImagickException.

Граница. Значения полезны в сравнении с эталоном, не как абсолютный quality score.

Что выбрать рядом. Getimagechannelmean и histogram для более понятной диагностики.

Доступность. PECL imagick 2 >= 2.3.0, PECL imagick 3.

Минимальный контрольный пример: обнаружить необычно тяжёлые хвосты и асимметрию распределения яркостиПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelKurtosis(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['kurtosis' => $result['kurtosis'] ?? null, 'skewness' => $result['skewness'] ?? null];
    $checks['named_fields'] = array_key_exists('kurtosis', $result) && array_key_exists('skewness', $result);
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelKurtosis',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть kurtosis и skewness выбранного каналаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelKurtosis(Imagick::CHANNEL_GRAY);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['kurtosis' => $result['kurtosis'] ?? null, 'skewness' => $result['skewness'] ?? null];
    $checks['named_fields'] = array_key_exists('kurtosis', $result) && array_key_exists('skewness', $result);
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelKurtosis',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; по умолчанию Imagick::CHANNEL_DEFAULTконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: The getImageChannelKurtosis purpose

Description: Get the kurtosis and skewness of a specific channel. Доступность зависит от версии ImageMagick не ниже 6.4.9.

Return: Returns an array with kurtosis and skewness members.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 10d54453c6bc010769e8783bc37d9814a6998cdd5486a96047fd91df62f1e8d0; SHA XML: eae568d4c10c68037570740635ca38d9b20ae82c7ceeae5d3a46f5d733803b57.

Imagick::getImageChannelMeanОценить среднюю яркость и разброс канала для контроля экспозиции.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageChannelMean(int $channel): array

Реальная потребность. Оценить среднюю яркость и разброс канала для контроля экспозиции.

Что получится. Вернуть mean и standarddeviation.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelMean(int $channel): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelMean(int $channel): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Среднее скрывает пересветы, тени и локальные проблемы. При ошибке выбрасывается ImagickException.

Граница. Единицы зависят от quantum range сборки.

Что выбрать рядом. Getimagehistogram или getimagechannelrange для формы/границ.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: оценить среднюю яркость и разброс канала для контроля экспозицииПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelMean(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['mean' => $result['mean'] ?? null, 'standardDeviation' => $result['standardDeviation'] ?? null];
    $checks['named_fields'] = isset($result['mean'], $result['standardDeviation']);
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelMean',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть mean и standardDeviationПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelMean(Imagick::CHANNEL_GREEN);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['mean' => $result['mean'] ?? null, 'standardDeviation' => $result['standardDeviation'] ?? null];
    $checks['named_fields'] = isset($result['mean'], $result['standardDeviation']);
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelMean',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Provide any channel constant that is valid for your channel mode. To apply to more than one channel, combine channeltype constants using bitwise operators. Refer to this list of channel constants .
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the mean and standard deviation

Description: Gets the mean and standard deviation of one or more image channels.

Return: Returns an array with "mean" and "standardDeviation" members.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: df6b65c213c234bdd36257c444e16f71e7a4a79f9193d9a3c44323d810d73353; SHA XML: d0496712bfa9707d285ba1e10236d8d8b0ea56de5515c61512ca55d004e166fe.

Imagick::getImageChannelRangeПроверить, использует ли канал доступный тоновый диапазон.

PECL imagick 2 >= 2.2.1, PECL imagick 3 · imagick

Imagick::getImageChannelRange(int $channel): array

Реальная потребность. Проверить, использует ли канал доступный тоновый диапазон.

Что получится. Вернуть minima и maxima.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelRange(int $channel): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelRange(int $channel): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Границы не показывают количество пикселей на этих уровнях. При ошибке выбрасывается ImagickException.

Граница. Сравнивайте с getquantumrange, не с жёстким 255.

Что выбрать рядом. Getimagechannelmean и histogram.

Доступность. PECL imagick 2 >= 2.2.1, PECL imagick 3.

Минимальный контрольный пример: проверить, использует ли канал доступный тоновый диапазонПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelRange(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelRange',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть minima и maximaПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelRange(Imagick::CHANNEL_BLUE);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelRange',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Константа Imagick::CHANNEL_*; несколько каналов объединяют побитовым OR только когда метод это поддерживает.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets channel range

Description: Gets the range for one or more image channels. Доступность зависит от версии ImageMagick не ниже 6.4.0.

Return: Returns an array containing minima and maxima values of the channel(s).

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 96e5f725542856237349c46190d2efe47fa16f28908970ebc22e35940813d5da; SHA XML: 88250fc1824944b6b67a1442e92bdf36634cfbe929631f756059718d8b82229a.

Imagick::getImageChannelStatisticsПолучить статистику всех присутствующих каналов для диагностического отчёта.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageChannelStatistics(): array

Реальная потребность. Получить статистику всех присутствующих каналов для диагностического отчёта.

Что получится. Вернуть массив записей depth/minima/maxima/mean/standarddeviation/kurtosis/skewness.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageChannelStatistics(): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageChannelStatistics(): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Ключи каналов являются константами, а необработанный большой массив неудобен пользователю. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Показывайте только нужные поля и называйте quantum scale.

Что выбрать рядом. Точечные getimagechannelmean/range для одного канала.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: получить статистику всех присутствующих каналов для диагностического отчётаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelStatistics();
    $checks = ['return_contract' => is_array($result)];
    $channels = [];
    foreach ($result as $channel => $stats) { $channels[(string) $channel] = ['mean' => $stats['mean'] ?? null, 'standardDeviation' => $stats['standardDeviation'] ?? null]; }
    $effect = ['channels' => $channels];
    $checks['has_channel'] = $channels !== [];
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelStatistics',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть массив записей depth/minima/maxima/mean/standardDeviation/kurtosis/skewnessПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageChannelStatistics();
    $checks = ['return_contract' => is_array($result)];
    $channels = [];
    foreach ($result as $channel => $stats) { $channels[(string) $channel] = ['mean' => $stats['mean'] ?? null, 'standardDeviation' => $stats['standardDeviation'] ?? null]; }
    $effect = ['channels' => $channels];
    $checks['has_channel'] = $channels !== [];
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageChannelStatistics',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Returns statistics for each channel in the image

Description: Returns statistics for each channel in the image. The statistics include the channel depth, its minima and maxima, the mean, and the standard deviation.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: 8c8e8ec14c01facf3efe8ed71de961d152b7fabb9fc5693eef97439a38c6b73d; SHA XML: 389d9ec0d842263dc895588d50c5518a5bbb221a5bab9ea3e1a40408e2514e7b.

Imagick::getImageColormapColorПрочитать конкретную запись палитры индексированного gif/png.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageColormapColor(int $index): ImagickPixel

Реальная потребность. Прочитать конкретную запись палитры индексированного gif/png.

Что получится. Вернуть imagickpixel цвета по индексу.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageColormapColor(int $index): ImagickPixel либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageColormapColor(int $index): ImagickPixel; модификаторы: public.

ПараметрТип и обязательностьКак читать
$indexint; обязательныйиндекс записи colormap после проверки/quantize
Official: The offset into the image colormap.

Возврат: ImagickPixel. Возвращается объект цвета; пример сразу переводит его в читаемые компоненты.

Когда ломается. На truecolor-картинке ожидаемой colormap может не быть, а индекс выходит за диапазон. При ошибке выбрасывается ImagickException.

Граница. Сначала quantize и проверяйте число цветов.

Что выбрать рядом. Getimagepixelcolor для цвета координаты.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: прочитать конкретную запись палитры индексированного GIF/PNGПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->quantizeImage(4, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColormapColor(0);
    $checks = ['return_contract' => $result instanceof ImagickPixel];
    $effect = ['color' => $result->getColor(false)];
    $checks['color_object'] = $result instanceof ImagickPixel;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColormapColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть ImagickPixel цвета по индексуПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->quantizeImage(4, Imagick::COLORSPACE_RGB, 0, false, false);
    if ($image->getImageColors() < 2) { throw new LogicException('Нужны минимум две записи палитры'); }
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColormapColor(1);
    $checks = ['return_contract' => $result instanceof ImagickPixel];
    $effect = ['color' => $result->getColor(false)];
    $checks['color_object'] = $result instanceof ImagickPixel;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColormapColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$indexint; обязательныйиндекс записи colormap после проверки/quantize
Official: The offset into the image colormap.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Returns the color of the specified colormap index

Description: Returns the color of the specified colormap index.

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 26ba6f29e3cfeb072b295cbf24d366a2d22956d1dfcb84975f39b54f8493b358; SHA XML: 74c467deefd5b459dc0bef0e43a5d0cc1d28aff801e28ad904c4a123b3b8ceb5.

Imagick::getImageColorsУзнать число уникальных цветов перед выбором png-8 или truecolor.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageColors(): int

Реальная потребность. Узнать число уникальных цветов перед выбором png-8 или truecolor.

Что получится. Вернуть int количества цветов текущего кадра.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageColors(): int либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageColors(): int; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: int. Возвращается целое число; его единицы и границы названы в карточке.

Когда ломается. На фотографии полный подсчёт может быть дорогим и число само не гарантирует хороший quantize. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Сравнивайте видимый результат и размер файла.

Что выбрать рядом. Getimagehistogram для цветов и их частот.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: узнать число уникальных цветов перед выбором PNG-8 или truecolorПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->quantizeImage(8, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColors();
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColors',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть int количества цветов текущего кадраПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->quantizeImage(16, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColors();
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColors',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the number of unique colors in the image

Description: Gets the number of unique colors in the image.

Return: Returns an int , the number of unique colors in the image.

Errors: —

Changelog: —

SHA страницы: 48dec78fec84524fcc56e7fad3ef4c2a01ea3ba212aad7658fff83cc96663161; SHA XML: db0db20a74630acfacf33167bda1c5f3e5d67b981d585f5085c68dffdf62023e.

Imagick::getImageColorspaceПроверить заявленное цветовое пространство перед экспортом.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageColorspace(): int

Реальная потребность. Проверить заявленное цветовое пространство перед экспортом.

Что получится. Вернуть константу colorspace_*.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageColorspace(): int либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageColorspace(): int; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: int. Возвращается целое число; его единицы и границы названы в карточке.

Когда ломается. Метка colorspace не доказывает наличие и корректность icc profile. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Назначение и преобразование пространства — разные действия.

Что выбрать рядом. Getimageprofiles и transformimagecolorspace/profileimage.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: проверить заявленное цветовое пространство перед экспортомПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColorspace();
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColorspace',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть константу COLORSPACE_*Пример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageColorspace();
    $checks = ['return_contract' => is_int($result)];
    $effect = ['value' => $result];
    $checks['non_negative'] = $result >= 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageColorspace',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the image colorspace

Description: Gets the image colorspace.

Return: Returns an integer which can be compared against COLORSPACE constants .

Errors: —

Changelog: —

SHA страницы: e274f1615104bfa80c872247f84700d6c77018768aa8fbc1b5733b5c1e926bfb; SHA XML: 5ebbc8dd5877df293510f7a9805b09ec224e71b56e696f6337cc2956a98414d6.

Imagick::getImageExtremaПолучить общий минимум/максимум пиксельных значений в legacy-коде.

PECL imagick 2, PECL imagick 3; deprecated: PECL imagick 3.4.4 · imagick

Imagick::getImageExtrema(): array

Реальная потребность. Получить общий минимум/максимум пиксельных значений в legacy-коде.

Что получится. Вернуть min и max.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageExtrema(): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageExtrema(): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Метод deprecated и объединяет каналы, скрывая проблемный канал. При ошибке выбрасывается ImagickException.

Граница. Новый код должен использовать channel-aware измерение.

Что выбрать рядом. Getimagechannelrange.

Доступность. PECL imagick 2, PECL imagick 3; deprecated: PECL imagick 3.4.4.

Минимальный контрольный пример: получить общий минимум/максимум пиксельных значений в legacy-кодеПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageExtrema();
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageExtrema',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть min и maxПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageExtrema();
    $checks = ['return_contract' => is_array($result)];
    $effect = ['range' => aenBound($result)];
    $checks['range_pair'] = count($result) >= 2;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageExtrema',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the extrema for the image

Description: Gets the extrema for the image. Returns an associative array with the keys "min" and "max".

Return: Returns an associative array with the keys "min" and "max".

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: dec9598f1865e17bfc060d1a51935067539f0e0c09f07d7359555d3db864eaa7; SHA XML: 5ffe9b001b03a90cb9756f09f42ab8214ae2fbecab80e5a1757ef8dcd27e593d.

Imagick::getImageHistogramНайти доминирующие цвета и частоты на небольшой палитре.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImageHistogram(): array

Реальная потребность. Найти доминирующие цвета и частоты на небольшой палитре.

Что получится. Вернуть массив imagickpixel с color count.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImageHistogram(): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImageHistogram(): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Полная фотография создаёт множество объектов и расходует память. При ошибке выбрасывается ImagickException.

Граница. Сначала уменьшайте/quantize копию или работайте с выборкой.

Что выбрать рядом. Getimagecolors для числа цветов; exportimagepixels полосами.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: найти доминирующие цвета и частоты на небольшой палитреПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->quantizeImage(8, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageHistogram();
    $checks = ['return_contract' => is_array($result)];
    $histogram = [];
    foreach (array_slice($result, 0, 5) as $pixel) { $histogram[] = ['color' => $pixel->getColor(false), 'count' => $pixel->getColorCount()]; }
    $effect = ['entries' => count($result), 'sample' => $histogram];
    $checks['has_colors'] = count($result) > 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageHistogram',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть массив ImagickPixel с color countПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->quantizeImage(16, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImageHistogram();
    $checks = ['return_contract' => is_array($result)];
    $histogram = [];
    foreach (array_slice($result, 0, 5) as $pixel) { $histogram[] = ['color' => $pixel->getColor(false), 'count' => $pixel->getColorCount()]; }
    $effect = ['entries' => count($result), 'sample' => $histogram];
    $checks['has_colors'] = count($result) > 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImageHistogram',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Gets the image histogram

Description: Returns the image histogram as an array of ImagickPixel objects.

Return: Returns the image histogram as an array of ImagickPixel objects.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: e0091779992559a0848de3fab71e26c35abe520008b35ea49999cc93033fd1fc; SHA XML: 4d0c8382b5406ea892356fa7d0c69802253156493d7d17ca3cb5eaaa1aafaf07.

Imagick::getImagePixelColorПроверить цвет контрольной точки или угол фона.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getImagePixelColor(int $x, int $y): ImagickPixel

Реальная потребность. Проверить цвет контрольной точки или угол фона.

Что получится. Вернуть imagickpixel по x,y.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getImagePixelColor(int $x, int $y): ImagickPixel либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getImagePixelColor(int $x, int $y): ImagickPixel; модификаторы: public.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The x-coordinate of the pixel
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The y-coordinate of the pixel

Возврат: ImagickPixel. Возвращается объект цвета; пример сразу переводит его в читаемые компоненты.

Когда ломается. Цикл из миллионов таких вызовов очень медленный из-за объектов. При ошибке выбрасывается ImagickException.

Граница. Координаты должны попадать в текущий кадр и учитывать предыдущий crop.

Что выбрать рядом. Getpixeliterator или exportimagepixels для области.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: проверить цвет контрольной точки или угол фонаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImagePixelColor(0, 0);
    $checks = ['return_contract' => $result instanceof ImagickPixel];
    $effect = ['color' => $result->getColor(false)];
    $checks['color_object'] = $result instanceof ImagickPixel;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImagePixelColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть ImagickPixel по x,yПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getImagePixelColor(11, 7);
    $checks = ['return_contract' => $result instanceof ImagickPixel];
    $effect = ['color' => $result->getColor(false)];
    $checks['color_object'] = $result instanceof ImagickPixel;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getImagePixelColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The x-coordinate of the pixel
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The y-coordinate of the pixel
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Returns the color of the specified pixel

Description: Returns the color of the specified pixel.

Return: Returns an ImagickPixel instance for the color at the coordinates given.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: dd1f55dd26c8286070b5e7642ea99aa3a9fb2f62321026e98e34dc685b1cf575; SHA XML: 572b702352bef2cef940c509bc84a2f7e9761e5e4301031eb3c5bb24804bf4d4.

Imagick::getPixelIteratorПройти изображение построчно без создания отдельного запроса на каждую координату.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getPixelIterator(): ImagickPixelIterator

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

Что получится. Вернуть imagickpixeliterator по всему кадру.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getPixelIterator(): ImagickPixelIterator либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getPixelIterator(): ImagickPixelIterator; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: ImagickPixelIterator. Возвращается iterator; пример проходит область и освобождает iterator в finally.

Когда ломается. После изменения пикселей без synciterator результат не сохранится. При ошибке выбрасывается ImagickException.

Граница. Каждая строка всё равно содержит объекты imagickpixel; освобождайте iterator.

Что выбрать рядом. Exportimagepixels полосами для числового массива.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: пройти изображение построчно без создания отдельного запроса на каждую координатуПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getPixelIterator();
    $checks = ['return_contract' => $result instanceof ImagickPixelIterator];
    $iterator = $result;
    $rowsVisited = 0; $pixelsVisited = 0;
    foreach ($iterator as $row) { ++$rowsVisited; $pixelsVisited += count($row); }
    $effect = ['rows' => $rowsVisited, 'pixels' => $pixelsVisited];
    $checks['all_pixels_seen'] = $pixelsVisited === $image->getImageWidth() * $image->getImageHeight();
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getPixelIterator',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть ImagickPixelIterator по всему кадруПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getPixelIterator();
    $checks = ['return_contract' => $result instanceof ImagickPixelIterator];
    $iterator = $result;
    $rowsVisited = 0; $pixelsVisited = 0;
    foreach ($iterator as $row) { ++$rowsVisited; $pixelsVisited += count($row); }
    $effect = ['rows' => $rowsVisited, 'pixels' => $pixelsVisited];
    $checks['all_pixels_seen'] = $pixelsVisited === $image->getImageWidth() * $image->getImageHeight();
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getPixelIterator',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Returns a MagickPixelIterator

Description: Returns a MagickPixelIterator.

Return: Returns an ImagickPixelIterator on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 1826241a92ded92c6c1c60ff5a8293b442e3e1d26a366aa1ff2bbd881962abb9; SHA XML: b21c4bec5589ffb78a0e9dc46819749f6b28c07cd5d4a4c3423f5ba4426496a9.

Imagick::getPixelRegionIteratorИзменить или измерить только небольшой roi вместо всего кадра.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::getPixelRegionIterator(int $x, int $y, int $columns, int $rows): ImagickPixelIterator

Реальная потребность. Изменить или измерить только небольшой roi вместо всего кадра.

Что получится. Вернуть iterator ограниченной области x,y,columns,rows.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::getPixelRegionIterator(int $x, int $y, int $columns, int $rows): ImagickPixelIterator либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::getPixelRegionIterator(int $x, int $y, int $columns, int $rows): ImagickPixelIterator; модификаторы: public.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The x-coordinate of the region.
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The y-coordinate of the region.
$columnsint; обязательныйцелевая ширина или ширина области в пикселях
Official: The width of the region.
$rowsint; обязательныйцелевая высота или высота области в пикселях
Official: The height of the region.

Возврат: ImagickPixelIterator. Возвращается iterator; пример проходит область и освобождает iterator в finally.

Когда ломается. Область вне кадра и забытый synciterator приводят к ошибке или отсутствию эффекта. При ошибке выбрасывается ImagickException.

Граница. Region coordinates относятся к текущему raster.

Что выбрать рядом. Crop clone + getpixeliterator или exportimagepixels.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: изменить или измерить только небольшой ROI вместо всего кадраПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getPixelRegionIterator(1, 1, 3, 2);
    $checks = ['return_contract' => $result instanceof ImagickPixelIterator];
    $iterator = $result;
    $changed = 0;
    foreach ($iterator as $row) { foreach ($row as $pixel) { $pixel->setColor('#e63946'); ++$changed; } $iterator->syncIterator(); }
    $effect = ['changed_pixels' => $changed, 'signature_before' => $before['signature'], 'signature_after' => $image->getImageSignature()];
    $checks['region_size'] = $changed === 6;
    $checks['pixels_changed'] = $image->getImageSignature() !== $before['signature'];
    $artifact = __DIR__ . '/out/' . 'getpixelregioniterator-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getPixelRegionIterator',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть iterator ограниченной области x,y,columns,rowsПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->getPixelRegionIterator(4, 2, 4, 3);
    $checks = ['return_contract' => $result instanceof ImagickPixelIterator];
    $iterator = $result;
    $changed = 0;
    foreach ($iterator as $row) { foreach ($row as $pixel) { $pixel->setColor('#4361ee'); ++$changed; } $iterator->syncIterator(); }
    $effect = ['changed_pixels' => $changed, 'signature_before' => $before['signature'], 'signature_after' => $image->getImageSignature()];
    $checks['region_size'] = $changed === 12;
    $checks['pixels_changed'] = $image->getImageSignature() !== $before['signature'];
    $artifact = __DIR__ . '/out/' . 'getpixelregioniterator-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::getPixelRegionIterator',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The x-coordinate of the region.
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The y-coordinate of the region.
$columnsint; обязательныйцелевая ширина или ширина области в пикселях
Official: The width of the region.
$rowsint; обязательныйцелевая высота или высота области в пикселях
Official: The height of the region.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Get an ImagickPixelIterator for an image section

Description: Get an ImagickPixelIterator for an image section.

Return: Returns an ImagickPixelIterator for an image section.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 692b618c5bece5a25552a2e22f8486097d66fd2d6aa1dc31418362d4af619557; SHA XML: bcf6eaa6b44ff8086620a5bfea857c1297cd08c705b0bdfccfd47004375034fa.

Imagick::importImagePixelsСоздать небольшой растр из массива rgb/rgba данных датчика или алгоритма.

PECL imagick 2 >= 2.3.0, PECL imagick 3 · imagick

Imagick::importImagePixels(int $x, int $y, int $width, int $height, string $map, int $storage, array $pixels): bool

Реальная потребность. Создать небольшой растр из массива rgb/rgba данных датчика или алгоритма.

Что получится. Записать плоский pixel array в прямоугольную область.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::importImagePixels(int $x, int $y, int $width, int $height, string $map, int $storage, array $pixels): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::importImagePixels(int $x, int $y, int $width, int $height, string $map, int $storage, array $pixels): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The image x position
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The image y position
$widthint; обязательныйширина прямоугольника/холста в пикселях
Official: The image width
$heightint; обязательныйвысота прямоугольника/холста в пикселях
Official: The image height
$mapstring; обязательныйпорядок каналов, например RGB или RGBA
Official: Map of pixel ordering as a string. This can be for example RGB . The value can be any combination or order of R = red, G = green, B = blue, A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan, Y = yellow, M = magenta, K = black, I = intensity (for grayscale), P = pad.
$storageint; обязательныйконстанта Imagick::PIXEL_* типа входных значений
Official: The pixel storage method. Refer to this list of pixel constants .
$pixelsarray; обязательныйплоский массив width*height*число_каналов
Official: The array of pixels

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Несовпадение числа элементов, map и storage искажает каналы или вызывает исключение. При ошибке выбрасывается ImagickException.

Граница. Проверяйте width*height*channels и диапазон типа storage.

Что выбрать рядом. Imagickpixeliterator для пошаговой записи.

Доступность. PECL imagick 2 >= 2.3.0, PECL imagick 3.

Минимальный контрольный пример: создать небольшой растр из массива RGB/RGBA данных датчика или алгоритмаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->clear();
    $image->newImage(12, 8, new ImagickPixel('transparent'));
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->importImagePixels(0, 0, 2, 2, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255]);
    $checks = ['return_contract' => $result === true];
    $roundTrip = $image->exportImagePixels(0, 0, 2, 2, 'RGB', Imagick::PIXEL_CHAR);
    $effect = ['round_trip_values' => count($roundTrip), 'first' => array_slice($roundTrip, 0, 12)];
    $checks['round_trip_size'] = count($roundTrip) === 12;
    $artifact = __DIR__ . '/out/' . 'importimagepixels-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::importImagePixels',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: записать плоский pixel array в прямоугольную областьПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->clear();
    $image->newImage(12, 8, new ImagickPixel('transparent'));
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->importImagePixels(2, 2, 3, 2, 'RGBA', Imagick::PIXEL_CHAR, [255, 128, 0, 255, 0, 128, 255, 255, 128, 0, 255, 255, 255, 255, 255, 192, 32, 32, 32, 255, 0, 0, 0, 255]);
    $checks = ['return_contract' => $result === true];
    $roundTrip = $image->exportImagePixels(2, 2, 3, 2, 'RGBA', Imagick::PIXEL_CHAR);
    $effect = ['round_trip_values' => count($roundTrip), 'first' => array_slice($roundTrip, 0, 12)];
    $checks['round_trip_size'] = count($roundTrip) === 24;
    $artifact = __DIR__ . '/out/' . 'importimagepixels-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::importImagePixels',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$xint; обязательныйгоризонтальная координата от левого края текущего raster
Official: The image x position
$yint; обязательныйвертикальная координата от верхнего края; у текста это baseline
Official: The image y position
$widthint; обязательныйширина прямоугольника/холста в пикселях
Official: The image width
$heightint; обязательныйвысота прямоугольника/холста в пикселях
Official: The image height
$mapstring; обязательныйпорядок каналов, например RGB или RGBA
Official: Map of pixel ordering as a string. This can be for example RGB . The value can be any combination or order of R = red, G = green, B = blue, A = alpha (0 is transparent), O = opacity (0 is opaque), C = cyan, Y = yellow, M = magenta, K = black, I = intensity (for grayscale), P = pad.
$storageint; обязательныйконстанта Imagick::PIXEL_* типа входных значений
Official: The pixel storage method. Refer to this list of pixel constants .
$pixelsarray; обязательныйплоский массив width*height*число_каналов
Official: The array of pixels
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Imports image pixels

Description: Imports pixels from an array into an image. The map is usually 'RGB'. This method imposes the following constraints for the parameters: amount of pixels in the array must match width x height x length of the map. Доступность зависит от версии ImageMagick не ниже 6.4.5.

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: cfa4e170b51b62d27d089cbaa0866d61a512a63c4299dfe3f2ed3d6b64cf6156; SHA XML: 7aa61fadbb02d4a333a7846403742bfbc2637c0da304a69a04ba74cdd659115b.

Imagick::queryFontMetricsДо рендеринга рассчитать холст для цены или многострочной подписи.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::queryFontMetrics(ImagickDraw $properties, string $text, bool $multiline = ?): array

Реальная потребность. До рендеринга рассчитать холст для цены или многострочной подписи.

Что получится. Вернуть метрики текста для конкретных draw/font settings.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::queryFontMetrics(ImagickDraw $properties, string $text, bool $multiline = ?): array либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::queryFontMetrics(ImagickDraw $properties, string $text, bool $multiline = ?): array; модификаторы: public.

ПараметрТип и обязательностьКак читать
$propertiesImagickDraw; обязательныйImagickDraw с font properties
Official: ImagickDraw object containing font properties
$textstring; обязательныйстрока для измерения или отрисовки
Official: The text
$multilinebool; по умолчанию Noneучитывать многострочную раскладку; null оставляет autodetect
Official: Multiline parameter. If left empty it is autodetected

Возврат: array. Возвращается массив. В примере проверяются конкретные ключи или число элементов, а не только сам тип.

Когда ломается. Отсутствующий font вызывает ошибку, а glyph overhang может выходить за textwidth/textheight. При ошибке выбрасывается ImagickException.

Граница. Оставляйте padding и проверяйте реальный trim на целевых шрифтах.

Что выбрать рядом. Сначала большой прозрачный холст + annotateimage + trimimage для сложной типографики.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: до рендеринга рассчитать холст для цены или многострочной подписиПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $fonts = Imagick::queryFonts('DejaVu*');
    if ($fonts === []) { $fonts = Imagick::queryFonts('*'); }
    if ($fonts === []) { throw new RuntimeException('На сервере не найден доступный шрифт'); }
    $draw = new ImagickDraw();
    $draw->setFont($fonts[0]);
    $draw->setFontSize(6.0);
    $draw->setFillColor(new ImagickPixel('#102a43'));
    $draw->setTextAntialias(true);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->queryFontMetrics($draw, 'PHP', false);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['textWidth' => $result['textWidth'] ?? null, 'textHeight' => $result['textHeight'] ?? null, 'ascender' => $result['ascender'] ?? null, 'descender' => $result['descender'] ?? null];
    $checks['positive_box'] = ($result['textWidth'] ?? 0) > 0 && ($result['textHeight'] ?? 0) > 0;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::queryFontMetrics',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: вернуть метрики текста для конкретных draw/font settingsПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $fonts = Imagick::queryFonts('DejaVu*');
    if ($fonts === []) { $fonts = Imagick::queryFonts('*'); }
    if ($fonts === []) { throw new RuntimeException('На сервере не найден доступный шрифт'); }
    $draw = new ImagickDraw();
    $draw->setFont($fonts[0]);
    $draw->setFontSize(7.0);
    $draw->setFillColor(new ImagickPixel('#102a43'));
    $draw->setTextAntialias(true);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->queryFontMetrics($draw, "Order\n42", true);
    $checks = ['return_contract' => is_array($result)];
    $effect = ['textWidth' => $result['textWidth'] ?? null, 'textHeight' => $result['textHeight'] ?? null, 'ascender' => $result['ascender'] ?? null, 'descender' => $result['descender'] ?? null];
    $checks['positive_box'] = ($result['textWidth'] ?? 0) > 0 && ($result['textHeight'] ?? 0) > 0;
    $textCanvas = new Imagick();
    $canvasWidth = (int) ceil(($result['textWidth'] ?? 0) + 8);
    $canvasHeight = (int) ceil(($result['textHeight'] ?? 0) + 8);
    $textCanvas->newImage($canvasWidth, $canvasHeight, new ImagickPixel('transparent'));
    $textCanvas->setImageFormat('png');
    $textCanvas->annotateImage($draw, 4.0, 4.0 + (float) ($result['ascender'] ?? 0), 0.0, "Order\n42");
    $artifact = __DIR__ . '/out/queryfontmetrics-workflow.png';
    $textCanvas->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::queryFontMetrics',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$propertiesImagickDraw; обязательныйImagickDraw с font properties
Official: ImagickDraw object containing font properties
$textstring; обязательныйстрока для измерения или отрисовки
Official: The text
$multilinebool; по умолчанию Noneучитывать многострочную раскладку; null оставляет autodetect
Official: Multiline parameter. If left empty it is autodetected
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Returns an array representing the font metrics

Description: Returns a multi-dimensional array representing the font metrics.

Return: Returns a multi-dimensional array representing the font metrics.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 2b532a7bdc7b81bf45d5e77f34b72846f8ce7586cf22fc70d0503aca962cad55; SHA XML: cb529686a38df3190a935b129be9a3f4338f9b66d54441e5a81976183c1b2708.

Imagick::renderЯвно завершить накопленный drawing workflow там, где binding требует render.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::render(): bool

Реальная потребность. Явно завершить накопленный drawing workflow там, где binding требует render.

Что получится. Попросить imagick отрисовать предшествующие команды.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::render(): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::render(): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Без предшествующих drawing-команд вызов не создаёт видимого результата. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Обычный php-код чаще применяет imagickdraw через drawimage/annotateimage.

Что выбрать рядом. Drawimage с явно заполненным imagickdraw.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: явно завершить накопленный drawing workflow там, где binding требует renderПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $draw = new ImagickDraw();
    $draw->setFillColor(new ImagickPixel('#ffcc33'));
    $draw->setStrokeColor(new ImagickPixel('#102a43'));
    $draw->setStrokeWidth(1.0);
    $draw->rectangle(2.0, 2.0, 8.0, 6.0);
    $image->drawImage($draw);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->render();
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $artifact = __DIR__ . '/out/' . 'render-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::render',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: попросить Imagick отрисовать предшествующие командыПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $draw = new ImagickDraw();
    $draw->setFillColor(new ImagickPixel('#38b2ac'));
    $draw->setStrokeColor(new ImagickPixel('#102a43'));
    $draw->setStrokeWidth(1.0);
    $draw->rectangle(2.0, 2.0, 10.0, 7.0);
    $image->drawImage($draw);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->render();
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $artifact = __DIR__ . '/out/' . 'render-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::render',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Renders all preceding drawing commands

Description: Renders all preceding drawing commands.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: d5fd30fe10e4884ba247d3ce31ac5a387b38b6fdf59d2af3093af5e18e74260e; SHA XML: 0a6b90b05d0abc83474ae6d9693fb9f89dbc14b49ff749c3e11a2cc050941269.

Imagick::separateImageChannelПолучить отдельную grayscale-карту красного, зелёного, синего или alpha канала.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::separateImageChannel(int $channel): bool

Реальная потребность. Получить отдельную grayscale-карту красного, зелёного, синего или alpha канала.

Что получится. Оставить в кадре выбранный channel как отдельное изображение.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::separateImageChannel(int $channel): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::separateImageChannel(int $channel): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Which 'channel' to return. For colorspaces other than RGB, you can still use the CHANNEL_RED, CHANNEL_GREEN, CHANNEL_BLUE constants to indicate the 1st, 2nd and 3rd channels.

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Номер канала без константы нечитаем, а rgb-константы в других spaces обозначают порядковые каналы. При ошибке выбрасывается ImagickException.

Граница. Операция меняет текущий объект; работайте с clone.

Что выбрать рядом. Exportimagepixels с одноканальным map для чисел.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: получить отдельную grayscale-карту красного, зелёного, синего или alpha каналаПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->separateImageChannel(Imagick::CHANNEL_RED);
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'separateimagechannel-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::separateImageChannel',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: оставить в кадре выбранный channel как отдельное изображениеПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->separateImageChannel(Imagick::CHANNEL_BLUE);
    $checks = ['return_contract' => $result === true];
    $afterGeometry = $image->getImageGeometry();
    $afterPage = $image->getImagePage();
    $afterCorner = $image->getImagePixelColor(0, 0)->getColor(false);
    $afterSignature = $image->getImageSignature();
    $effect = ['before' => $before, 'after' => ['geometry' => $afterGeometry, 'page' => $afterPage, 'corner' => $afterCorner, 'signature' => $afterSignature]];
    $checks['non_empty_raster'] = $image->getImageWidth() > 0 && $image->getImageHeight() > 0;
    $checks['observable_change'] = $afterSignature !== $before['signature'] || $afterGeometry !== $before['geometry'];
    $artifact = __DIR__ . '/out/' . 'separateimagechannel-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::separateImageChannel',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$channelint; обязательныйконстанта Imagick::CHANNEL_* или допустимая комбинация
Official: Which 'channel' to return. For colorspaces other than RGB, you can still use the CHANNEL_RED, CHANNEL_GREEN, CHANNEL_BLUE constants to indicate the 1st, 2nd and 3rd channels.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Separates a channel from the image

Description: Separates a channel from the image and returns a grayscale image. A channel is a particular color component of each pixel in the image.

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 5f98a66ac4d7506c51ad37660bdf01bc84ce915566b19bf6b8741f1547670863; SHA XML: 7ad656daf1f85382108720b84e30b8787072dfb1926e8c847c2ea107c2206542.

Imagick::setImageColormapColorЗаменить конкретный цвет индексированной иконки без обхода всех пикселей.

PECL imagick 2, PECL imagick 3 · imagick

Imagick::setImageColormapColor(int $index, ImagickPixel $color): bool

Реальная потребность. Заменить конкретный цвет индексированной иконки без обхода всех пикселей.

Что получится. Изменить запись palette по index.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::setImageColormapColor(int $index, ImagickPixel $color): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::setImageColormapColor(int $index, ImagickPixel $color): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
$indexint; обязательныйиндекс записи colormap после проверки/quantize
Official: В frozen official page отдельное описание отсутствует.
$colorImagickPixel; обязательныйновый ImagickPixel для записи палитры
Official: В frozen official page отдельное описание отсутствует.

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. Truecolor вход или неверный индекс не дают ожидаемого эффекта. При ошибке выбрасывается ImagickException.

Граница. Все пиксели с этим индексом поменяются одновременно.

Что выбрать рядом. Opaquepaintimage для замены по близости цвета или importimagepixels для точной области.

Доступность. PECL imagick 2, PECL imagick 3.

Минимальный контрольный пример: заменить конкретный цвет индексированной иконки без обхода всех пикселейПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->quantizeImage(4, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->setImageColormapColor(0, new ImagickPixel('#00ff66'));
    $checks = ['return_contract' => $result === true];
    $palettePixel = $image->getImageColormapColor(0);
    $paletteColor = $palettePixel->getColor(false);
    $effect = ['palette_index' => 0, 'color' => $paletteColor, 'signature_before' => $before['signature'], 'signature_after' => $image->getImageSignature()];
    $checks['palette_readback'] = [($paletteColor['r'] ?? -1), ($paletteColor['g'] ?? -1), ($paletteColor['b'] ?? -1)] === [0, 255, 102];
    $checks['pixels_changed'] = $image->getImageSignature() !== $before['signature'];
    $artifact = __DIR__ . '/out/' . 'setimagecolormapcolor-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::setImageColormapColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: изменить запись palette по indexПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->quantizeImage(4, Imagick::COLORSPACE_RGB, 0, false, false);
    if ($image->getImageColors() < 2) { throw new LogicException('Нужны минимум две записи палитры'); }
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->setImageColormapColor(1, new ImagickPixel('#6633ff'));
    $checks = ['return_contract' => $result === true];
    $palettePixel = $image->getImageColormapColor(1);
    $paletteColor = $palettePixel->getColor(false);
    $effect = ['palette_index' => 1, 'color' => $paletteColor, 'signature_before' => $before['signature'], 'signature_after' => $image->getImageSignature()];
    $checks['palette_readback'] = [($paletteColor['r'] ?? -1), ($paletteColor['g'] ?? -1), ($paletteColor['b'] ?? -1)] === [102, 51, 255];
    $checks['pixels_changed'] = $image->getImageSignature() !== $before['signature'];
    $artifact = __DIR__ . '/out/' . 'setimagecolormapcolor-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::setImageColormapColor',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
$indexint; обязательныйиндекс записи colormap после проверки/quantize
Official: В frozen official page отдельное описание отсутствует.
$colorImagickPixel; обязательныйновый ImagickPixel для записи палитры
Official: В frozen official page отдельное описание отсутствует.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Sets the color of the specified colormap index

Description: Sets the color of the specified colormap index.

Return: Returns true on success.

Errors: При ошибке выбрасывается ImagickException.

Changelog: —

SHA страницы: 7a200ee5f585f36574faafbefcd5db676040cbca79775ba5eb8511a9afd2259d; SHA XML: dc47b5ae55d645dee1dd8824b6bf6a6b23f4bba0bbb428289f2c7ddeb8d9600a.

Imagick::uniqueImageColorsПостроить компактную полоску всех уникальных цветов изображения.

PECL imagick 2,PECL imagick 3 · imagick

Imagick::uniqueImageColors(): bool

Реальная потребность. Построить компактную полоску всех уникальных цветов изображения.

Что получится. Заменить кадр палитрой, где каждый цвет встречается один раз.

Самый маленький смысл вызова. Объект $image уже содержит один текущий кадр. Вызов Imagick::uniqueImageColors(): bool либо меняет этот кадр, либо возвращает измерение; ниже сначала показан маленький лабораторный вход, затем отдельная рабочая ситуация.

Перед примером: переменная, функция и return, объект и метод, try/catch/finally, пути и файлы, первый Imagick-файл, лимиты ресурсов.

Точная сигнатура. Imagick::uniqueImageColors(): bool; модификаторы: public.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.

Возврат: bool. true подтверждает выполнение вызова, но файл и видимый эффект проверяются отдельно.

Когда ломается. На фотографии результат может содержать огромное число пикселей и потерять исходную композицию. Официальная страница не добавляет отдельного текста ошибок; ImagickException всё равно обрабатывается на границе I/O/операции.

Граница. Метод разрушителен: запускайте на clone и при необходимости сначала quantize.

Что выбрать рядом. Getimagehistogram, если нужны ещё и частоты.

Доступность. PECL imagick 2,PECL imagick 3.

Минимальный контрольный пример: построить компактную полоску всех уникальных цветов изображенияПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick();
    $image->newPseudoImage(12, 8, 'gradient:#112233-#f0c674');
    $image->importImagePixels(0, 0, 1, 1, 'RGB', Imagick::PIXEL_CHAR, [255, 0, 0]);
    $image->setImageFormat('png');
    $image->quantizeImage(8, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->uniqueImageColors();
    $checks = ['return_contract' => $result === true];
    $effect = ['palette_width' => $image->getImageWidth(), 'palette_height' => $image->getImageHeight()];
    $checks['palette_strip'] = $image->getImageHeight() === 1 && $image->getImageWidth() > 0;
    $artifact = __DIR__ . '/out/' . 'uniqueimagecolors-minimal.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::uniqueImageColors',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Пример сам создаёт маленький несимметричный градиент, вызывает один изучаемый метод, проверяет return и печатает bounded JSON. Если операция меняет пиксели, создаётся отдельный PNG в ./out. Выполнение Imagick пока не заявляется.

Рабочая ситуация на другом входе: заменить кадр палитрой, где каждый цвет встречается один разПример для указанного окружения
<?php
declare(strict_types=1);

function aenBound(mixed $value): mixed
{
    if ($value instanceof ImagickPixel) { return $value->getColor(false); }
    if ($value instanceof ImagickPixelIterator) { return ['type' => 'ImagickPixelIterator']; }
    if ($value instanceof Imagick) { return ['type' => 'Imagick', 'geometry' => $value->getImageGeometry()]; }
    if (is_array($value)) { return array_slice($value, 0, 12, true); }
    return $value;
}

$image = null; $reference = null; $draw = null; $iterator = null; $transformed = null; $textCanvas = null;
try {
    $outputDir = __DIR__ . '/out';
    if (!is_dir($outputDir) && !mkdir($outputDir, 0775, true) && !is_dir($outputDir)) {
        throw new RuntimeException('Не удалось создать каталог результата');
    }
    $image = new Imagick(__DIR__ . '/fixtures/geometry.ppm');
    $image->setImageFormat('png');
    $image->quantizeImage(16, Imagick::COLORSPACE_RGB, 0, false, false);
    $before = [
        'geometry' => $image->getImageGeometry(),
        'page' => $image->getImagePage(),
        'object_page' => $image->getPage(),
        'corner' => $image->getImagePixelColor(0, 0)->getColor(false),
        'signature' => $image->getImageSignature(),
        'colorspace' => $image->getImageColorspace(),
    ];
    $result = $image->uniqueImageColors();
    $checks = ['return_contract' => $result === true];
    $effect = ['palette_width' => $image->getImageWidth(), 'palette_height' => $image->getImageHeight()];
    $checks['palette_strip'] = $image->getImageHeight() === 1 && $image->getImageWidth() > 0;
    $artifact = __DIR__ . '/out/' . 'uniqueimagecolors-workflow.png';
    $image->setImageFormat('png');
    $image->writeImage($artifact);
    $effect['artifact'] = basename($artifact);
    $effect['bytes'] = filesize($artifact);
    $checks['artifact_written'] = is_file($artifact) && filesize($artifact) > 8;
    foreach ($checks as $check => $passed) {
        if (!$passed) { throw new LogicException('Не прошла проверка результата: ' . $check); }
    }
    $observation = [
        'method' => 'Imagick::uniqueImageColors',
        'input' => $before,
        'return' => aenBound($result),
        'effect' => $effect,
        'checks' => $checks,
    ];
    echo json_encode($observation, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR), PHP_EOL;
} catch (ImagickException $exception) {
    fwrite(STDERR, 'Imagick отказал: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} catch (Throwable $exception) {
    fwrite(STDERR, 'Проверка примера не пройдена: ' . $exception->getMessage() . PHP_EOL);
    exit(1);
} finally {
    if ($iterator instanceof ImagickPixelIterator) { $iterator->clear(); }
    if ($draw instanceof ImagickDraw) { $draw->clear(); }
    if ($reference instanceof Imagick) { $reference->clear(); }
    if ($transformed instanceof Imagick) { $transformed->clear(); }
    if ($textCanvas instanceof Imagick) { $textCanvas->clear(); }
    if ($image instanceof Imagick) { $image->clear(); }
}

Этот сценарий читает объявленный 12×8 PPM, использует другие параметры и принимает проверяемое решение по result/effect. Это самостоятельный workflow, а не копия с заменённым числом; runtime и visual pass отложены до окружения с Imagick.

ПараметрТип и обязательностьКак читать
—без параметровМетод использует текущий кадр/состояние объекта.
Полный frozen-контракт официальной страницы

Модификаторы: public

Purpose: Discards all but one of any pixel color

Description: Discards all but one of any pixel color. Доступность зависит от версии ImageMagick не ниже 6.2.9.

Return: Returns true on success.

Errors: —

Changelog: —

SHA страницы: b79f720f9bf618d02691fde613a49b25fd4b23c96d6f8278f3235d2e25577673; SHA XML: 31d3e4f8b5d6cda48429ebf7e640135925bf805cfbe2c794deacd12d75a32135.

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

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

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

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

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