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

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

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

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

Глава 435 · После первых изображений, цветов GmagickPixel и наложения OVER

Gmagick: прозрачность, matte color и реальный фон

Проверить фактическую прозрачность, отличить её от свойства цвета, сохранить небольшой логотип и подготовить карточку на выбранном фоне.

Увидеть прозрачность на клетчатой подложке

Продолжаем цвета и компоненты пикселя и наложение изображений. Здесь слова «alpha», «matte channel» и «matte color» описывают разные вещи. Alpha — значение прозрачности каждого пикселя; matte channel — старое название соответствующего канала; matte color — одно цветовое свойство изображения. Модель листа с пустыми местами помогает представить наложение, но файл хранит числа, а не физические отверстия.

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

Исходный логотип с сохранённой прозрачностью; цвет страницы виден сквозь пустую область
Исходный логотип с сохранённой прозрачностью; цвет страницы виден сквозь пустую область — 320 × 200 px.
Тот же логотип наложен на отдельную клетчатую подложку
Тот же логотип наложен на отдельную клетчатую подложку — 320 × 200 px.
PNG содержит канал alpha, но все его пиксели непрозрачны
PNG содержит канал alpha, но все его пиксели непрозрачны — 320 × 200 px.
<?php
$logo = new Gmagick(__DIR__ . '/logo.png');
$preview = new Gmagick(__DIR__ . '/checker.ppm');
$preview->compositeImage($logo, Gmagick::COMPOSITE_OVER, 0, 0);
$preview->setImageFormat('PNG');
$preview->writeImage(__DIR__ . '/preview.png');

new создаёт объект и читает указанный файл. Переменные $logo и $preview относятся к разным изображениям. Стрелка -> вызывает метод у объекта слева. compositeImage накладывает $logo на $preview; OVER учитывает прозрачность верхнего слоя, а два нуля задают его положение от левого верхнего угла. На выходе preview.png содержит нарисованные клетки, а исходный logo.png сохраняет пустые области.

Увидеть прозрачность на клетчатой подложкеСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$logo = new Gmagick(__DIR__ . '/logo.png');
$matteAvailable = method_exists($logo, 'getImageMatte');
$matteChannel = $matteAvailable ? $logo->getImageMatte() : null;
$hasTransparentPixels = false;
foreach ($logo->getImageHistogram() as $pixel) {
    if ($pixel->getColorValue(Gmagick::COLOR_OPACITY) > 0.0) {
        $hasTransparentPixels = true;
        break;
    }
}
$checker = new Gmagick(__DIR__ . '/checker.ppm');
$checker->compositeImage($logo, Gmagick::COMPOSITE_OVER, 0, 0);
$logo->setImageDepth(8);
$logo->setImageFormat('PNG');
$logo->writeImage(__DIR__ . '/gm101-logo-copy.png');
$checker->setImageDepth(8);
$checker->setImageFormat('PNG');
$checker->writeImage(__DIR__ . '/gm101-logo-checker.png');
$opaque = new Gmagick(__DIR__ . '/product.ppm');
$opaque->setImageType(Gmagick::IMGTYPE_TRUECOLORMATTE);
$opaque->setImageDepth(8);
$opaque->setImageFormat('PNG');
$opaque->writeImage(__DIR__ . '/gm101-opaque-rgba.png');
$opaqueRead = new Gmagick(__DIR__ . '/gm101-opaque-rgba.png');
$allOpaque = true;
foreach ($opaqueRead->getImageHistogram() as $pixel) {
    if ($pixel->getColorValue(Gmagick::COLOR_OPACITY) > 0.0) $allOpaque = false;
}
$pngBytes = file_get_contents(__DIR__ . '/gm101-opaque-rgba.png');
$pngColorType = ord($pngBytes[25]); // IHDR color type: 6 is RGBA.

