Как повторно использовать цветовые палитры в нескольких канвах/изображениях PHP GD?

Вопрос или проблема

Как я могу рисовать и ссылаться на один и тот же набор цветов на нескольких холстах GD?

Я новичок в использовании PHP-GD для изображений, я делал только пару очень простых вещей с ним.

Я создаю генератор карт, который будет иметь 3+ масштаба в виде холстов GD. Каждый масштаб представляет собой увеличение предыдущего масштаба и добавление более детализированной информации. Первый масштаб – это изображение 20×20 с цветами земли и воды. Второй масштаб – 60×60 пикселей (каждый пиксель превращается в сетку 3×3 пикселей) и выполняет интерполяцию, чтобы округлить пиксели первого масштаба.

Все работает отлично, за исключением того, что PHP, похоже, не предоставляет способа повторно использовать и ссылаться на цвета в нескольких изображениях. Моя генерация карты полностью основана на цвете пикселей, считанных с холста изображения. Я хочу ссылаться на одни и те же цвета во всех 3 масштабах моей карты, но меня заставляют создавать эти глупые «цветовые ссылки», возвращаемые imagecolorallocate(). Изображения в истинных цветах не имеют палитр, вы просто используете любой цвет, который хотите. Почему PHP не позволяет использовать правильные изображения в истинных цветах без палитр?

Мне нужно иметь возможность делать следующее:

  • Проверять цвета пикселей во всех 3 моих холстах GD, чтобы увидеть, соответствуют ли они определенному списку цветов (земля, вода и т. д.)
  • Рисовать пиксели на любом из 3 холстов GD, используя тот же список цветов (земля, вода и т. д.)

Я ищу способ избежать повторения переменных для каждого цвета, как это у меня сейчас:

$Colour_Water_1 = imagecolorallocate($Scale_1, 68, 97, 147);
$Colour_Land_1  = imagecolorallocate($Scale_1, 99, 67, 33);

$Colour_Water_2 = imagecolorallocate($Scale_2, 68, 97, 147);
$Colour_Land_2  = imagecolorallocate($Scale_2, 99, 67, 33);

Мне было бы достаточно одной переменной $Variable для каждого отдельного цвета на каждом масштабе, но не разные переменные для каждого цвета на каждом масштабе! Какой подход кто-нибудь предлагает мне использовать?

Идеально было бы иметь один глобальный массив цветов, доступный каждому холсту GD:

$Map_Colours = array(
   "Water" => array(68, 97, 147),
   "Land"  => array(99, 67, 33),
);

Документация для imagecolorallocate() даже не указывает, что возвращается функцией. Что такое “цветовая ссылка”, которая возвращается?

Я рассматривал возможность создания одного гигантского холста, на который будут нанесены 3 меньших изображения в разных местах гигантского холста, что позволяет избежать наличия нескольких палитр, но это не идеальный и довольно глупый подход, который станет все более неэффективным по мере добавления дальнейших увеличенных масштабов в мой генератор карт.

Мне не важно, являются ли изображения карты истинного цвета или основаны на палитре. Я изначально создал изображения на основе палитры, но как только я понял, что используемые палитры не совпадают между разными холстами GD, и я не могу ссылаться на одни и те же цвета в каждом холсте, эта идея рухнула. Затем я переключился на изображения истинного цвета, потому что думал, что они «просто заработают», из-за отсутствия палитры внутри, но PHP GD все равно требует использования imagecolorallocate() для изображений истинного цвета!

Я нашел функцию imagepalettecopy(), но у нее та же проблема: каждый холст требует своих собственных отдельных цветовых ссылок.

Я также нашел этот комментарий на php.net, который утверждал, что вы можете ссылаться на любой цвет в изображении истинного цвета, как если бы он уже был выделен, но код, который они предоставили, не был мне очень ясен:

jessiedeer at hotmail dot com - 11 years ago

