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

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

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

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

Глава 414 · После первых изображений, массивов и объектов Gmagick

Gmagick: объект цвета, каналы и палитра изображения

Создать и прочитать цвет, изменить канал, посчитать частоты и выбрать акценты собственного рисунка.

Получить образец цвета из строки и объекта

Продолжаем первые изображения Gmagick. Здесь Gmagick работает с GraphicsMagick; это не другое имя Imagick и не его новая версия. Проверенный отдельный runtime: PHP8.3.6, Gmagick2.0.6RC1, GraphicsMagick1.3.42 Q16. Расширение должно быть загружено именно в том PHP, который запускает программу; наличие класса проверяют class_exists('Gmagick'). Доступность и установка разобраны в начале маршрута.

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

Слева #244f65, справа новый цвет того же GmagickPixel #e5a74a
Слева #244f65, справа новый цвет того же GmagickPixel #e5a74a — 320 × 200 px.
<?php
$color = new GmagickPixel('#244f65');
$rgb = $color->getColor(true);
echo $rgb['r'], ', ', $rgb['g'], ', ', $rgb['b'], "\n";
$color->setColor('rgb(229,167,74)');
echo $color->getColor(true)['r'], "\n";

new создаёт объект GmagickPixel, а переменная $color хранит его. Строка #244f65 содержит три шестнадцатеричные пары RGB: красный 36, зелёный 79, синий 101. Стрелка -> вызывает метод объекта. getColor(true) возвращает массив; ключи r, g, b позволяют взять отдельные числа. Код выводит «36, 79, 101», затем «229». setColor меняет тот же объект. В полной программе первая rectangle уже запомнила синий стиль, поэтому последующая смена цвета не перекрашивает первую фигуру.

Получить образец цвета из строки и объектаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image = new Gmagick();
$image->newImage(320,200,'#ffffff','png');
$color = new GmagickPixel('#244f65');
$rgb = $color->getColor(true);
$normalized = $color->getColor(true,true);
$serialized = $color->getColor();
$draw = new GmagickDraw();
$draw->setFillColor($color);
$draw->rectangle(20,30,150,170);
$changed = $color->setColor('rgb(229,167,74)');
$draw->setFillColor($color);
$draw->rectangle(170,30,300,170);
$image->drawImage($draw);
$errors = ['color'=>gmTry(fn()=>new GmagickPixel('not-a-color'))];
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-color-swatches.png');