gmReport('gm101-alpha-visible',["gmagick.construct", "gmagick.getimagehistogram", "gmagickpixel.getcolorvalue", "gmagick.compositeimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.setimagetype"],["gm101-logo-copy.png", "gm101-logo-checker.png", "gm101-opaque-rgba.png"],
    ['guarded_method_unavailable'=>$matteAvailable === false && $matteChannel === null,'actual_transparency'=>$hasTransparentPixels,'opaque_alpha_channel'=>$allOpaque && $pngColorType === 6,'size_gm101_logo_copy'=>gmInspect('gm101-logo-copy.png')['width'] === 320 && gmInspect('gm101-logo-copy.png')['height'] === 200,'size_gm101_logo_checker'=>gmInspect('gm101-logo-checker.png')['width'] === 320 && gmInspect('gm101-logo-checker.png')['height'] === 200,'size_gm101_opaque_rgba'=>gmInspect('gm101-opaque-rgba.png')['width'] === 320 && gmInspect('gm101-opaque-rgba.png')['height'] === 200],
    $errors ?? [], ['matte_method_available' => $matteAvailable, 'availability_path' => 'guarded_fallback', 'alternative_executed' => true, 'has_transparent_pixels' => $hasTransparentPixels, 'opaque_png_color_type' => $pngColorType]);
echo "gm101-logo-copy.png 320x200\ngm101-logo-checker.png 320x200\ngm101-opaque-rgba.png 320x200\n";
Ожидаемый результат
gm101-logo-copy.png 320x200
gm101-logo-checker.png 320x200
gm101-opaque-rgba.png 320x200

Запуск: php example.php с Gmagick. Проверенная среда: PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16. Архив содержит точные собственные входы в .b64; gm-fixture.php восстанавливает их и записывает проверочные metrics.json. Изучаемые операции находятся в программе. Исходный logo.png остаётся прозрачным и неизменным.

Название «matte channel» в старом API относится к каналу прозрачности. Наличие такого канала ещё не доказывает, что какой-то пиксель прозрачен. Третья картинка специально записана как RGBA, но все её значения alpha равны 255. Наш запасной путь проверяет фактические пиксели, а не наличие места под канал: это связанный, но другой вопрос.

В исходном RGBA8-файле alpha = 0 означает полную прозрачность, 255 — полную непрозрачность. У нашего белого участка alpha = 64, около 25% непрозрачности. Константа Gmagick::COLOR_OPACITY при чтении GmagickPixel в проверенной библиотеке использует обратное направление: 0 — непрозрачно, 1 — прозрачно; для этого участка получилось 191/255. Нельзя переносить число из одного представления в другое без уточнения смысла.

Что проверяемЧто получаемЧего этого недостаточно доказать
getImageMatte() при наличии методаПризнак наличия каналаЕсть ли хотя бы один прозрачный пиксель
getImageMatteColor()GmagickPixel со значением свойстваКак выглядит изображение на выбранном фоне
Гистограмма и COLOR_OPACITYЕсть ли реально прозрачные значенияСтруктурное наличие канала с полностью непрозрачными значениями
Наложение OVER на отдельный холстПиксели готовой карточкиСохранность прозрачного оригинала, если его перезаписать

В установленной сборке getImageMatte отсутствует. Доступность проверяется до вызова; полный пример не падает и не притворяется, что выполнил этот getter. Запасная проверка просматривает цвета гистограммы и отвечает на другой полезный вопрос: есть ли фактическая прозрачность. Одной точки в углу для такого вывода обо всём изображении недостаточно.

<?php
$logo = new Gmagick(__DIR__ . '/logo.png');
if (method_exists($logo, 'getImageMatte')) {
    $hasChannel = $logo->getImageMatte();
} else {
    $hasChannel = null; // Метод недоступен, результат неизвестен.
}

Каждый ZIP сам восстанавливает logo.png, checker.ppm и product.ppm из точных .b64-данных. Помощник занимается только входными файлами и проверочными метриками; он не подменяет наложение и другие изучаемые действия. Короткие фрагменты предполагают эти файлы рядом с PHP. Логотип создан нативными командами GmagickDraw, затем сохранён как исходник; альфа 64 получена из настоящего PNG. Клетки нарисованы в отдельном PPM и входят только в проверочные превью. Для повторного использования нужен прозрачный logo.png, а не картинка с уже нарисованными клетками.

