PHP GD2: как сохранить прозрачность альфа-канала и правильную гамму - PullRequest
5 голосов
/ 22 июля 2010

Я был заинтригован этим обсуждением масштабирования изображения и впоследствии обнаружил, что код PHP, который я использую для создания миниатюр из загруженных изображений, страдает той же проблемой. Я решил попробовать исправление PHP, размещенное в нижней части (преобразование гаммы от 2.2 до 1.0, изменение размера изображения, преобразование гаммы обратно с 1.0 до 2.2). Это работает для решения проблемы, отмеченной в статье, однако эта модификация кода имеет неприятный побочный эффект - выбивает прозрачность альфа-канала PNG.

Вот код, который у меня есть с гамма-коррекцией.

<?php
$image = imagecreatefrompng($source_file);
$resized_image = imagecreatetruecolor($new_width, $new_height);
imagealphablending($resized_image, false);
imagesavealpha($resized_image, true);
imagegammacorrect($image, 2.2, 1.0);
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height);
imagegammacorrect($resized_image, 1.0, 2.2);
imagepng($resized_image, $dest_file);
?>

Кто-нибудь знает, как изменить размер изображения, используя прием гамма-коррекции, сохраняя прозрачность альфа-канала исходного изображения?

Редактировать

примеры изображений:

  1. оригинальный файл - PNG с прозрачностью альфа-канала
  2. измененный размер файла с обоими вызовами функции imagegammacorrect () закомментирован
  3. измененный размер файла с обоими вызовами функции imagegammacorrect () на месте

Вы можете видеть, что прозрачность в порядке, пока вы не попытаетесь исправить гамму. (Самый простой способ увидеть, как работает прозрачность, - это проверить тег абзаца, обернутый вокруг изображений, и добавить фон: черный; к его атрибуту стиля через FireBug или аналогичный.)

исходное изображение http://ender.hosting.emarketsouth.com/images/test-image.png без гамма-коррекции http://ender.hosting.emarketsouth.com/images/test-image-resized-no-gamma.png гамма-коррекция - нет прозрачности http://ender.hosting.emarketsouth.com/images/test-image-resized.png

Ответы [ 2 ]

2 голосов
/ 23 июля 2010

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

Я предполагаю, что функция imagegammacorrect () содержит ошибку.Возможно, гамма относится только к RGB, и GD пытается выполнить те же вычисления для альфа-канала?Теория цвета - не моя сильная сторона.

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

<?php
// Load image
$image = imagecreatefrompng('test-image.png');

// Create destination
$resized_image = imagecreatetruecolor(100, 100);
imagealphablending($resized_image, false); // Overwrite alpha
imagesavealpha($resized_image, true);

// Create a separate alpha channel
$alpha_image = imagecreatetruecolor(200, 200);
imagealphablending($alpha_image, false); // Overwrite alpha
imagesavealpha($alpha_image, true);

for ($x = 0; $x < 200; $x++) {
    for ($y = 0; $y < 200; $y++) {
        $alpha = (imagecolorat($image, $x, $y) >> 24) & 0xFF;
        $color = imagecolorallocatealpha($alpha_image, 0, 0, 0, $alpha);
        imagesetpixel($alpha_image, $x, $y, $color);
    }
}

// Resize image to destination, using gamma correction
imagegammacorrect($image, 2.2, 1.0);
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, 100, 100, 200, 200);
imagegammacorrect($resized_image, 1.0, 2.2);

// Resize alpha channel
$alpha_resized_image = imagecreatetruecolor(200, 200);
imagealphablending($alpha_resized_image, false);
imagesavealpha($alpha_resized_image, true);

imagecopyresampled($alpha_resized_image, $alpha_image, 0, 0, 0, 0, 100, 100, 200, 200);

// Copy alpha channel back to resized image
for ($x = 0; $x < 100; $x++) {
    for ($y = 0; $y < 100; $y++) {
        $alpha = (imagecolorat($alpha_resized_image, $x, $y) >> 24) & 0xFF;
        $rgb = imagecolorat($resized_image, $x, $y);
        $r = ($rgb >> 16 ) & 0xFF;
        $g = ($rgb >> 8 ) & 0xFF;
        $b = $rgb & 0xFF;
        $color = imagecolorallocatealpha($resized_image, $r, $g, $b, $alpha);
        imagesetpixel($resized_image, $x, $y, $color);
    }
}

imagepng($resized_image, 'test-image-scaled.png');
?>

Замените жестко закодированные значения переменными, конечно ... И вот результат, который я получаю, используя ваше изображение и мой код:

Изменение размера изображенияhttp://www.jejik.com/sander/test-image-scaled.png

0 голосов
/ 22 июля 2010

Проблема с imagecopyresampled () и прозрачностью. Посмотрите этот комментарий на php.net для возможного решения.

...