Нет необходимости выделять цвета с imagecreatetruecolor. Все [256 x 256 x 256 x 128] истинные цвета уже выделены, и вы можете использовать индексы цветов напрямую.

Примеры:
Синий => индекс цвета 255.
Белый => индекс цвета 16777215 (= 255*256² + 255*256+255).
Полная прозрачность => индекс цвета 2130706432 (= 127*256^3).

Это похоже на то, как QBASIC ссылался на 6-битные цвета VGA (значения RGB от 0 до 63):

(Красный) + (Зеленый * 256) + (Синий * 65536)

Также, почему они указывают альфа как 128 (только 7 бит вместо 8 бит)?

Если этот метод действительно работает с использованием правильной формулы, он также должен быть применим при проверке пикселя на холсте, чтобы увидеть, соответствует ли он определенному цвету (земля, вода и т. д.).

Ответ или решение

Как повторно использовать цветовые палитры на нескольких канвасах (изображениях) PHP GD

Создание карт является интересным, но иногда сложным процессом, особенно когда необходимо работать с несколькими масштабами изображения. В данном случае можно использовать подход, который позволит вам избежать дублирования цветовых значений для каждого масштаба, сохраняя при этом простоту и читаемость вашего кода.

Проблема с imagecolorallocate()

Как вы правильно заметили, функция imagecolorallocate() возвращает уникальный идентификатор цвета для каждого изображения, что делает невозможным повторное использование одного и того же цвета на разных канвасах без дублирования кода. Чтобы устранить это неудобство, вы можете создать глобальный массив для хранения цветовых значений, а затем использовать эти значения для создания цветовых идентификаторов на каждом канвасе.

Пример решения с глобальным массивом цветов

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

// Глобальный массив цветов
$Map_Colours = array(
    "Water" => array(68, 97, 147),
    "Land"  => array(99, 67, 33),
);

// Функция для выделения цвета на конкретном канвасе
function allocateColors($canvas, $colorArray) {
    $allocatedColors = array();
    foreach ($colorArray as $key => $rgb) {
        $allocatedColors[$key] = imagecolorallocate($canvas, $rgb[0], $rgb[1], $rgb[2]);
    }
    return $allocatedColors;
}

// Создание канвасов
$Scale_1 = imagecreatetruecolor(20, 20);
$Scale_2 = imagecreatetruecolor(60, 60);

// Выделение цветов для каждого канваса
$Colors_Scale_1 = allocateColors($Scale_1, $Map_Colours);
$Colors_Scale_2 = allocateColors($Scale_2, $Map_Colours);

Использование идентификаторов цветов

Теперь, зная идентификаторы цветов, вы можете легко рисовать на любом из канвасов и проверять цвет пикселей:

// Пример рисования
imagesetpixel($Scale_1, 5, 5, $Colors_Scale_1['Water']);
imagesetpixel($Scale_2, 10, 10, $Colors_Scale_2['Land']);

// Проверка цвета пикселя
$colorAtPixel = imagecolorat($Scale_1, 5, 5);
if ($colorAtPixel == $Colors_Scale_1['Water']) {
    // Цвет совпадает с цветом воды
}

Оптимизация работы с альфа-каналом

В PHP GD альфа-канал имеет лишь 7 бит, что позволяет передавать значения от 0 до 127, где 0 — это полностью непрозрачный цвет, а 127 — полностью прозрачный. Чтобы работать с прозрачностью, вы можете использовать imagealphablending() и imagesavealpha():

imagealphablending($Scale_2, false);
imagesavealpha($Scale_2, true);

Итоги

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

При разработке карт с использованием PHP GD важно помнить, что использование true color изображений значительно упрощает работу с цветами, так как вы можете использовать любую RGB комбинацию, а не только цветовую палитру. Это также позволяет эффективно управлять прозрачностью ваших изображений, если необходимо.

Задавайте вопросы, если вам потребуется дальнейшее разъяснение по какой-либо из тем или по коду!

Оцените материал
Добавить комментарий

Капча загружается...