Проверить, закрашивает ли matte color прозрачные места

Допустим, для карточки выбран янтарный фирменный фон. Попробуем назначить его свойству matte color и проверим результат. Две настройки цвета читаются правильно, однако прозрачные места остаются прозрачными и клетки всё ещё видны.

Тот же логотип наложен на отдельную клетчатую подложку
Тот же логотип наложен на отдельную клетчатую подложку — 320 × 200 px.
Свойство matte color равно янтарному; прозрачная область осталась прозрачной
Свойство matte color равно янтарному; прозрачная область осталась прозрачной — 320 × 200 px.
Свойство matte color равно синему; пиксели совпадают с исходником
Свойство matte color равно синему; пиксели совпадают с исходником — 320 × 200 px.
Клетки по-прежнему видны: назначение цвета не заменило наложение
Клетки по-прежнему видны: назначение цвета не заменило наложение — 320 × 200 px.
<?php
$logo = new Gmagick(__DIR__ . '/logo.png');
$ok = $logo->setImageMatteColor('#e5a74a');
$pixel = $logo->getImageMatteColor();
$rgb = $pixel->getColor(true);
echo $rgb['r'], ',', $rgb['g'], ',', $rgb['b'], "\n";

Ожидаемый вывод — 229,167,74. Строка #e5a74a задаёт цвет. getImageMatteColor возвращает GmagickPixel — объект цвета; getColor(true) читает массив с компонентами r, g и b. Квадратные скобки выбирают значение по ключу. Setter в проверенной сборке возвращает bool true, поэтому следующую операцию вызываем у $logo, а не строим цепочку из результата setter.

Проверить, закрашивает ли matte color прозрачные местаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$amber = new Gmagick(__DIR__ . '/logo.png');
$before = $amber->getImageSignature();
$amberResult = $amber->setImageMatteColor('#e5a74a');
$amberRgb = $amber->getImageMatteColor()->getColor(true);
$blue = new Gmagick(__DIR__ . '/logo.png');
$blueResult = $blue->setImageMatteColor(new GmagickPixel('#244f65'));
$blueRgb = $blue->getImageMatteColor()->getColor(true);
$unchanged = $before === $amber->getImageSignature()
    && $before === $blue->getImageSignature();
$checker = new Gmagick(__DIR__ . '/checker.ppm');
$checker->compositeImage($amber, Gmagick::COMPOSITE_OVER, 0, 0);
$amber->setImageDepth(8);
$amber->setImageFormat('PNG');
$amber->writeImage(__DIR__ . '/gm101-matte-amber.png');
$blue->setImageDepth(8);
$blue->setImageFormat('PNG');
$blue->writeImage(__DIR__ . '/gm101-matte-blue.png');
$checker->setImageDepth(8);
$checker->setImageFormat('PNG');
$checker->writeImage(__DIR__ . '/gm101-matte-checker.png');

gmReport('gm101-alpha-setting',["gmagickpixel.construct", "gmagick.construct", "gmagick.getimagesignature", "gmagick.setimagemattecolor", "gmagick.getimagemattecolor", "gmagickpixel.getcolor", "gmagick.compositeimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm101-matte-amber.png", "gm101-matte-blue.png", "gm101-matte-checker.png"],
    ['setter_bool'=>$amberResult === true && $blueResult === true,'getter_colors'=>$amberRgb === ['r'=>229,'g'=>167,'b'=>74] && $blueRgb === ['r'=>36,'g'=>79,'b'=>101],'pixels_unchanged'=>$unchanged,'size_gm101_matte_amber'=>gmInspect('gm101-matte-amber.png')['width'] === 320 && gmInspect('gm101-matte-amber.png')['height'] === 200,'size_gm101_matte_blue'=>gmInspect('gm101-matte-blue.png')['width'] === 320 && gmInspect('gm101-matte-blue.png')['height'] === 200,'size_gm101_matte_checker'=>gmInspect('gm101-matte-checker.png')['width'] === 320 && gmInspect('gm101-matte-checker.png')['height'] === 200],
    $errors ?? [], ['amber_rgb' => $amberRgb, 'blue_rgb' => $blueRgb, 'setter_returns_bool' => true, 'unchanged_pixel_signature' => $unchanged]);
