PHP & GD - прозрачный фон, залитый близким цветом - PullRequest
6 голосов
/ 03 июня 2011

Я знаю, что проблемы PHP + GD Transparency были забиты до смерти на этом и многих других сайтах, но я выполнил все рекомендации и не могу решить свою проблему.

Сначала объяснение:

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

Вот два изображения:

check mark

blue arrow

Теперь к моему коду:

Я использую библиотеку / API, которую я создал, чтобы избавиться от крошечной боли при редактировании изображений с помощью PHP + GD. Это все еще в зачаточном состоянии, но соответствующие файлы:

Базовый класс
Главный загрузчик
(плохо названный) Класс комбината

Я запускаю код, используя следующий скрипт:

<?php
    require_once('Image.php');

    header("Content-Type: image/png");

    $img = new Image();
    $over = new Image();

    $img->source = "arrow.png";
    $over->source = "chk-done_24.png";

    $img->Combine->Overlay($over, 20, 20, 0, 0, $over->width, $over->height);
    $img->output();
    $img->clean();
    unset($img);
?>

Я ожидаю, что результат будет примерно таким:

Combined images

Но вместо этого я получаю это:

Square bottom

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

В объединенном классе I, связанном выше, я также попробовал imagecopy , imagecopyresampled и vanilla imagecopymerge , оба с похожими результатами.

Я в полной растерянности.

Edit:

Для ясности, у меня такой вопрос: какая часть моего кода неверна? Почему он заполняет прозрачную область цветом (вместо черного или белого) и как я могу это исправить, при этом сохраняя возможность объединения изображений с прозрачностью?

Обновление:

Обратите внимание, что при создании нового объекта Image он вызывает newImage, который содержит следующий код:

$this->handle = imagecreatetruecolor($this->width, $this->height);
imagealphablending($this->handle, false);
imagesavealpha($this->handle, true);

Я чувствую, что это может быть легко пропустить.

1 Ответ

2 голосов
/ 06 июня 2011

Обратите внимание, что не имеет значения, что вы создаете дескриптор в newImage и вызываете imagealphablending и imagesavealpha для него, потому что loadImage выбрасывает этот дескриптор.

Причина в том, что это«заполнение» прозрачной области синим цветом означает, что она вообще не заполняет прозрачную область.Это просто полное удаление альфа-канала, и синий цвет - это то, что хранится в тех пикселях с альфа-нулем.Обратите внимание, что это может быть трудно увидеть в графической программе, так как эта программа сама может заменить полностью прозрачные пиксели черным или белым.

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

            private function loadImage()
            {
                    $img = null;
                    switch( $this->type )
                    {
                            case 1:
                                            $img = imagecreatefromgif($this->source);
                                            break;
                            case 2:
                                            $img = imagecreatefromjpeg($this->source);
                                            break;
                            case 3:
                                            $img = imagecreatefrompng($this->source);
                                            break;
                            default:
                                            break;
                    }
                    if (!$img) return false;
                    $this->handle = imagecreatetruecolor($this->width, $this->height);
                    imagealphablending($this->handle, false);
                    imagesavealpha($this->handle, true);
                    imagecopyresampled($this->handle, $img, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
                    return true;
            }

(Лично я предпочитаю ImageMagick, а не GD).

...