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

Дерево руководства
Глава 397 · После объектов и базовой работы с изображениями
Imagick: прочитать режим интерполяции и проверить результат обработки
Настройка текущего изображения, независимые клоны и кадры, явная операция пересчёта и два готовых PNG с рецептом повторного экспорта.
Проверить режим и увидеть, что настройка не перерисовывает изображение
Вы увеличиваете маленькую иконку и хотите понимать, почему одна версия остаётся пиксельной, а другая получает плавные края. Начните с проверки выбранной настройки. getImageInterpolateMethod отвечает, какой режим хранится у текущего изображения. Сам он не увеличивает картинку, а помогает проверить подготовку к обработке.

Для первого короткого фрагмента нужен файл icon.png рядом со скриптом. Он входит в каждый архив в виде base64; полный example.php автоматически восстановит обычный PNG. Можно взять и собственный файл. new Imagick читает его в объект $image; стрелка -> вызывает метод этого объекта. Пустые скобки getter означают, что аргументов ему не требуется.
$image = new Imagick(__DIR__ . "/icon.png");
$method = $image->getImageInterpolateMethod();
var_dump($method); // int(0) для нашего исходного PNGПеременная $method получает целое число. Для нашего файла 0 соответствует INTERPOLATE_UNDEFINED: явный режим не выбран. Это нормальное состояние, а не ошибка. Следующие три строки назначат ближайший пиксель и прочитают настройку обратно. Символы :: обращаются к именованной константе класса; её имя объясняет смысл лучше случайного числа.
$image->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$method = $image->getImageInterpolateMethod();
var_dump($method === Imagick::INTERPOLATE_NEAREST_PIXEL); // bool(true)В проверенной сборке это int(10), но код сравнивает имена констант. Размер пока остаётся 40×32, и домик не становится крупнее. Это удобно для диагностики: setter сообщает, что настройка принята, getter показывает, что хранится сейчас, а пересчёт выполняется отдельной операцией.
Прочитать настройку и убедиться, что сам рисунок не изменился
Getter вернул целое значение выбранного режима. В проверенной сборке исходный PNG имел UNDEFINED=0, после setter — NEAREST_PIXEL=10. Сам исходник остался 40×32 с прежними пикселями; две одинаковые картинки 400×320 — отдельное увеличение 10× для просмотра.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
$image = clone $source;
$before = ipState($image);
$setResult = $image->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$method = $image->getImageInterpolateMethod();
$after = ipState($image);
$left = ipPreview($source);
$right = ipPreview($image);
$images = ['before'=>ipImage($left,'first-before8.png'),'after'=>ipImage($right,'first-after8.png')];
$rects = ipCompare([$left,$right],'interpolate-first.png');
ipDiagnostic('interpolate-first',[
'before'=>$before,'after'=>$after,'set_return'=>$setResult,'get_type'=>get_debug_type($method),'get_value'=>$method,'display'=>['source_geometry'=>[40,32],'preview_geometry'=>[400,320],'preview_method'=>'sampleImage','scale'=>10],
'images'=>$images,'panel_keys'=>['before','after'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['default_undefined'=>$before['method']===Imagick::INTERPOLATE_UNDEFINED,'setter_true'=>$setResult===true,'getter_int'=>is_int($method),'getter_matches_setting'=>$method===Imagick::INTERPOLATE_NEAREST_PIXEL,'pixels_unchanged'=>$before['RGBA16_sha256']===$after['RGBA16_sha256'],'geometry_unchanged'=>$after['geometry']===[40,32],'display_equal'=>ipHash($left)===ipHash($right)]
]);
echo "interpolate-first.png\nfirst-before8.png\nfirst-after8.png\nmetrics.json\nbefore=UNDEFINED after=NEAREST_PIXEL getter=int pixels=unchanged size=40x32\n";
Getter вернул целое значение выбранного режима. В проверенной сборке исходный PNG имел UNDEFINED=0, после setter — NEAREST_PIXEL=10. Сам исходник остался 40×32 с прежними пикселями; две одинаковые картинки 400×320 — отдельное увеличение 10× для просмотра. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-first.png
first-before8.png
first-after8.png
metrics.json
before=UNDEFINED after=NEAREST_PIXEL getter=int pixels=unchanged size=40x32
Применить прочитанный режим и проверить отдельные кадры

Теперь передадим прочитанный режим операции, которая действительно использует интерполяцию. В нашей сборке interpolativeResizeImage получает ширину, высоту и метод. Здесь 400 и 320 — размеры результата в пикселях. В отличие от первых увеличенных панелей, это уже сами создаваемые изображения.
$method = $image->getImageInterpolateMethod();
$image->interpolativeResizeImage(400, 320, $method);
$image->setImageFormat("png");
$image->writeImage(__DIR__ . "/large-icon.png");Для иконки из крупных цветных клеток NEAREST_PIXEL сохраняет отчётливую сетку. BILINEAR смешивает соседние значения, поэтому между цветами появляются переходы. Это два разных визуальных решения. Сглаживание не восстанавливает утраченные детали, а ближайший пиксель не является универсальным выбором для фотографий, тонких линий или уменьшения. Для фотографического превью отдельно выбирают операцию и фильтр, сравнивая результат в целевом размере.
Следующий полный пример нужен, когда обработчик работает с клонами или несколькими изображениями. Для наших одиночных изображений clone создаёт независимую копию: установка BILINEAR в $smooth не меняет NEAREST_PIXEL у $pixel. addImage добавляет обе копии в список. foreach выбирает текущий кадр, а getter внутри цикла читает именно его настройку. Перед обработкой getImage() выделяет текущий кадр в отдельный Imagick. Это существенно: clone объекта последовательности копирует весь список и в проверенном запуске возвращает выбор к первому кадру; такой clone нельзя использовать здесь как выделение текущего кадра. У нас два самостоятельных кадра в памяти, не сохранённая GIF-анимация.
Прочитать настройку клона и каждого кадра, затем применить её
Два кадра содержат одинаковый исходный рисунок, но разные настройки: NEAREST_PIXEL и BILINEAR. После явной передачи каждого getter в interpolativeResizeImage получены разные PNG 400×320: чёткие блоки пикселей и сглаженные переходы.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
$pixel = clone $source;
$pixel->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$smooth = clone $pixel;
$smooth->setImageInterpolateMethod(Imagick::INTERPOLATE_BILINEAR);
$cloneStates = ['pixel'=>ipState($pixel),'smooth'=>ipState($smooth)];
$sequence = new Imagick();
$sequence->addImage($pixel);
$sequence->addImage($smooth);
$frameStates = [];
$outputs = [];
foreach ($sequence as $index => $frame) {
$frameStates[] = ['index'=>$index,'state'=>ipState($frame)];
$result = $frame->getImage();
$selected = $result->getImageInterpolateMethod();
$result->interpolativeResizeImage(400, 320, $selected);
$outputs[] = $result;
}
$images = ['nearest'=>ipImage($outputs[0],'frames-nearest8.png'),'bilinear'=>ipImage($outputs[1],'frames-bilinear8.png')];
$rects = ipCompare($outputs,'interpolate-frames.png');
ipDiagnostic('interpolate-frames',[
'clone_states'=>$cloneStates,'frame_states'=>$frameStates,'output_states'=>array_map('ipState',$outputs),'original_pixel_after'=>ipState($pixel),'sequence_frames'=>$sequence->getNumberImages(),
'images'=>$images,'panel_keys'=>['nearest','bilinear'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['clone_independent'=>$pixel->getImageInterpolateMethod()===Imagick::INTERPOLATE_NEAREST_PIXEL&&$smooth->getImageInterpolateMethod()===Imagick::INTERPOLATE_BILINEAR,'clone_pixels_equal'=>ipHash($pixel)===ipHash($smooth),'two_frames'=>$sequence->getNumberImages()===2,'frame_methods'=>$frameStates[0]['state']['method']===Imagick::INTERPOLATE_NEAREST_PIXEL&&$frameStates[1]['state']['method']===Imagick::INTERPOLATE_BILINEAR,'outputs_differ'=>ipHash($outputs[0])!==ipHash($outputs[1]),'output_geometry'=>$outputs[0]->getImageGeometry()===['width'=>400,'height'=>320]&&$outputs[1]->getImageGeometry()===['width'=>400,'height'=>320]]
]);
echo "interpolate-frames.png\nframes-nearest8.png\nframes-bilinear8.png\nmetrics.json\nframe0=NEAREST_PIXEL frame1=BILINEAR outputs=400x320 different=yes\n";
Два кадра содержат одинаковый исходный рисунок, но разные настройки: NEAREST_PIXEL и BILINEAR. После явной передачи каждого getter в interpolativeResizeImage получены разные PNG 400×320: чёткие блоки пикселей и сглаженные переходы. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-frames.png
frames-nearest8.png
frames-bilinear8.png
metrics.json
frame0=NEAREST_PIXEL frame1=BILINEAR outputs=400x320 different=yes
Путь данных: исходные 40×32 → настройка конкретного кадра → getter → третий аргумент interpolativeResizeImage → новые 400×320 → PNG. Более подробная механика дробных координат уже разобрана в главе о выборке и интерполяции. Здесь важна привязка настройки к нужному изображению и её явная передача операции.
Не путать настройку, параметр операции и фильтр масштабирования

Частая ошибка — считать возвращённое значение историей всех преобразований. Пусть объект хранит NEAREST_PIXEL. Если передать в конкретный вызов interpolativeResizeImage явный BILINEAR, этот вызов рассчитает билинейный результат. В проверенной сборке getter после него всё ещё возвращает NEAREST_PIXEL: отдельный аргумент операции не переписал сохранённую настройку.
$image->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$image->interpolativeResizeImage(400, 320, Imagick::INTERPOLATE_BILINEAR);
var_dump($image->getImageInterpolateMethod() === Imagick::INTERPOLATE_NEAREST_PIXEL);
// bool(true); пиксели при этом рассчитаны явным BILINEAR.У resizeImage другая связь параметров: ему передаётся фильтр из FILTER_*. Это не константа INTERPOLATE_*. В контроле ниже два клона получили разные настройки интерполяции, но одинаковый явный FILTER_LANCZOS; их пиксели оказались одинаковыми. Наблюдение относится к данной операции и параметрам, а не утверждает, что настройка вообще нигде не используется.
$image->resizeImage(400, 320, Imagick::FILTER_LANCZOS, 1.0);1.0 — параметр размытия фильтра в этом вызове. Для точной диагностики сравнивайте результаты на одном этапе: здесь контроль явного BILINEAR сравнивает два состояния Q16 до записи. PNG с глубиной 8 бит может округлить промежуточные значения; нельзя объявить методы различными, сравнив несохранённый Q16 с прочитанным PNG8.
Отличить настройку от явного аргумента операции и фильтра resizeImage
Явный BILINEAR в interpolativeResizeImage дал билинейные пиксели, хотя getter объекта всё ещё показывает NEAREST_PIXEL. Два resizeImage с одним FILTER_LANCZOS дали одинаковые пиксели при разных настройках интерполяции. Три ошибочных вызова перехвачены.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
$configured = clone $source;
$configured->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$override = clone $configured;
$override->interpolativeResizeImage(400, 320, Imagick::INTERPOLATE_BILINEAR);
$bilinearControl = clone $source;
$bilinearControl->setImageInterpolateMethod(Imagick::INTERPOLATE_BILINEAR);
$bilinearControl->interpolativeResizeImage(400, 320, $bilinearControl->getImageInterpolateMethod());
$overrideEqualsBilinear = ipHash($override) === ipHash($bilinearControl);
$lanczos = [];
foreach ([Imagick::INTERPOLATE_NEAREST_PIXEL, Imagick::INTERPOLATE_BILINEAR] as $method) {
$result = clone $source;
$result->setImageInterpolateMethod($method);
$result->resizeImage(400, 320, Imagick::FILTER_LANCZOS, 1.0);
$lanczos[] = $result;
}
$errors = ['empty_get'=>ipTry(fn()=>(new Imagick())->getImageInterpolateMethod()),'empty_set'=>ipTry(fn()=>(new Imagick())->setImageInterpolateMethod(Imagick::INTERPOLATE_BILINEAR)),'array_method'=>ipTry(fn()=>$configured->setImageInterpolateMethod([]))];
$images = ['lanczos_nearest'=>ipImage($lanczos[0],'controls-lanczos-nearest8.png'),'lanczos_bilinear'=>ipImage($lanczos[1],'controls-lanczos-bilinear8.png'),'override'=>ipImage($override,'controls-override8.png')];
$rects = ipCompare([$lanczos[0],$lanczos[1],$override],'interpolate-controls.png');
ipDiagnostic('interpolate-controls',[
'override_state'=>ipState($override),'bilinear_control'=>ipState($bilinearControl),'override_argument'=>Imagick::INTERPOLATE_BILINEAR,'comparison_stage'=>'Both Q16 pixel states before any save; save helpers only mutate clones','lanczos_states'=>array_map('ipState',$lanczos),'filter'=>Imagick::FILTER_LANCZOS,'errors'=>$errors,
'images'=>$images,'panel_keys'=>['lanczos_nearest','lanczos_bilinear','override'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['explicit_argument_wins'=>$overrideEqualsBilinear,'getter_is_not_history'=>$override->getImageInterpolateMethod()===Imagick::INTERPOLATE_NEAREST_PIXEL,'lanczos_pixels_equal'=>ipHash($lanczos[0])===ipHash($lanczos[1]),'lanczos_settings_differ'=>$lanczos[0]->getImageInterpolateMethod()!==$lanczos[1]->getImageInterpolateMethod(),'empty_get_caught'=>($errors['empty_get']['error']['class']??null)==='ImagickException','empty_set_caught'=>($errors['empty_set']['error']['class']??null)==='ImagickException','array_method_caught'=>($errors['array_method']['error']['class']??null)==='TypeError']
]);
echo "interpolate-controls.png\ncontrols-lanczos-nearest8.png\ncontrols-lanczos-bilinear8.png\ncontrols-override8.png\nmetrics.json\noverride=BILINEAR stored=NEAREST_PIXEL lanczos-equal=yes errors=3\n";
Явный BILINEAR в interpolativeResizeImage дал билинейные пиксели, хотя getter объекта всё ещё показывает NEAREST_PIXEL. Два resizeImage с одним FILTER_LANCZOS дали одинаковые пиксели при разных настройках интерполяции. Три ошибочных вызова перехвачены. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-controls.png
controls-lanczos-nearest8.png
controls-lanczos-bilinear8.png
controls-override8.png
metrics.json
override=BILINEAR stored=NEAREST_PIXEL lanczos-equal=yes errors=3
Пустой Imagick не содержит изображения, у которого можно прочитать настройку. Три перехваченные ошибки в программе показывают отдельно getter без картинки, setter без картинки и неверный тип аргумента setter. try/catch позволяет получить понятное сообщение и сохранить отчёт; это практическое дополнение к механизму исключений.
Сохранить два результата и рецепт следующего запуска

Для каталога собственных иконок нужен повторяемый экспорт: пиксельная версия для демонстрации сетки и мягкое превью для сравнения. Функция exportIcon ниже принимает исходный Imagick, режим и имя файла. Она клонирует исходник, читает назначенный режим, применяет его и возвращает сведения о результате. Сам исходный icon.png остаётся 40×32.
$pixel = exportIcon($source, Imagick::INTERPOLATE_NEAREST_PIXEL, "pixel-icon.png");
$smooth = exportIcon($source, Imagick::INTERPOLATE_BILINEAR, "smooth-preview.png");Объявление exportIcon приведено в полном примере. В результате рядом появятся два PNG 400×320 и recipe.json. Откройте изображения: в первом видны клетки, во втором — плавные границы. JSON содержит имя и SHA исходника, имя операции, размеры и символические имена методов. Он нужен для повторного экспорта, а не для отображения PNG браузером.
Выдать две версии PNG и сохранить воспроизводимый рецепт
Получены pixel-icon.png и smooth-preview.png размером 400×320, а также recipe.json с двумя символическими режимами и SHA исходника. После нового чтения PNG getter вернул UNDEFINED=0, но разные рассчитанные пиксели остались. Повтор из исходных 40×32 по рецепту дал тот же результат до кодирования PNG.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
function exportIcon(Imagick $source, int $method, string $filename): array
{
$result = clone $source;
$result->setImageInterpolateMethod($method);
$selected = $result->getImageInterpolateMethod();
$result->interpolativeResizeImage(400, 320, $selected);
$beforeSave = ipState($result);
$saved = ipSave($result, $filename);
return ['selected'=>$selected,'before_save'=>$beforeSave,'saved'=>$saved];
}
$exports = [
'pixel'=>exportIcon($source, Imagick::INTERPOLATE_NEAREST_PIXEL, 'pixel-icon.png'),
'smooth'=>exportIcon($source, Imagick::INTERPOLATE_BILINEAR, 'smooth-preview.png'),
];
$recipe = [
'source'=>'icon.png',
'source_sha256'=>$sourceHash,
'operation'=>'interpolativeResizeImage',
'width'=>400, 'height'=>320,
'variants'=>[
['file'=>'pixel-icon.png','method'=>'NEAREST_PIXEL'],
['file'=>'smooth-preview.png','method'=>'BILINEAR'],
],
];
file_put_contents(__DIR__ . '/recipe.json', json_encode(
$recipe, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR
) . "\n");
$readRecipe = json_decode((string)file_get_contents(__DIR__.'/recipe.json'),true,512,JSON_THROW_ON_ERROR);
$methodMap = ['NEAREST_PIXEL'=>Imagick::INTERPOLATE_NEAREST_PIXEL,'BILINEAR'=>Imagick::INTERPOLATE_BILINEAR];
$reads = [];
$replays = [];
foreach ($readRecipe['variants'] as $variant) {
$read = new Imagick(__DIR__ . '/' . $variant['file']);
$reads[] = $read;
$replay = clone $source;
$replay->setImageInterpolateMethod($methodMap[$variant['method']]);
$selected = $replay->getImageInterpolateMethod();
$replay->interpolativeResizeImage($readRecipe['width'], $readRecipe['height'], $selected);
$expected = $variant['method']==='NEAREST_PIXEL' ? $exports['pixel'] : $exports['smooth'];
$replays[] = ['method'=>$selected,'source_geometry'=>[40,32],'pre_save_equal'=>ipHash($replay)===$expected['before_save']['RGBA16_sha256']];
}
$images = ['pixel'=>ipImage($reads[0],'workflow-pixel8.png'),'smooth'=>ipImage($reads[1],'workflow-smooth8.png')];
$rects = ipCompare($reads,'interpolate-workflow.png');
ipDiagnostic('interpolate-workflow',[
'exports'=>$exports,'readback'=>array_map('ipState',$reads),'recipe'=>$readRecipe,'recipe_sha256'=>hash_file('sha256',__DIR__.'/recipe.json'),'replays'=>$replays,
'images'=>$images,'panel_keys'=>['pixel','smooth'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['selected_methods'=>$exports['pixel']['selected']===Imagick::INTERPOLATE_NEAREST_PIXEL&&$exports['smooth']['selected']===Imagick::INTERPOLATE_BILINEAR,'readback_setting_undefined'=>$reads[0]->getImageInterpolateMethod()===Imagick::INTERPOLATE_UNDEFINED&&$reads[1]->getImageInterpolateMethod()===Imagick::INTERPOLATE_UNDEFINED,'readback_pixels_differ'=>ipHash($reads[0])!==ipHash($reads[1]),'readback_geometry'=>$reads[0]->getImageGeometry()===['width'=>400,'height'=>320]&&$reads[1]->getImageGeometry()===['width'=>400,'height'=>320],'recipe_bound'=>$readRecipe['source_sha256']===$sourceHash,'replay_from_original_equal'=>$replays[0]['pre_save_equal']&&$replays[1]['pre_save_equal']]
]);
echo "interpolate-workflow.png\nworkflow-pixel8.png\nworkflow-smooth8.png\npixel-icon.png\nsmooth-preview.png\nrecipe.json\nmetrics.json\nexports=2 PNG-setting=UNDEFINED recipe=2-variants replay-from-original=equal\n";
Получены pixel-icon.png и smooth-preview.png размером 400×320, а также recipe.json с двумя символическими режимами и SHA исходника. После нового чтения PNG getter вернул UNDEFINED=0, но разные рассчитанные пиксели остались. Повтор из исходных 40×32 по рецепту дал тот же результат до кодирования PNG. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-workflow.png
workflow-pixel8.png
workflow-smooth8.png
pixel-icon.png
smooth-preview.png
recipe.json
metrics.json
exports=2 PNG-setting=UNDEFINED recipe=2-variants replay-from-original=equal
Новый Imagick из любого из этих PNG вернул UNDEFINED. Это не отменяет обработки: файл уже содержит её результат. Getter не определяет по внешнему виду, каким алгоритмом файл когда-то создан. Настройку для следующего преобразования назначают заново. Для воспроизводимого повтора программа читает recipe.json и начинает с исходных 40×32; повторное увеличение уже увеличенного файла было бы другой цепочкой операций.
В рецепте записаны NEAREST_PIXEL и BILINEAR, а не числа 10 и 5. Небольшой явный массив сопоставляет разрешённые имена с константами. Проверка SHA связывает рецепт с конкретным исходником, но не удостоверяет автора. В производственном обработчике дополнительно проверяют разрешённые пути и диапазоны размеров: здесь файлы и размеры собственные, фиксированные. Для разных версий ImageMagick сохраните версию среды и сравните итоговые файлы, если требуется повторяемость между машинами.
Если картинка кажется размытой только на странице, откройте PNG в его настоящем размере и проверьте CSS-размер: браузер может выполнить ещё одно масштабирование. Для пиксельной графики рассмотрите подходящий режим её отображения отдельно. Ни установка getter/setter, ни параметр качества JPEG сами по себе не создают недостающих деталей. Связанные темы: масштабирование и пропорции, запись и чтение файлов и структура JSON-документа.
Полный контракт getter, ошибки, ограничения и упражнения
Imagick::getImageInterpolateMethod: полный контракт
Imagick::getImageInterpolateMethod(): intМетод читает настройку интерполяции текущего изображения в объекте Imagick. Обязательных и необязательных аргументов нет: скобки остаются пустыми. При успехе возвращается int — одна из констант Imagick::INTERPOLATE_*. Он не возвращает новое изображение и не запускает пересчёт пикселей. Официальная доступность: PECL imagick 2, PECL imagick 3. Отдельного changelog у официальной страницы нет.
| Что читаем | Что означает | Что из этого не следует |
|---|---|---|
| INTERPOLATE_UNDEFINED | В изображении нет явно выбранного режима. В нашем PNG это int(0). | Это не false и не ошибка; нельзя объявить одним этим числом алгоритм любой последующей операции. |
| INTERPOLATE_NEAREST_PIXEL | Выбран ближайший пиксель; это имя доступно в проверенной сборке ImageMagick 7. | Оно не запускает увеличение и не выбирает фильтр resizeImage. |
| INTERPOLATE_BILINEAR | Выбрана билинейная интерполяция. | Это не гарантия лучшего качества для каждого изображения и масштаба. |
| Другая константа INTERPOLATE_* | Другой режим, поддерживаемый данной сборкой. | Пример распознаёт только три состояния; остальные не следует молча переименовывать в BILINEAR. |
Числа 0, 10 и 5 в этой главе — наблюдения нашей сборки, а не числа для подстановки в переносимый код. Сравнивайте с именованными константами. Историческое имя INTERPOLATE_NEARESTNEIGHBOR не определено в проверенной сборке ImageMagick 7; поэтому оно не используется в программах. Проверяйте defined для нужного имени и method_exists для операции, которую собираетесь выполнить. Условия её наличия зависят от версии и сборки расширения.
Официальный раздел ошибок указывает ImagickException. Реальный вызов getter на new Imagick() без изображения дал ImagickException: сначала прочитайте файл или создайте изображение. Setter на пустом объекте тоже дал ImagickException, массив вместо его int-аргумента — TypeError. Эти два последних условия относятся к setter, а не к безаргументному getter. Обработка ошибок не заменяет проверку доступности расширения и поддерживаемых методов.
$image = new Imagick(__DIR__ . "/icon.png");
$method = $image->getImageInterpolateMethod();
if ($method === Imagick::INTERPOLATE_UNDEFINED) {
echo "Режим явно не выбран";
}Getter смотрит на текущее изображение; при нескольких кадрах сначала выберите нужный кадр или перебирайте их. После клонирования изменение настройки клона не должно использоваться как проверка настройки исходника: читайте нужный объект. Getter также не является журналом обработки: операция могла получить собственный явный параметр, а после чтения сохранённого файла настройка может не восстановиться. В наших PNG повторное чтение вернуло UNDEFINED при сохранённых результатах обработки.
Связанные действия: задать интерполяцию и разобрать выборку между пикселями, изменить геометрию и выбрать фильтр, прочитать и записать изображение, отличить состояние объекта от сведений, сохранённых в файле.
Запуск и проверка понимания
Каждый архив содержит example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте всё рядом, затем выполните php example.php. Исходная иконка восстанавливается автоматически. Проверенная среда — PHP 8.5.11, Imagick 3.8.1, ImageMagick 7.1.1-46 Q16. Четыре программы действительно вызывают getter; вспомогательная операция interpolativeResizeImage подтверждена исходниками расширения и запуском. Её отдельная страница PHP.net в момент подготовки не была доступна, поэтому ссылка дана на исходный интерфейс расширения.
Упражнение: getter вернул 0 после чтения уже увеличенного PNG. Исчезло ли увеличение? Нет: проверьте размеры и сами пиксели; 0 относится к текущей настройке, а не к истории файла. Второе упражнение: getter показывает NEAREST_PIXEL, но явный третий аргумент операции — BILINEAR. Чем обработаны пиксели? В нашем контроле — BILINEAR. Третье упражнение: после назначения режима размер по-прежнему 40×32. Ошибка ли это? Нет, для изменения размера нужна отдельная операция. Четвёртое упражнение: обязательно ли NEAREST_PIXEL лучше для фотографии? Нет: он сохраняет дискретный вид, который может быть нежелателен для такой задачи.
Полный вспомогательный PHP из каждого архива
<?php
declare(strict_types=1);
function ipRestore(): void {
$hashes = json_decode('{"icon.png":"60338b8053d2145687ce95bea04f4f53e1ec736cb5252c696695816705e44194"}', true, 512, JSON_THROW_ON_ERROR);
foreach ($hashes as $name => $hash) {
$raw = base64_decode((string) file_get_contents(__DIR__ . '/' . $name . '.b64'), true);
if ($raw === false || hash('sha256', $raw) !== $hash || file_put_contents(__DIR__ . '/' . $name, $raw) === false) {
throw new RuntimeException('Input missing or changed');
}
}
if (!method_exists(Imagick::class, 'interpolativeResizeImage') || !defined('Imagick::INTERPOLATE_NEAREST_PIXEL')) {
throw new RuntimeException('This example requires the demonstrated Imagick/ImageMagick 7 interpolation API');
}
}
function ipHash(Imagick $image): string {
return hash('sha256', json_encode($image->exportImagePixels(0, 0, $image->getImageWidth(), $image->getImageHeight(), 'RGBA', Imagick::PIXEL_SHORT), JSON_THROW_ON_ERROR));
}
function ipName(int $method): string {
return match ($method) {
Imagick::INTERPOLATE_UNDEFINED => 'UNDEFINED',
Imagick::INTERPOLATE_NEAREST_PIXEL => 'NEAREST_PIXEL',
Imagick::INTERPOLATE_BILINEAR => 'BILINEAR',
default => 'OTHER(' . $method . ')',
};
}
function ipState(Imagick $image): array {
$method = $image->getImageInterpolateMethod();
return ['geometry'=>[$image->getImageWidth(),$image->getImageHeight()], 'RGBA16_sha256'=>ipHash($image), 'method'=>$method, 'method_name'=>ipName($method)];
}
function ipSave(Imagick $image, string $name): array {
$copy = clone $image;
$copy->setImageFormat('png');
$copy->setImageDepth(8);
$copy->setOption('png:bit-depth', '8');
$copy->setOption('png:color-type', '2');
$copy->setOption('png:exclude-chunk', 'all');
if (!$copy->writeImage(__DIR__ . '/' . $name)) throw new RuntimeException('Cannot save PNG');
$read = new Imagick(__DIR__ . '/' . $name);
return ['filename'=>$name,'sha256'=>hash_file('sha256',__DIR__.'/'.$name),'bytes'=>filesize(__DIR__.'/'.$name),'state'=>ipState($read)];
}
function ipImage(Imagick $image, string $name): array {
$saved = ipSave($image, $name);
return ['geometry'=>[$image->getImageWidth(),$image->getImageHeight()],'RGBA16_sha256'=>ipHash($image),'encoded_png'=>['filename'=>$name,'RGBA16_sha256'=>$saved['state']['RGBA16_sha256']],'display_basis'=>'Actual PHP raster; encoded PNG readback is distinct from pre-save Q16 state'];
}
function ipPreview(Imagick $image): Imagick {
$copy = clone $image;
$copy->sampleImage(400,320);
return $copy;
}
function ipCompare(array $images, string $name): array {
$canvas = new Imagick();
$canvas->newImage(400*count($images),320,'white','png');
$rects=[];
foreach($images as $n=>$image) {
$canvas->compositeImage($image,Imagick::COMPOSITE_COPY,400*$n,0);
$rects[]=['x'=>400*$n,'y'=>0,'width'=>400,'height'=>320];
}
ipSave($canvas,$name);
return $rects;
}
function ipTry(callable $fn): array {
try { $value=$fn();return ['type'=>get_debug_type($value),'returned'=>$value]; }
catch(Throwable $e) { return ['error'=>['class'=>get_class($e),'message'=>$e->getMessage()]]; }
}
function ipDiagnostic(string $id,array $data):void {
$doc=['schema'=>'aen-interpolate-method-program-diagnostics-v1','example_id'=>$id,'runtime'=>['php'=>PHP_VERSION,'imagick'=>phpversion('imagick'),'imagemagick'=>Imagick::getVersion()],'constants'=>['UNDEFINED'=>Imagick::INTERPOLATE_UNDEFINED,'NEAREST_PIXEL'=>Imagick::INTERPOLATE_NEAREST_PIXEL,'BILINEAR'=>Imagick::INTERPOLATE_BILINEAR]]+$data;
if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)."\n")===false)throw new RuntimeException('Cannot save metrics');
}
ipRestore восстанавливает собственный вход и проверяет нужный API. ipState читает текущую настройку, размеры и пиксели для отчёта; ipPreview увеличивает маленький исходник исключительно для просмотра. ipSave сохраняет клон как PNG8 и читает его обратно, не меняя исследуемый объект. Это разделяет исходное Q16-состояние и действительно закодированные пиксели. metrics.json содержит фактические результаты, но для использования метода достаточно первых коротких фрагментов.
Практические вопросы и источники
Ниже — реальные вопросы, которые помогают выбрать полезные сценарии. Ответы не скопированы: пояснения и программы созданы для этой главы, а технические утверждения проверены по официальному контракту, исходникам и выполненным примерам.
ImageMagick resize without interpolation: Увеличение маленькой карты смешивает цвета вместо сохранения видимой сетки. Сравниваем два собственных результата и явно передаём режим операции; getter служит проверкой настройки.
Resize image programatically to get the same result as a browser: Файл превью выглядит иначе, чем большое изображение, уменьшенное браузером. Сравниваем фактические файлы одинакового размера и поясняем дополнительное масштабирование страницы.
Resize an image with 54x54 squares (540x540) to 54x54pixel lossless: Сетка цветных квадратов теряет чёткость при пересчёте размеров. Разделяем цель сохранения клеток и сглаживания; выбор режима зависит от содержимого и масштаба, а не от универсального числа качества.
preventing resized images from becoming blurred: После увеличения малого изображения автор получает размытый файл. Показываем исходные размеры и действительный результат; увеличение не восстанавливает неизвестные детали.
PHP Imagick: copy image object to another image object but with bigger resolution: Копирование и изменение resolution не дают ожидаемого нового растрового размера. Проверяем независимую настройку клона и отличаем сохранённое состояние от отдельного пересчёта пикселей.
PHP Imagick - Text and Lines not clear/smooth after resize: Тонкие линии и текст выглядят плохо после resize, crop и композиции. Отделяем параметры конкретной операции и проверяем её результат; getter не заменяет выбор фильтра и сравнение в целевом размере.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
Imagick::getImageInterpolateMethodПрочитать настройку интерполяции и проверить реальную обработку
PECL imagick 2, PECL imagick 3 · imagick
Imagick::getImageInterpolateMethod(): intImagick::getImageInterpolateMethod: полный контракт
Imagick::getImageInterpolateMethod(): intМетод читает настройку интерполяции текущего изображения в объекте Imagick. Обязательных и необязательных аргументов нет: скобки остаются пустыми. При успехе возвращается int — одна из констант Imagick::INTERPOLATE_*. Он не возвращает новое изображение и не запускает пересчёт пикселей. Официальная доступность: PECL imagick 2, PECL imagick 3. Отдельного changelog у официальной страницы нет.
| Что читаем | Что означает | Что из этого не следует |
|---|---|---|
| INTERPOLATE_UNDEFINED | В изображении нет явно выбранного режима. В нашем PNG это int(0). | Это не false и не ошибка; нельзя объявить одним этим числом алгоритм любой последующей операции. |
| INTERPOLATE_NEAREST_PIXEL | Выбран ближайший пиксель; это имя доступно в проверенной сборке ImageMagick 7. | Оно не запускает увеличение и не выбирает фильтр resizeImage. |
| INTERPOLATE_BILINEAR | Выбрана билинейная интерполяция. | Это не гарантия лучшего качества для каждого изображения и масштаба. |
| Другая константа INTERPOLATE_* | Другой режим, поддерживаемый данной сборкой. | Пример распознаёт только три состояния; остальные не следует молча переименовывать в BILINEAR. |
Числа 0, 10 и 5 в этой главе — наблюдения нашей сборки, а не числа для подстановки в переносимый код. Сравнивайте с именованными константами. Историческое имя INTERPOLATE_NEARESTNEIGHBOR не определено в проверенной сборке ImageMagick 7; поэтому оно не используется в программах. Проверяйте defined для нужного имени и method_exists для операции, которую собираетесь выполнить. Условия её наличия зависят от версии и сборки расширения.
Официальный раздел ошибок указывает ImagickException. Реальный вызов getter на new Imagick() без изображения дал ImagickException: сначала прочитайте файл или создайте изображение. Setter на пустом объекте тоже дал ImagickException, массив вместо его int-аргумента — TypeError. Эти два последних условия относятся к setter, а не к безаргументному getter. Обработка ошибок не заменяет проверку доступности расширения и поддерживаемых методов.
$image = new Imagick(__DIR__ . "/icon.png");
$method = $image->getImageInterpolateMethod();
if ($method === Imagick::INTERPOLATE_UNDEFINED) {
echo "Режим явно не выбран";
}Getter смотрит на текущее изображение; при нескольких кадрах сначала выберите нужный кадр или перебирайте их. После клонирования изменение настройки клона не должно использоваться как проверка настройки исходника: читайте нужный объект. Getter также не является журналом обработки: операция могла получить собственный явный параметр, а после чтения сохранённого файла настройка может не восстановиться. В наших PNG повторное чтение вернуло UNDEFINED при сохранённых результатах обработки.
Связанные действия: задать интерполяцию и разобрать выборку между пикселями, изменить геометрию и выбрать фильтр, прочитать и записать изображение, отличить состояние объекта от сведений, сохранённых в файле.
Прочитать настройку и убедиться, что сам рисунок не изменился
Getter вернул целое значение выбранного режима. В проверенной сборке исходный PNG имел UNDEFINED=0, после setter — NEAREST_PIXEL=10. Сам исходник остался 40×32 с прежними пикселями; две одинаковые картинки 400×320 — отдельное увеличение 10× для просмотра.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
$image = clone $source;
$before = ipState($image);
$setResult = $image->setImageInterpolateMethod(Imagick::INTERPOLATE_NEAREST_PIXEL);
$method = $image->getImageInterpolateMethod();
$after = ipState($image);
$left = ipPreview($source);
$right = ipPreview($image);
$images = ['before'=>ipImage($left,'first-before8.png'),'after'=>ipImage($right,'first-after8.png')];
$rects = ipCompare([$left,$right],'interpolate-first.png');
ipDiagnostic('interpolate-first',[
'before'=>$before,'after'=>$after,'set_return'=>$setResult,'get_type'=>get_debug_type($method),'get_value'=>$method,'display'=>['source_geometry'=>[40,32],'preview_geometry'=>[400,320],'preview_method'=>'sampleImage','scale'=>10],
'images'=>$images,'panel_keys'=>['before','after'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['default_undefined'=>$before['method']===Imagick::INTERPOLATE_UNDEFINED,'setter_true'=>$setResult===true,'getter_int'=>is_int($method),'getter_matches_setting'=>$method===Imagick::INTERPOLATE_NEAREST_PIXEL,'pixels_unchanged'=>$before['RGBA16_sha256']===$after['RGBA16_sha256'],'geometry_unchanged'=>$after['geometry']===[40,32],'display_equal'=>ipHash($left)===ipHash($right)]
]);
echo "interpolate-first.png\nfirst-before8.png\nfirst-after8.png\nmetrics.json\nbefore=UNDEFINED after=NEAREST_PIXEL getter=int pixels=unchanged size=40x32\n";
Getter вернул целое значение выбранного режима. В проверенной сборке исходный PNG имел UNDEFINED=0, после setter — NEAREST_PIXEL=10. Сам исходник остался 40×32 с прежними пикселями; две одинаковые картинки 400×320 — отдельное увеличение 10× для просмотра. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-first.png
first-before8.png
first-after8.png
metrics.json
before=UNDEFINED after=NEAREST_PIXEL getter=int pixels=unchanged size=40x32
Выдать две версии PNG и сохранить воспроизводимый рецепт
Получены pixel-icon.png и smooth-preview.png размером 400×320, а также recipe.json с двумя символическими режимами и SHA исходника. После нового чтения PNG getter вернул UNDEFINED=0, но разные рассчитанные пиксели остались. Повтор из исходных 40×32 по рецепту дал тот же результат до кодирования PNG.
<?php
declare(strict_types=1);
require __DIR__ . '/interpolate-fixture.php';
ipRestore();
$source = new Imagick(__DIR__ . '/icon.png');
$sourceBefore = ipState($source);
$sourceHash = hash_file('sha256', __DIR__ . '/icon.png');
function exportIcon(Imagick $source, int $method, string $filename): array
{
$result = clone $source;
$result->setImageInterpolateMethod($method);
$selected = $result->getImageInterpolateMethod();
$result->interpolativeResizeImage(400, 320, $selected);
$beforeSave = ipState($result);
$saved = ipSave($result, $filename);
return ['selected'=>$selected,'before_save'=>$beforeSave,'saved'=>$saved];
}
$exports = [
'pixel'=>exportIcon($source, Imagick::INTERPOLATE_NEAREST_PIXEL, 'pixel-icon.png'),
'smooth'=>exportIcon($source, Imagick::INTERPOLATE_BILINEAR, 'smooth-preview.png'),
];
$recipe = [
'source'=>'icon.png',
'source_sha256'=>$sourceHash,
'operation'=>'interpolativeResizeImage',
'width'=>400, 'height'=>320,
'variants'=>[
['file'=>'pixel-icon.png','method'=>'NEAREST_PIXEL'],
['file'=>'smooth-preview.png','method'=>'BILINEAR'],
],
];
file_put_contents(__DIR__ . '/recipe.json', json_encode(
$recipe, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR
) . "\n");
$readRecipe = json_decode((string)file_get_contents(__DIR__.'/recipe.json'),true,512,JSON_THROW_ON_ERROR);
$methodMap = ['NEAREST_PIXEL'=>Imagick::INTERPOLATE_NEAREST_PIXEL,'BILINEAR'=>Imagick::INTERPOLATE_BILINEAR];
$reads = [];
$replays = [];
foreach ($readRecipe['variants'] as $variant) {
$read = new Imagick(__DIR__ . '/' . $variant['file']);
$reads[] = $read;
$replay = clone $source;
$replay->setImageInterpolateMethod($methodMap[$variant['method']]);
$selected = $replay->getImageInterpolateMethod();
$replay->interpolativeResizeImage($readRecipe['width'], $readRecipe['height'], $selected);
$expected = $variant['method']==='NEAREST_PIXEL' ? $exports['pixel'] : $exports['smooth'];
$replays[] = ['method'=>$selected,'source_geometry'=>[40,32],'pre_save_equal'=>ipHash($replay)===$expected['before_save']['RGBA16_sha256']];
}
$images = ['pixel'=>ipImage($reads[0],'workflow-pixel8.png'),'smooth'=>ipImage($reads[1],'workflow-smooth8.png')];
$rects = ipCompare($reads,'interpolate-workflow.png');
ipDiagnostic('interpolate-workflow',[
'exports'=>$exports,'readback'=>array_map('ipState',$reads),'recipe'=>$readRecipe,'recipe_sha256'=>hash_file('sha256',__DIR__.'/recipe.json'),'replays'=>$replays,
'images'=>$images,'panel_keys'=>['pixel','smooth'],'panel_geometry'=>$rects,'source_before'=>$sourceBefore,'source_after'=>ipState($source),'source_sha256'=>$sourceHash,'source_unchanged'=>ipState($source)===$sourceBefore&&hash_file('sha256',__DIR__.'/icon.png')===$sourceHash,
'checks'=>['selected_methods'=>$exports['pixel']['selected']===Imagick::INTERPOLATE_NEAREST_PIXEL&&$exports['smooth']['selected']===Imagick::INTERPOLATE_BILINEAR,'readback_setting_undefined'=>$reads[0]->getImageInterpolateMethod()===Imagick::INTERPOLATE_UNDEFINED&&$reads[1]->getImageInterpolateMethod()===Imagick::INTERPOLATE_UNDEFINED,'readback_pixels_differ'=>ipHash($reads[0])!==ipHash($reads[1]),'readback_geometry'=>$reads[0]->getImageGeometry()===['width'=>400,'height'=>320]&&$reads[1]->getImageGeometry()===['width'=>400,'height'=>320],'recipe_bound'=>$readRecipe['source_sha256']===$sourceHash,'replay_from_original_equal'=>$replays[0]['pre_save_equal']&&$replays[1]['pre_save_equal']]
]);
echo "interpolate-workflow.png\nworkflow-pixel8.png\nworkflow-smooth8.png\npixel-icon.png\nsmooth-preview.png\nrecipe.json\nmetrics.json\nexports=2 PNG-setting=UNDEFINED recipe=2-variants replay-from-original=equal\n";
Получены pixel-icon.png и smooth-preview.png размером 400×320, а также recipe.json с двумя символическими режимами и SHA исходника. После нового чтения PNG getter вернул UNDEFINED=0, но разные рассчитанные пиксели остались. Повтор из исходных 40×32 по рецепту дал тот же результат до кодирования PNG. В архиве example.php, icon.png.b64 и interpolate-fixture.php. Распакуйте файлы рядом и выполните php example.php: собственный icon.png восстановится автоматически. Вспомогательный PHP целиком приведён в конце главы. Проверенная среда: PHP 8.5.11 / Imagick 3.8.1 / ImageMagick 7.1.1-46 Q16, Windows. Полные примеры требуют interpolativeResizeImage и константу INTERPOLATE_NEAREST_PIXEL, проверяют их наличие перед обработкой.
Ожидаемый вывод после настоящего запуска
interpolate-workflow.png
workflow-pixel8.png
workflow-smooth8.png
pixel-icon.png
smooth-preview.png
recipe.json
metrics.json
exports=2 PNG-setting=UNDEFINED recipe=2-variants replay-from-original=equal
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