echo "gm101-matte-amber.png 320x200\ngm101-matte-blue.png 320x200\ngm101-matte-checker.png 320x200\n";
Ожидаемый результат
gm101-matte-amber.png 320x200
gm101-matte-blue.png 320x200
gm101-matte-checker.png 320x200

Запуск: php example.php с Gmagick. Проверенная среда: PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16. Архив содержит точные собственные входы в .b64; gm-fixture.php восстанавливает их и записывает проверочные metrics.json. Изучаемые операции находятся в программе. Исходный logo.png остаётся прозрачным и неизменным.

Полная программа сравнивает подпись пикселей до и после двух назначений: она осталась прежней. Само свойство matte color не является командой заменить прозрачность цветом. Чтобы получить реальные фоновые пиксели, дальше создадим отдельный холст и выполним наложение. Полученный объект цвета также нельзя напрямую считать одним пикселем изображения: это значение свойства.

Дополнительный setter этой сборки

setImageMatteColor не имеет отдельной страницы в текущем официальном PHP Manual и не включён здесь в число новых официальных карточек. Он присутствует в исследованной сборке и в исходниках расширения. Перед переносом кода в другое окружение проверьте method_exists($logo, "setImageMatteColor").

Gmagick::setImageMatteColor($color): bool

Один обязательный аргумент: строка распознаваемого цвета или GmagickPixel. Исходник обёртки разбирает это как цвет; проверены оба варианта. Возврат в нашей сборке — true, не Gmagick. У пустого объекта операция даёт GmagickException, неизвестная строка цвета даёт GmagickPixelException, массив — GmagickException. Назначается свойство matte color; переносить это описание на изменение всех alpha-пикселей нельзя.

getColor() без true в этой Q16-сборке возвращает строку с квантовыми значениями. Для нового холста мы явно собираем обычный RGB8 через getColor(true) и sprintf. Объект GmagickPixel и массив RGB подробнее разобраны в уроке о цвете.

Получить светлую и тёмную карточку с реальным фоном

Для светлой и тёмной темы нужны две действительно разные карточки. Воспользуемся выбранным matte color как настройкой приложения: прочитаем её, создадим холст такого цвета и наложим логотип. Теперь прозрачные места заполнены фоном, а полупрозрачная полоса смешивается с ним.

Тот же логотип наложен на отдельную клетчатую подложку
Тот же логотип наложен на отдельную клетчатую подложку — 320 × 200 px.
Логотип на светлом фоне RGB 248,248,248
Логотип на светлом фоне RGB 248,248,248 — 320 × 200 px.
Логотип на тёмном фоне RGB 24,34,43; полупрозрачная полоса заметнее
Логотип на тёмном фоне RGB 24,34,43; полупрозрачная полоса заметнее — 320 × 200 px.
<?php
$logo = new Gmagick(__DIR__ . '/logo.png');
$canvas = new Gmagick();
$canvas->newImage(320, 200, '#18222b', 'png');
$canvas->compositeImage($logo, Gmagick::COMPOSITE_OVER, 0, 0);
$canvas->writeImage(__DIR__ . '/dark-card.png');

newImage принимает ширину и высоту в пикселях, цвет и формат. Этот вызов действительно создаёт фон. Затем compositeImage изменяет его пиксели с учётом alpha логотипа. В полной программе цвет приходит из getImageMatteColor: sprintf превращает три числа RGB8 в строку #RRGGBB; %02x означает две шестнадцатеричные цифры с ведущим нулём. Так сохранённая настройка становится явным входом операции.