gmReport('gm98-color-swatch',["gmagick.construct", "gmagickpixel.construct", "gmagickdraw.construct", "gmagick.newimage", "gmagickpixel.getcolor", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagickpixel.setcolor", "gmagick.drawimage", "gmagick.setimageformat", "gmagick.setimagedepth", "gmagick.writeimage"],["gm98-color-swatches.png"],
    ['same_pixel'=>$changed===$color,'rgb_blue'=>$rgb===['r'=>36,'g'=>79,'b'=>101],'normalized_red'=>abs($normalized["r"]-36/255)<0.00002,'invalid_color'=>$errors['color']['class']==='GmagickPixelException','geometry_color_swatches'=>gmInspect('gm98-color-swatches.png')['width']===320&&gmInspect('gm98-color-swatches.png')['height']===200],
    $errors ?? [], ['rgb'=>$rgb,'normalized'=>$normalized,'runtime_string'=>$serialized]);
echo "gm98-color-swatches.png 320x200\n";
Ожидаемый результат
gm98-color-swatches.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-color-swatches.png 320x200

getColor() без true на этом Q16-стенде возвращает строку rgb(9252,20303,25957). Это значения внутреннего диапазона, а не готовая CSS-строка с числами 0–255. Для веб-цвета используйте массив и явное форматирование, для передачи между Gmagick-операциями — сам GmagickPixel. getColor(true,true) возвращает доли 0–1. Неизвестное название цвета перехватывается как GmagickPixelException: ошибка создаётся до появления полезного рисунка.

Основа синтаксиса: переменные, массивы, объекты и вызов методов. Полный архив запускается командой php example.php. gm-fixture.php восстанавливает собственные входы и проверяет результат; он не рисует изучаемые фигуры. Файлы PNG и metrics.json сохраняются рядом с программой. В коротких фрагментах с product.ppm этот файл уже должен лежать рядом; архивы восстанавливают его из .b64.

Изменить один канал, оставив два других

Теперь нужно получить вариант фирменного цвета, меняя только красную составляющую. Два образца позволяют увидеть изменение без случайной потери зелёного и синего. Значение отдельного канала задаётся долей, поэтому 0.5 означает половину диапазона, а не число 128 или 50 процентов в строке.

Справа красный канал установлен в 0.5; зелёный и синий сохранены
Справа красный канал установлен в 0.5; зелёный и синий сохранены — 320 × 200 px.
<?php
$color = new GmagickPixel('#244f65');
$before = $color->getColorValue(Gmagick::COLOR_RED);
$color->setColorValue(Gmagick::COLOR_RED, 0.5);
$after = $color->getColorValue(Gmagick::COLOR_RED);
echo round($before, 3), ' -> ', round($after, 3), "\n";

Gmagick::COLOR_RED — именованная константа канала, не строка «red». Двойное двоеточие обращается к константе класса. getColorValue читает число в диапазоне 0–1, setColorValue записывает новое. round(...,3) округляет только вывод: получится «0.141 -> 0.5». В полной программе массивы до и после подтверждают, что зелёный 79 и синий 101 не изменились; при переводе красного в целочисленный RGB8 действует округление.

Изменить один канал, оставив два другихСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image = new Gmagick();
$image->newImage(320,200,'#ffffff','png');
$color = new GmagickPixel('#244f65');
$original = $color->getColor(true);
$redBefore = $color->getColorValue(Gmagick::COLOR_RED);
$draw = new GmagickDraw();
$draw->setFillColor($color);$draw->rectangle(20,30,150,170);
$result = $color->setColorValue(Gmagick::COLOR_RED,0.5);
$redAfter = $color->getColorValue(Gmagick::COLOR_RED);
$changed = $color->getColor(true);
$draw->setFillColor($color);$draw->rectangle(170,30,300,170);
$image->drawImage($draw);
$errors = ['channel'=>gmTry(fn()=>$color->getColorValue(-999))];
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-red-channel.png');

gmReport('gm98-color-channel',["gmagick.construct", "gmagickpixel.construct", "gmagickdraw.construct", "gmagick.newimage", "gmagickpixel.getcolor", "gmagickpixel.getcolorvalue", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagickpixel.setcolorvalue", "gmagick.drawimage", "gmagick.setimageformat", "gmagick.setimagedepth", "gmagick.writeimage"],["gm98-red-channel.png"],
    ['same_pixel'=>$result===$color,'red_half'=>abs($redAfter-0.5)<0.00002,'other_channels'=>$changed['g']===$original['g']&&$changed['b']===$original['b'],'unknown_channel'=>$errors['channel']['class']==='GmagickPixelException','geometry_red_channel'=>gmInspect('gm98-red-channel.png')['width']===320&&gmInspect('gm98-red-channel.png')['height']===200],
    $errors ?? [], ['before'=>$original,'after'=>$changed,'red_before'=>$redBefore,'red_after'=>$redAfter]);
echo "gm98-red-channel.png 320x200\n";
Ожидаемый результат
gm98-red-channel.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-red-channel.png 320x200

Число −999 не является константой канала: проверенный getColorValue даёт GmagickPixelException. Не вводите номер канала вручную. Для формы, где пользователь задаёт 0–255, сначала проверьте границы и разделите значение на 255; готовую проверку допустимых долей показывает функция темы ниже.

Отличить канал цвета от реальной прозрачности рисунка

У плашки нужно сохранить видимый фон. Однако сохранённый канал цвета ещё не доказывает прозрачность рисунка: в этой сборке передача GmagickPixel с opacity 0.5 в setFillColor даёт непрозрачную фигуру. Слева и в центре видны одинаковые синие плашки при разных настройках Pixel. Справа показан рабочий путь: отдельный белый Draw-слой осветляет синий, сохраняя его видимым.

Слева Pixel opacity 0, в центре Pixel opacity 0.5: обе плашки непрозрачные; справа белый Draw-слой с реальной alpha 64/255 поверх синего
Слева Pixel opacity 0, в центре Pixel opacity 0.5: обе плашки непрозрачные; справа белый Draw-слой с реальной alpha 64/255 поверх синего — 320 × 200 px.
<?php
$color = new GmagickPixel('#244f65');
$color->setColorValue(Gmagick::COLOR_OPACITY, 0.5);
$opacity = $color->getColorValue(Gmagick::COLOR_OPACITY);
$rgb = $color->getColor(true);
echo round($opacity, 2), ' / ', count($rgb), "\n";

Код выводит «0.5 / 3»: канал читается обратно, а массив содержит r, g, b. COLOR_OPACITY использует 0 для непрозрачного цвета и 1 для прозрачного; это обратная шкала к alpha. В полной программе foreach перебирает 0 и 0.5 и передаёт каждый объект в отдельный GmagickDraw. Две одинаковые плашки показывают ограничение такой передачи. Затем 1−0.5 преобразует запрос в шкалу непрозрачности Draw; отдельный setFillOpacity задаёт его явно на белом прозрачном слое.

Отличить канал цвета от реальной прозрачности рисункаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image = new Gmagick();
$image->newImage(320,200,'#ffffff','png');
$observed = [];
foreach ([0.0,0.5] as $index=>$opacity) {
    $color = new GmagickPixel('#244f65');
    $color->setColorValue(Gmagick::COLOR_OPACITY,$opacity);
    $observed[] = ['opacity'=>$color->getColorValue(Gmagick::COLOR_OPACITY),'rgb'=>$color->getColor(true),'normalized'=>$color->getColor(true,true)];
    $draw = new GmagickDraw();
    $draw->setFillColor($color);
    $draw->rectangle(10+$index*105,30,100+$index*105,170);
    $image->drawImage($draw);
}
$requested = 1.0-$color->getColorValue(Gmagick::COLOR_OPACITY);
$layer = new Gmagick();$layer->newImage(90,140,'none','png');
$fill = new GmagickDraw();$fill->setFillColor(new GmagickPixel('white'));
$fill->setFillOpacity($requested);
$fill->rectangle(0,0,89,139);$layer->drawImage($fill);
$layer->setImageDepth(8);$layer->setImageFormat('PNG');
$decoded = new Gmagick();$decoded->readImageBlob($layer->getImageBlob());
$decoded->cropImage(1,1,20,20);
$actualOpacity = $decoded->getImageHistogram()[0]->getColorValue(Gmagick::COLOR_OPACITY);
$swatch = new Gmagick();$swatch->newImage(90,140,'#244f65','png');
$swatch->compositeImage($layer,Gmagick::COMPOSITE_OVER,0,0);
$image->compositeImage($swatch,Gmagick::COMPOSITE_OVER,220,30);
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-pixel-opacity.png');

gmReport('gm98-color-opacity',["gmagick.construct", "gmagickpixel.construct", "gmagickdraw.construct", "gmagick.newimage", "gmagickpixel.setcolorvalue", "gmagickpixel.getcolorvalue", "gmagickpixel.getcolor", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagick.drawimage", "gmagickdraw.setfillopacity", "gmagick.setimagedepth", "gmagick.setimageformat", "gmagick.readimageblob", "gmagick.getimageblob", "gmagick.cropimage", "gmagick.getimagehistogram", "gmagick.compositeimage", "gmagick.writeimage"],["gm98-pixel-opacity.png"],
    ['two_pixel_settings'=>count($observed)===2,'channel_roundtrip'=>abs($observed[1]["opacity"]-0.5)<0.00002,'array_is_rgb'=>array_keys($observed[1]["rgb"])===["r","g","b"],'explicit_fill_request'=>abs($fill->getFillOpacity()-0.5)<0.00002,'encoded_layer_alpha64'=>abs($actualOpacity-191/255)<1e-9,'geometry_pixel_opacity'=>gmInspect('gm98-pixel-opacity.png')['width']===320&&gmInspect('gm98-pixel-opacity.png')['height']===200],
    $errors ?? [], ['pixel_settings'=>$observed,'requested_draw_fill'=>$requested,'encoded_png_opacity'=>$actualOpacity,'encoded_png_alpha'=>64]);
echo "gm98-pixel-opacity.png 320x200\n";
Ожидаемый результат
gm98-pixel-opacity.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-pixel-opacity.png 320x200

И этот setter в Gmagick2.0.6RC1/GraphicsMagick1.3.42 Q16 не доказывает ожидаемые 50%: запрос 0.5 фактически даёт в закодированном PNG alpha 64/255, около 25% непрозрачности. Программа кодирует слой, читает его обратно, проверяет COLOR_OPACITY=191/255 и только затем накладывает через COMPOSITE_OVER. Справа получается RGB90,123,139. Это конкретный проверенный путь, а не универсальная формула преобразования прозрачности. PHP.net описывает четвёртую составляющую opacity в массиве getColor, но этот runtime возвращает только RGB; канал читаем отдельно. Не переносите CSS-смысл rgba(...,0.25) на эту сборку: её разбор также отличается. Подробный слой с подписью и сохранённой альфой разобран в соседней главе наложения.

Посчитать цвета и построить полосы их частот

Автоматически выбрать акцент по фотографии трудно, пока неизвестно, какие цвета в ней вообще есть. Начнём с собственного простого рисунка: шесть цветов, 320×200, всего 64 000 пикселей. Рядом с ним — полосы, длина которых показывает частоту каждого цвета, а не его яркость.

Собственный растр: шесть цветов и 64 000 пикселей
Собственный растр: шесть цветов и 64 000 пикселей — 320 × 200 px.
Шесть полос, длина пропорциональна количеству пикселей каждого цвета
Шесть полос, длина пропорциональна количеству пикселей каждого цвета — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/product.ppm');
echo $image->getImageColors(), "\n";
$histogram = $image->getImageHistogram();
foreach ($histogram as $color) {
    echo $color->getColorCount(), "\n";
}

getImageColors возвращает число различных цветов: здесь 6. getImageHistogram возвращает массив GmagickPixel. В foreach переменная $color по очереди получает каждый объект, а getColorCount — число пикселей этого цвета в гистограмме. Порядок элементов не используем как рейтинг. Полная программа собирает RGB и частоту, сортирует по убыванию количества и вычисляет ширину полосы относительно наибольшего количества 31 000.

Посчитать цвета и построить полосы их частотСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$image = new Gmagick(__DIR__.'/product.ppm');
$colors = $image->getImageColors();
$histogram = $image->getImageHistogram();
$sum = 0; $rows = [];
foreach ($histogram as $pixel) {
    $rgb = $pixel->getColor(true);
    $count = $pixel->getColorCount();
    $rows[] = ['rgb'=>$rgb,'count'=>$count]; $sum += $count;
}
usort($rows,fn($a,$b)=>($b['count']<=>$a['count']) ?: ($a['rgb']['r']<=>$b['rgb']['r']));
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-histogram-source.png');
$chart = new Gmagick();
$chart->newImage(320,200,'#ffffff','png');
$draw = new GmagickDraw();
foreach ($rows as $index=>$row) {
    $rgb = $row['rgb'];
    $draw->setFillColor(sprintf('rgb(%d,%d,%d)',$rgb['r'],$rgb['g'],$rgb['b']));
    $draw->rectangle(10,10+30*$index,10+280*$row['count']/$rows[0]['count'],30+30*$index);
}
$chart->drawImage($draw);
$chart->setImageFormat('PNG');
$chart->setImageDepth(8);
$chart->writeImage(__DIR__.'/gm98-histogram-bars.png');

gmReport('gm98-color-histogram',["gmagick.construct", "gmagickdraw.construct", "gmagick.getimagecolors", "gmagick.getimagehistogram", "gmagickpixel.getcolor", "gmagickpixel.getcolorcount", "gmagick.setimageformat", "gmagick.setimagedepth", "gmagick.writeimage", "gmagick.newimage", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagick.drawimage"],["gm98-histogram-source.png", "gm98-histogram-bars.png"],
    ['six_colors'=>$colors===6&&count($histogram)===6,'whole_image'=>$sum===320*200,'largest_background'=>$rows[0]['count']===31000,'geometry_histogram_source'=>gmInspect('gm98-histogram-source.png')['width']===320&&gmInspect('gm98-histogram-source.png')['height']===200,'geometry_histogram_bars'=>gmInspect('gm98-histogram-bars.png')['width']===320&&gmInspect('gm98-histogram-bars.png')['height']===200],
    $errors ?? [], ['colors'=>$colors,'pixel_sum'=>$sum,'histogram'=>$rows]);
echo "gm98-histogram-source.png 320x200 gm98-histogram-bars.png 320x200\n";
Ожидаемый результат
gm98-histogram-source.png 320x200 gm98-histogram-bars.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-histogram-source.png 320x200 gm98-histogram-bars.png 320x200

Сумма частот равна 64 000; равенство проверяется программой. count($histogram) отвечает на вопрос «сколько записей», а сумма getColorCount — «сколько пикселей представлено». Гистограмма не содержит координат. У фотографии с шумом и сглаживанием могут быть сотни тысяч разных цветов, поэтому этот точный подсчёт не является готовой кластеризацией палитры. Размер входа и политику уменьшения выбирают заранее.

Выбрать три акцента, исключив известный фон

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

Три самых частых акцента после явного исключения двух фоновых цветов
Три самых частых акцента после явного исключения двух фоновых цветов — 320 × 200 px.
<?php
$image = new Gmagick(__DIR__ . '/product.ppm');
$histogram = $image->getImageHistogram();
$color = $histogram[0];
$rgb = $color->getColor(true);
echo $color->getColorCount(), ' pixels', "\n";

Короткий фрагмент показывает чтение одной записи, но не объявляет её наиболее частой. Полная программа перебирает все записи, сравнивает массивы RGB оператором === и пропускает известные фоновые цвета через continue. usort задаёт порядок по частоте, а при равенстве — по красному каналу, чтобы порядок был воспроизводим. array_slice(...,0,3) берёт три первых результата. Новый GmagickPixel без аргумента получает цвет позже через setColor.

Выбрать три акцента, исключив известный фонСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
$source = new Gmagick(__DIR__.'/product.ppm');
$countColors = $source->getImageColors();
$choices = [];
foreach ($source->getImageHistogram() as $pixel) {
    $rgb = $pixel->getColor(true); $count = $pixel->getColorCount();
    if ($rgb===['r'=>244,'g'=>237,'b'=>220] || $rgb===['r'=>248,'g'=>243,'b'=>229]) { continue; }
    $choices[] = ['rgb'=>$rgb,'count'=>$count];
}
usort($choices,fn($a,$b)=>($b['count']<=>$a['count']) ?: ($a['rgb']['r']<=>$b['rgb']['r']));
$palette = array_slice($choices,0,3);
$image = new Gmagick();
$image->newImage(320,200,'#ffffff','png');
$draw = new GmagickDraw();
foreach ($palette as $index=>$entry) {
    $rgb=$entry['rgb']; $color=new GmagickPixel();
    $color->setColor(sprintf('#%02x%02x%02x',$rgb['r'],$rgb['g'],$rgb['b']));
    $draw->setFillColor($color);$draw->rectangle(10+105*$index,30,100+105*$index,170);
}
$image->drawImage($draw);
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-accent-palette.png');

gmReport('gm98-color-palette',["gmagick.construct", "gmagickdraw.construct", "gmagickpixel.construct", "gmagick.getimagecolors", "gmagick.getimagehistogram", "gmagickpixel.getcolor", "gmagickpixel.getcolorcount", "gmagick.newimage", "gmagickpixel.setcolor", "gmagickdraw.setfillcolor", "gmagickdraw.rectangle", "gmagick.drawimage", "gmagick.setimageformat", "gmagick.setimagedepth", "gmagick.writeimage"],["gm98-accent-palette.png"],
    ['source_colors'=>$countColors===6,'three_accents'=>count($palette)===3,'counts_selected'=>$palette[0]['count']===9600&&$palette[1]['count']===9600&&$palette[2]['count']===9180,'geometry_accent_palette'=>gmInspect('gm98-accent-palette.png')['width']===320&&gmInspect('gm98-accent-palette.png')['height']===200],
    $errors ?? [], $palette);
echo "gm98-accent-palette.png 320x200\n";
Ожидаемый результат
gm98-accent-palette.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-accent-palette.png 320x200

Получаются зелёный и красный по 9600 пикселей, затем синий — 9180. sprintf с %02x превращает целые RGB8 в шестнадцатеричные пары; это явная безопасная для смысла конверсия вместо использования Q16-строки getColor(). Если фон не известен заранее или состоит из оттенков, нужны другая стратегия и критерии группировки. Результат этого примера нельзя называть универсальным доминирующим цветом любого снимка.

Проверить настройки темы до рисования карточки

Повторяемый стиль карточки должен принимать проверенные значения. Функция темы создаёт цвет, меняет красную составляющую и opacity, затем возвращает GmagickPixel для рисования. Вызывающий код сам решает, какую фигуру нарисовать этим цветом.

Цвет функции темы применён к карточке с округлёнными углами
Цвет функции темы применён к карточке с округлёнными углами — 320 × 200 px.
<?php
$color = new GmagickPixel();
$color->setColor('#244f65');
$color->setColorValue(Gmagick::COLOR_RED, 0.5);
$color->setColorValue(Gmagick::COLOR_OPACITY, 0.0);
echo $color->getColorValue(Gmagick::COLOR_RED), "\n";

Короткий вызов выводит 0.5. В полной программе function объявляет themeColor; string и float описывают ожидаемые виды аргументов, а : GmagickPixel — вид результата. if отвергает доли вне 0–1, throw сообщает InvalidArgumentException, return передаёт готовый объект. Такой контроль — правило нашей функции, не обещание, что каждый setter библиотеки сам проверяет все границы. Свежий цвет имеет getColorCount()==0: это не статистика ещё не нарисованной карточки.

Проверить настройки темы до рисования карточкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__ . '/gm-fixture.php';
gmRestore();
function themeColor(string $definition,float $red,float $opacity): GmagickPixel {
    if ($red<0 || $red>1 || $opacity<0 || $opacity>1) { throw new InvalidArgumentException('Channels must be in 0..1'); }
    $pixel=new GmagickPixel();$pixel->setColor($definition);
    $pixel->setColorValue(Gmagick::COLOR_RED,$red);
    $pixel->setColorValue(Gmagick::COLOR_OPACITY,$opacity);
    return $pixel;
}
$color=themeColor('#244f65',0.5,0.0);
$state=['rgb'=>$color->getColor(true),'red'=>$color->getColorValue(Gmagick::COLOR_RED),'opacity'=>$color->getColorValue(Gmagick::COLOR_OPACITY),'count'=>$color->getColorCount()];
$errors=['range'=>gmTry(fn()=>themeColor('#244f65',255,0.0)),'channel'=>gmTry(fn()=>$color->setColorValue(-999,0.5))];
$image = new Gmagick();
$image->newImage(320,200,'#ffffff','png');
$draw=new GmagickDraw();$draw->setFillColor($color);$draw->roundRectangle(30,30,290,170,24,24);
$image->drawImage($draw);
$image->setImageFormat('PNG');
$image->setImageDepth(8);
$image->writeImage(__DIR__.'/gm98-theme-card.png');

gmReport('gm98-color-theme',["gmagickpixel.construct", "gmagick.construct", "gmagickdraw.construct", "gmagickpixel.setcolor", "gmagickpixel.setcolorvalue", "gmagickpixel.getcolor", "gmagickpixel.getcolorvalue", "gmagickpixel.getcolorcount", "gmagick.newimage", "gmagickdraw.setfillcolor", "gmagickdraw.roundrectangle", "gmagick.drawimage", "gmagick.setimageformat", "gmagick.setimagedepth", "gmagick.writeimage"],["gm98-theme-card.png"],
    ['red_half'=>abs($state["red"]-0.5)<0.00002,'fresh_count'=>$state["count"]===0,'range_rejected'=>$errors['range']['class']==='InvalidArgumentException','channel_rejected'=>$errors['channel']['class']==='GmagickPixelException','geometry_theme_card'=>gmInspect('gm98-theme-card.png')['width']===320&&gmInspect('gm98-theme-card.png')['height']===200],
    $errors ?? [], $state);
echo "gm98-theme-card.png 320x200\n";
Ожидаемый результат
gm98-theme-card.png 320x200

Все файлы архива кладутся рядом; php example.php восстанавливает собственные входы, сохраняет PNG и metrics.json. Нужен Gmagick: проверенный стенд PHP8.3.6 / Gmagick2.0.6RC1 / GraphicsMagick1.3.42 Q16. Команды рисования находятся непосредственно в программе; gm-fixture.php только готовит входы и проверяет результат.

Вывод успешного запуска
gm98-theme-card.png 320x200

Попытка передать красный 255 останавливается нашей проверкой; неправильная константа канала отдельно демонстрирует GmagickPixelException. Эти ошибки имеют разные причины. На выходе — настоящая закруглённая карточка, в следующей главе разберём команды, которые создают её форму. Нельзя считать успешным только создание объекта: полезный результат появляется после drawImage и записи PNG.

Упражнение: как задать зелёному каналу максимальную долю? Ответ: setColorValue(Gmagick::COLOR_GREEN,1.0). Почему getColorCount у свежего цвета равен0? Ответ: объект не получен как запись гистограммы с частотой. Как получить общее количество пикселей по гистограмме? Ответ: сложить getColorCount всех записей. Приём с foreach разобран в циклах, оформление themeColor — в функциях.

Практический вопрос, из которого вырос сценарий

PHP GMagick: how to get pixel color?: Автор хочет получить цвет пикселя в Gmagick и ищет прямой аналог getImagePixelColor из Imagick. Разделяем объект цвета и координату: GmagickPixel сам не читает фотографию, а гистограмма содержит частоты, не позиции. На собственном рисунке строим полосы частот и палитру. Для одной проверочной точки используем копию, вырезку 1×1 и гистограмму этой копии. Не выдаём API Imagick за API Gmagick.

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

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

Gmagick::getimagecolorsУзнать число цветов текущего изображения

PECL gmagick >= Unknown · gmagick

Gmagick::getimagecolors(): int

Узнать число цветов текущего изображения. Аргументов нет; возвращается int — количество цветов. В основном описании PHP.net есть противоречивая фраза о цвете по индексу палитры, но индекс не входит в сигнатуру, а раздел возврата и реальный вызов дают количество. На нашем входе результат 6 совпадает с числом записей гистограммы. Это не количество пикселей, не глубина каналов и не количество байтов PNG. PHP.net указывает GmagickException при ошибке.

Gmagick::getimagecolors(): int

Аргументов нет: пустые скобки вызывают чтение текущего состояния.

Возвращаемое значение: Целое число, смысл зависит от метода и пояснён выше.

Официальный отказ: GmagickException при ошибке операции.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Посчитать цвета и построить полосы их частот; Выбрать три акцента, исключив известный фон.

Gmagick::getimagehistogramПолучить цвета и их частоты

PECL gmagick >= Unknown · gmagick

Gmagick::getimagehistogram(): array

Получить цвета и их частоты. Аргументов нет. Возвращается массив GmagickPixel, по одному объекту на представленный цвет; частоту читают getColorCount, компоненты — getColor. PHP.net указывает GmagickException. Массив гистограммы не является сеткой координат: его индекс не задаёт положение пикселя. Для нашего собственного изображения получены шесть цветов, частоты суммируются в 320×200. Порядок для вывода выбираем самостоятельно: сортируем по частоте, а равные частоты — по красному каналу. На фотографии множество близких оттенков увеличит размер результата; шесть цветов примера не являются ограничением API.

Gmagick::getimagehistogram(): array

Аргументов нет: пустые скобки вызывают чтение текущего состояния.

Возвращаемое значение: Массив объектов GmagickPixel.

Официальный отказ: GmagickException при ошибке операции.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Посчитать цвета и построить полосы их частот; Выбрать три акцента, исключив известный фон.

GmagickPixel::__constructСоздать объект, представляющий цвет

PECL gmagick >= Unknown · gmagick

GmagickPixel::__construct(string $color = ?): void

Создать объект, представляющий цвет. Необязательная строка color задаёт исходный цвет. Без аргумента создаётся объект, которому затем можно назначить цвет через setColor. Это не чтение пикселя из фотографии: координат и изображения в конструкторе нет. new возвращает созданный GmagickPixel, а сам конструктор не является методом цепочки. PHP.net показывает необязательный string с неопределённым значением по умолчанию; Reflection проверенной сборки показывает ?string=null. Неверная строка дала GmagickPixelException.

GmagickPixel::__construct(string $color = ?): void
АргументТип и обязательностьЗначение
colorstring; необязательныйНеобязательная строка начального цвета; можно назначить цвет позже.

Возвращаемое значение: Конструктор не имеет отдельного возвращаемого значения; выражение new создаёт объект.

На этой странице PHP.net отдельный список исключений не приведён; это не гарантия отсутствия отказов. Неверный PHP-тип может дать TypeError, неверная строка цвета — GmagickPixelException, а проверенный неполный массив точек — Exception. Ошибки перехватываются в самостоятельных примерах там, где создаются соответствующие данные.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Получить образец цвета из строки и объекта; Проверить настройки темы до рисования карточки.

GmagickPixel::getcolorПолучить строку, RGB-массив или нормализованные каналы

PECL gmagick >= Unknown · gmagick

GmagickPixel::getcolor(bool $as_array = false, bool $normalize_array = false): mixed

Получить строку, RGB-массив или нормализованные каналы. as_array=false запрашивает строку, true — массив. normalize_array=false оставляет значения массива в обычном представлении, true нормализует их; в нашем RGB-входе это r/g/b в 0…1 вместо 0…255. Официальное описание также обещает четвёртую компоненту opacity, если она задана. Однако в проверенной сборке массив содержит только r/g/b, а строка показывает Q16-значения: исходному #244f65 соответствует rgb(9252,20303,25957). Это не готовый CSS RGB8 и не надёжное сохранение прозрачности. Для канала opacity используйте getColorValue(COLOR_OPACITY). Возвращается string или array; PHP.net указывает GmagickPixelException при ошибке.

GmagickPixel::getcolor(bool $as_array = false, bool $normalize_array = false): mixed
АргументТип и обязательностьЗначение
as_arraybool; необязательный, по умолчанию falsefalse возвращает строку, true запрашивает массив.
normalize_arraybool; необязательный, по умолчанию falsetrue нормализует числовые каналы массива.

Возвращаемое значение: Строка либо массив согласно флагам.

Описание возвращаемого значения PHP.net предусматривает GmagickPixelException при ошибке.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Получить образец цвета из строки и объекта; Отличить канал цвета от реальной прозрачности рисунка.

GmagickPixel::getcolorcountПрочитать число пикселей с данным цветом из гистограммы

PECL gmagick >= Unknown · gmagick

GmagickPixel::getcolorcount(): int

Прочитать число пикселей с данным цветом из гистограммы. Без аргументов. Возвращается int — счётчик, связанный с этим цветом; PHP.net указывает GmagickPixelException при неудаче. У объектов, полученных из getImageHistogram, счётчик показывает частоту цвета во входном изображении. У просто созданного GmagickPixel в probe он равен нулю: объект цвета сам не анализирует фотографию. Сумма шести частот нашего растра равна 64 000, то есть 320×200. Для доли цвета делите его счётчик на площадь, а не на число цветов.

GmagickPixel::getcolorcount(): int

Аргументов нет: пустые скобки вызывают чтение текущего состояния.

Возвращаемое значение: Целое число, смысл зависит от метода и пояснён выше.

Описание возвращаемого значения PHP.net предусматривает GmagickPixelException при ошибке.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Посчитать цвета и построить полосы их частот; Выбрать три акцента, исключив известный фон.

GmagickPixel::getcolorvalueПрочитать один нормализованный канал

PECL gmagick >= Unknown · gmagick

GmagickPixel::getcolorvalue(int $color): float

Прочитать один нормализованный канал. color — целая константа цветового канала Gmagick, например COLOR_RED, а не позиция элемента RGB-массива и не константа CHANNEL_RED другого назначения. Возвращается float в 0…1; PHP.net указывает GmagickPixelException при ошибке. Для #244f65 красный канал равен 36/255. Значение канала opacity имеет собственный смысл; в проверенной сборке непрозрачный цвет дал COLOR_OPACITY=0. Неизвестное значение −999 действительно вызвало GmagickPixelException.

GmagickPixel::getcolorvalue(int $color): float
АргументТип и обязательностьЗначение
colorint; обязательныйОдна из констант цветового канала Gmagick::COLOR_*.

Возвращаемое значение: Дробное число, а не строка.

Описание возвращаемого значения PHP.net предусматривает GmagickPixelException при ошибке.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Изменить один канал, оставив два других; Проверить настройки темы до рисования карточки.

GmagickPixel::setcolorЗаменить описание цвета строкой

PECL gmagick >= Unknown · gmagick

GmagickPixel::setcolor(string $color): GmagickPixel

Заменить описание цвета строкой. color — строка определения цвета. Официальные примеры допустимых форм: имя blue, #0000ff, rgb(0,0,255), cmyk(100,100,100,10) и другие распознаваемые определения. В программах используются явные RGB/hex. Возвращается GmagickPixel; проверенный вызов вернул тот же объект. Смена его цвета не означает автоматической перекраски уже сохранённого PNG. Передавайте объект заново в нужную команду рисования. Интерпретация других цветовых моделей и альфа-строк требует проверки выбранной версии; строка rgba в нашем probe не совпала с ожидаемой CSS-интерпретацией альфа-числа.

GmagickPixel::setcolor(string $color): GmagickPixel
АргументТип и обязательностьЗначение
colorstring; обязательныйЦветовая строка, объект или константа канала согласно конкретной сигнатуре; различие пояснено выше.

Возвращаемое значение: GmagickPixel: объект цвета.

На этой странице PHP.net отдельный список исключений не приведён; это не гарантия отсутствия отказов. Неверный PHP-тип может дать TypeError, неверная строка цвета — GmagickPixelException, а проверенный неполный массив точек — Exception. Ошибки перехватываются в самостоятельных примерах там, где создаются соответствующие данные.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

Два применения: Получить образец цвета из строки и объекта; Выбрать три акцента, исключив известный фон.

GmagickPixel::setcolorvalueИзменить отдельный канал, включая opacity

PECL gmagick >= Unknown · gmagick

GmagickPixel::setcolorvalue(int $color, float $value): GmagickPixel

Изменить отдельный канал, включая opacity. color — константа цветового канала, value — float от 0 до 1. Метод возвращает GmagickPixel и может задавать канал opacity. Значение 0.5 для COLOR_RED означает половину диапазона, а не красный уровень 0.5 из 255; в getColor(true) получилось 128 с округлением. Другие RGB-каналы остаются прежними. В функции темы диапазон проверяется явно до вызова. Для несуществующей константы probe дал GmagickPixelException. RGB8-округление и Q16-значение не следует сравнивать как одно и то же число.

GmagickPixel::setcolorvalue(int $color, float $value): GmagickPixel
АргументТип и обязательностьЗначение
colorint; обязательныйОдна из констант цветового канала Gmagick::COLOR_*.
valuefloat; обязательныйНовое значение канала от 0 до 1.

Возвращаемое значение: GmagickPixel: объект цвета.

На этой странице PHP.net отдельный список исключений не приведён; это не гарантия отсутствия отказов. Неверный PHP-тип может дать TypeError, неверная строка цвета — GmagickPixelException, а проверенный неполный массив точек — Exception. Ошибки перехватываются в самостоятельных примерах там, где создаются соответствующие данные.

Требуется PECL Gmagick. PHP.net указывает нижнюю границу версии как Unknown; конкретная минимальная версия здесь не выдумывается. Результаты уроков привязаны к указанному Q16-окружению.

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

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

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

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

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

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