Получить светлую и тёмную карточку с реальным фономСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$logo = new Gmagick(__DIR__ . '/logo.png');
$colors = [];
foreach (['light' => '#f8f8f8', 'dark' => '#18222b'] as $name => $requested) {
    $logo->setImageMatteColor($requested);
    $rgb = $logo->getImageMatteColor()->getColor(true);
    $colors[$name] = $rgb;
    $css = sprintf('#%02x%02x%02x', $rgb['r'], $rgb['g'], $rgb['b']);
    $canvas = new Gmagick();
    $canvas->newImage(320, 200, $css, 'png');
    $canvas->compositeImage($logo, Gmagick::COMPOSITE_OVER, 0, 0);
    $canvas->setImageDepth(8);
    $canvas->setImageFormat('PNG');
    $canvas->writeImage(__DIR__ . '/gm101-' . $name . '-card.png');
}

gmReport('gm101-alpha-backgrounds',["gmagick.construct", "gmagick.setimagemattecolor", "gmagick.getimagemattecolor", "gmagickpixel.getcolor", "gmagick.newimage", "gmagick.compositeimage", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage"],["gm101-light-card.png", "gm101-dark-card.png"],
    ['theme_colors'=>$colors['light'] === ['r'=>248,'g'=>248,'b'=>248] && $colors['dark'] === ['r'=>24,'g'=>34,'b'=>43],'size_gm101_light_card'=>gmInspect('gm101-light-card.png')['width'] === 320 && gmInspect('gm101-light-card.png')['height'] === 200,'size_gm101_dark_card'=>gmInspect('gm101-dark-card.png')['width'] === 320 && gmInspect('gm101-dark-card.png')['height'] === 200],
    $errors ?? [], ['background_colors' => $colors, 'background_applied_by' => 'newImage + compositeImage OVER']);
echo "gm101-light-card.png 320x200\ngm101-dark-card.png 320x200\n";
Ожидаемый результат
gm101-light-card.png 320x200
gm101-dark-card.png 320x200

Запуск: php example.php с Gmagick. Проверенная среда: PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16. Архив содержит точные собственные входы в .b64; gm-fixture.php восстанавливает их и записывает проверочные metrics.json. Изучаемые операции находятся в программе. Исходный logo.png остаётся прозрачным и неизменным.

У прозрачного угла исходника alpha равна 0, поэтому здесь полностью виден фон. У синей эмблемы alpha равна 255, её цвет остаётся прежним. У белой полосы вне эмблемы alpha равна 64 из 255: на тёмном фоне её RGB стал 81,89,96, а на светлом — 249,249,249. Это реальные значения сохранённых файлов; прозрачность нельзя оценивать по одному названию цвета.

Уменьшить логотип, сохранив прозрачность

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

Тот же логотип наложен на отдельную клетчатую подложку
Тот же логотип наложен на отдельную клетчатую подложку — 320 × 200 px.
Самостоятельный прозрачный PNG для компактной карточки
Самостоятельный прозрачный PNG для компактной карточки — 160 × 100 px.
Уменьшенный логотип поверх отдельной клетчатой подложки
Уменьшенный логотип поверх отдельной клетчатой подложки — 160 × 100 px.
<?php
$preview = new Gmagick(__DIR__ . '/logo.png');
$preview->thumbnailImage(160, 100, true);
$preview->setImageMatteColor('#f8f8f8');
$preview->setImageFormat('PNG');
$preview->writeImage(__DIR__ . '/small-logo.png');

thumbnailImage ограничивает размер рамкой 160 × 100 и при true сохраняет пропорции. Наш исходник 320 × 200 уменьшается вдвое по обеим осям. Назначение matte color сделано после изменения размера. Полная программа повторно открывает полученный PNG и проверяет наличие реально прозрачных пикселей; это проверка результата записи, а не предположение о настройке объекта.

Уменьшить логотип, сохранив прозрачностьСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$preview = new Gmagick(__DIR__ . '/logo.png');
$preview->thumbnailImage(160, 100, true);
$preview->setImageMatteColor('#f8f8f8');
$matteAvailable = method_exists($preview, 'getImageMatte');
$matteChannel = $matteAvailable ? $preview->getImageMatte() : null;
$preview->setImageDepth(8);
$preview->setImageFormat('PNG');
$preview->writeImage(__DIR__ . '/gm101-small-logo.png');
$decoded = new Gmagick(__DIR__ . '/gm101-small-logo.png');
$hasTransparency = false;
foreach ($decoded->getImageHistogram() as $pixel) {
    if ($pixel->getColorValue(Gmagick::COLOR_OPACITY) > 0.0) {
        $hasTransparency = true;
        break;
    }
}
$checker = new Gmagick(__DIR__ . '/checker.ppm');
$checker->resizeImage(160, 100, Gmagick::FILTER_POINT, 1.0, false);
$checker->compositeImage($preview, Gmagick::COMPOSITE_OVER, 0, 0);
$checker->setImageDepth(8);
$checker->setImageFormat('PNG');
$checker->writeImage(__DIR__ . '/gm101-small-checker.png');

gmReport('gm101-alpha-preview',["gmagick.construct", "gmagick.thumbnailimage", "gmagick.setimagemattecolor", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.getimagehistogram", "gmagickpixel.getcolorvalue", "gmagick.resizeimage", "gmagick.compositeimage"],["gm101-small-logo.png", "gm101-small-checker.png"],
    ['guarded_method_unavailable'=>$matteAvailable === false && $matteChannel === null,'saved_transparency'=>$hasTransparency,'size_gm101_small_logo'=>gmInspect('gm101-small-logo.png')['width'] === 160 && gmInspect('gm101-small-logo.png')['height'] === 100,'size_gm101_small_checker'=>gmInspect('gm101-small-checker.png')['width'] === 160 && gmInspect('gm101-small-checker.png')['height'] === 100],
    $errors ?? [], ['matte_method_available' => $matteAvailable, 'availability_path' => 'guarded_fallback', 'alternative_executed' => true, 'saved_png_has_transparent_pixels' => $hasTransparency]);
echo "gm101-small-logo.png 160x100\ngm101-small-checker.png 160x100\n";
Ожидаемый результат
gm101-small-logo.png 160x100
gm101-small-checker.png 160x100

Запуск: php example.php с Gmagick. Проверенная среда: PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16. Архив содержит точные собственные входы в .b64; gm-fixture.php восстанавливает их и записывает проверочные metrics.json. Изучаемые операции находятся в программе. Исходный logo.png остаётся прозрачным и неизменным.

Для показа на клетках уменьшается отдельный фон, затем поверх него накладывается маленький логотип. Файл small-logo.png остаётся пригодным для других подложек. В проверяемых точках (5,5) alpha осталась 0, а у полосы в (25,50) — 64. Координаты проверки относятся уже к новой геометрии 160 × 100.

Гистограмма подходит для этого небольшого изображения с немногими цветами. Для больших фотографий её построение обрабатывает весь растр и требует памяти для найденных цветов; проверка одного заранее выбранного пикселя дешевле, но не заменяет полный ответ. Размер и исходный формат входа следует учитывать при выборе способа проверки. О размерах и пропорциях см. thumbnailImage и resizeImage.

Подготовить непрозрачную карточку функцией и обработать ошибки

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

Тот же логотип наложен на отдельную клетчатую подложку
Тот же логотип наложен на отдельную клетчатую подложку — 320 × 200 px.
Непрозрачная янтарная карточка; исходный прозрачный файл сохранён отдельно
Непрозрачная янтарная карточка; исходный прозрачный файл сохранён отдельно — 320 × 200 px.
<?php
$logo = new Gmagick(__DIR__ . '/logo.png');
$logo->setImageMatteColor('#e5a74a');
$rgb = $logo->getImageMatteColor()->getColor(true);
$color = sprintf('#%02x%02x%02x', $rgb['r'], $rgb['g'], $rgb['b']);
$card = new Gmagick();
$card->newImage(320, 200, $color, 'png');
$card->compositeImage($logo, Gmagick::COMPOSITE_OVER, 0, 0);

Малый фрагмент связывает настройку, чтение цвета и наложение. Полная функция получает объект и строку цвета через параметры, читает ширину и высоту исходника, создаёт новый холст и возвращает его через return. clone используется только для копии настроек: вызов функции не меняет свойство matte color исходного объекта. После возврата обычный writeImage записывает полученную карточку.

Подготовить непрозрачную карточку функцией и обработать ошибкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
function catalogCard(Gmagick $source, string $background): Gmagick {
    $settings = clone $source;
    $settings->setImageMatteColor($background);
    $rgb = $settings->getImageMatteColor()->getColor(true);
    $css = sprintf('#%02x%02x%02x', $rgb['r'], $rgb['g'], $rgb['b']);
    $canvas = new Gmagick();
    $canvas->newImage($source->getImageWidth(), $source->getImageHeight(), $css, 'png');
    $canvas->compositeImage($source, Gmagick::COMPOSITE_OVER, 0, 0);
    return $canvas;
}
$source = new Gmagick(__DIR__ . '/logo.png');
$before = $source->getImageSignature();
$card = catalogCard($source, '#e5a74a');
$card->setImageDepth(8);
$card->setImageFormat('PNG');
$card->writeImage(__DIR__ . '/gm101-catalog-card.png');
$decoded = new Gmagick(__DIR__ . '/gm101-catalog-card.png');
$allOpaque = true;
foreach ($decoded->getImageHistogram() as $pixel) {
    if ($pixel->getColorValue(Gmagick::COLOR_OPACITY) > 0.0) $allOpaque = false;
}
$errors = [
    'bad_color' => gmTry(fn() => catalogCard($source, 'this-is-not-a-color')),
    'empty_getter' => gmTry(fn() => (new Gmagick())->getImageMatteColor()),
    'array_color' => gmTry(fn() => $source->setImageMatteColor([]))
];

gmReport('gm101-alpha-catalog-function',["gmagick.construct", "gmagick.setimagemattecolor", "gmagick.getimagemattecolor", "gmagickpixel.getcolor", "gmagick.newimage", "gmagick.getimagewidth", "gmagick.getimageheight", "gmagick.compositeimage", "gmagick.getimagesignature", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.writeimage", "gmagick.getimagehistogram", "gmagickpixel.getcolorvalue"],["gm101-catalog-card.png"],
    ['source_pixels_unchanged'=>$before === $source->getImageSignature(),'output_opaque'=>$allOpaque,'bad_color_caught'=>$errors['bad_color']['class'] === 'GmagickPixelException','empty_caught'=>$errors['empty_getter']['class'] === 'GmagickException','wrong_type_caught'=>$errors['array_color']['class'] === 'GmagickException','size_gm101_catalog_card'=>gmInspect('gm101-catalog-card.png')['width'] === 320 && gmInspect('gm101-catalog-card.png')['height'] === 200],
    $errors ?? [], ['actual_output_opaque' => $allOpaque, 'source_pixels_preserved' => $before === $source->getImageSignature()]);
echo "gm101-catalog-card.png 320x200\n";
Ожидаемый результат
gm101-catalog-card.png 320x200

Запуск: php example.php с Gmagick. Проверенная среда: PHP 8.3.6, Gmagick 2.0.6RC1, GraphicsMagick 1.3.42 Q16. Архив содержит точные собственные входы в .b64; gm-fixture.php восстанавливает их и записывает проверочные metrics.json. Изучаемые операции находятся в программе. Исходный logo.png остаётся прозрачным и неизменным.

Непонятная строка цвета дала GmagickPixelException, чтение свойства пустого изображения — GmagickException, массив вместо допустимого цвета в этом setter — тоже GmagickException. Не подменяем все отказы одним выдуманным TypeError. Для результата проверена непрозрачность всех цветов гистограммы; пиксели исходника и исходный файл сохранены.

Путь данных в catalogCard: исходный Gmagick и строка цвета → копия настройки → GmagickPixel → массив RGB → строка #RRGGBB → новый холст → OVER → возвращённая карточка. При другом фоне вызывающий код меняет только второй аргумент. Функции и возвращаемые значения разобраны в основах функций, отдельная обработка отказов — в исключениях.

Упражнения. Может ли RGBA PNG быть полностью непрозрачным? Да: все значения alpha могут равняться 255. Закрасит ли setImageMatteColor прозрачные места? В показанной операции нет: нужен отдельный фон и наложение. Можно ли заменить проверку наличия канала проверкой одного прозрачного пикселя? Нет: это разные вопросы. Как сохранить универсальный исходник? Записать карточку в другой файл и оставить logo.png отдельно. Следующий шаг — гамма и цветовые метаданные; проверка реального формата файла — в экспорте и кодировании.

Практические вопросы, использованные как задачи

Detect Alpha Channel with ImageMagick: Автор хочет выбирать PNG для изображений с прозрачностью и JPEG для остальных и спрашивает, как обнаружить прозрачность входа. Наш пример разделяет наличие канала и его фактические значения. Он показывает RGBA с полностью непрозрачными пикселями, прозрачный логотип и рабочую проверку гистограммы при отсутствии getter. Формат выбирается по требованиям к результату; одно расширение имени ничего не доказывает.

Set transparent background using ImageMagick and commandline prompt: Автор назначает background none и пробует flatten, но белые пиксели изображения не становятся прозрачными. Мы показываем ту же важную границу на matte color: установка свойства не заменяет изменение пикселей. На собственной эмблеме сравниваются настройка, реальная alpha и явное наложение. Алгоритм удаления белого фона не выдаётся за следствие этого setter.

GraphicsMagick using nodejs not returning correct image: После обработки изображения через GraphicsMagick автор не получает ожидаемый белый фон в прозрачной области при подготовке JPEG. В нашем маршруте фон сначала создаётся как настоящее изображение, затем выполняется OVER. Исходный прозрачный PNG остаётся отдельным файлом. Видимые светлый, тёмный и янтарный варианты доказывают применение цвета до дальнейшего выбора формата экспорта.

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

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

Gmagick::getimagematteПроверить наличие matte-канала с учётом доступности

PECL gmagick >= Unknown · gmagick

Gmagick::getimagematte(): int

Проверяет наличие matte-канала у активного изображения. Это структурный признак: канал может существовать и содержать только полностью непрозрачные значения. В проверенной сборке этот метод отсутствует, поэтому примеры используют method_exists и отдельную проверку фактической прозрачности. Успешный вызов отсутствующего getter здесь не заявляется.

Gmagick::getimagematte(): int

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

Возврат по официальной странице: сигнатура содержит int, а текст описывает true при наличии matte-канала и false при его отсутствии. Мы сохраняем это различие документации, не выдумывая фактический тип для отсутствующего метода.

Официальная ошибка — GmagickException. Если сам метод не включён в установленную сборку, прямой вызов в PHP даёт Error раньше библиотечной операции; это отдельная граница доступности.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; номер PHP в шапке сайта не уточняет её. Доступность метода проверяется у реально установленного расширения. Здесь среда PHP 8.3.6 / Gmagick 2.0.6RC1 / GraphicsMagick 1.3.42 Q16.

Два рабочих сценария с проверкой доступности и альтернативой: Увидеть прозрачность на клетчатой подложке; Уменьшить логотип, сохранив прозрачность.

Gmagick::getimagemattecolorПрочитать свойство matte color как объект цвета

PECL gmagick >= Unknown · gmagick

Gmagick::getimagemattecolor(): GmagickPixel

Возвращает цвет свойства matte color активного изображения как отдельный объект GmagickPixel. Это значение настройки изображения; оно не сообщает, есть ли прозрачные пиксели, и само чтение не меняет изображение. Примеры читают RGB-компоненты, затем явно используют их как цвет нового холста.

Gmagick::getimagemattecolor(): GmagickPixel

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

Возврат: GmagickPixel при успехе. Для чтения RGB можно вызвать getColor(true); это массив цвета, а не строка для автоматической передачи в любой графический метод.

Официальная ошибка — GmagickException. Пустой Gmagick действительно вызвал такое исключение в проверенном окружении.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; номер PHP в шапке сайта не уточняет её. Доступность метода проверяется у реально установленного расширения. Здесь среда PHP 8.3.6 / Gmagick 2.0.6RC1 / GraphicsMagick 1.3.42 Q16.

Два самостоятельных применения: Проверить, закрашивает ли matte color прозрачные места; Получить светлую и тёмную карточку с реальным фоном.

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

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

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

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

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