Сохранение прозрачности PNG в GD2 + PHP

При работе с изображениями PNG-24 с альфа-каналом, при изменении размера или после других манипуляций с помощью библиотеки GD2 пропадает прозрачность.

Изображение без сохранения alpha-канала

Изображение без сохранения alpha канала

Изображение с сохранение alpha-канала

Изображение с сохранённым alpha каналом

Для решения этой проблемы к ресурсу(в примере — код на PHP) перед любыми манипуляциями с картинкой, фотографией применяем две функции: imageAlphaBlending и imageSaveAlpha.

Пример

Скрипт(неуниверсальный, рассчитан на изменение размера только изображения PNG).

Вот и всё, оказалось всё просто.

Небольшие проблемы

В процессе использования возникла только одна проблема. Не все png-fix для IE6 фиксили уменьшенные с помощью этого скрипта изображения. На практике привык использовать DD_belatedPNG, но он не помог.  Помог IE PNG Fix 2.0 Alpha 4. Вообще последний выигрывает в тех случаях, когда полно всяких извращений с пнгешками( как то изменения размера средствами html/css, навешивания событий на такие изображения и прочее). Я говорю про извращения, так как для немощного IE 6 с применением фикса это всё сложно. Появляются глюки.  Надо, когда время будет, сравнить все известные мне png фиксилки.

Рубрики: PHP, Web-разработка
Понравилось? Поделись с другими плз












Комментарии ВКонтакте





Комментарии с сайта
  1. Гость:

    Спасибо, очень интересная статья. Удобный способ, и главное без потери качества PNG картинки. Автор РЕСПЕКТ!!!

  2. JokerBaD:

    СПАСИБО!!!!!

  3. Pavel:

    // Говорим браузеру о типе изображения. Тип — PNG
    header(«Content-Type: image/png»);

    Нужны ли эти строчки если после уменьшения размера картинка не выводится в браузер, а просто сохраняется на сервере?

    • admin:

      нет, при сохранении файла на сервере эта строка не нужна
      этот код
      header(«Content-Type: image/png»);
      просто устанавливает дополнительную информацию в заголовке ответа, отсылаемого веб-сервером, чтобы браузер смог понять, что делать с полученным контентом

      • Pavel:

        в результате альфа канал заменяется черным цветом 🙁
        пробовал
        $black = imagecolorallocatealpha($filnal, 0, 0, 0, 127);
        imagecolortransparent($filnal, $black);
        качество теряется…
        подскажите, что сделал не так?

        $output = imagecreatefrompng($filepath); //$filepath — путь к png
        $w_output = 130; //ширина после уменьшения
        $h_input = imagesy($output); // y — исходного $w_input = imagesx($output); // x — исходного
        if ($w_input > $w_output){
        $rait = $w_input / $w_output;
        $x_output = round($w_input / $rait, 2); $y_output = round($h_input / $rait, 2);
        $filnal = imagecreatetruecolor($x_output, $y_output);
        imagealphablending($final, false);
        imagesavealpha($final, true);
        imagecopyresampled($filnal, $output, 0, 0, 0, 0, $x_output, $y_output, $w_input, $h_input);
        $black = imagecolorallocatealpha($filnal, 0, 0, 0, 127);
        imagecolortransparent($filnal, $black);
        imagepng($filnal, ‘thumb.png’);
        }

        • admin:

          Посмотрел код. Стало интересно 🙂 У вас вообще весь прозрачный фон заменялся чёрным цветом?
          А с применением всё стало работать? Но только качество ухудшилось или то же не работало? Насчёт качества, не знаю, при уменьшении изображения оно всегда теряется, но конечно не до безобразия.
          А насчёт приведённого Вами кода, вообще он работающий, если немного подправить. Когда запустил ваш код, у меня из png с прозрачными местами сгенерировался чёрный прямоугольник 🙂
          Немного подправил, заработало, вот исправленный мною код

          $filepath = '1.png';
          $output = imagecreatefrompng($filepath); //$filepath – путь к png
          $w_output = 100; //ширина после уменьшения

          $h_input = imagesy($output); // y – исходного
          $w_input = imagesx($output); // x – исходного

          if ($w_input > $w_output){
          $rait = $w_input / $w_output;
          $x_output = ceil($w_input / $rait);
          $y_output = ceil($h_input / $rait);
          $final = imagecreatetruecolor($x_output, $y_output);
          imagealphablending($final, false);
          imagesavealpha($final, true);

          imagecopyresampled($final, $output, 0, 0, 0, 0, $x_output, $y_output, $w_input, $h_input);

          // $black = imagecolorallocatealpha($final, 0, 0, 0, 127);

          // imagecolortransparent($final, $black);

          imagepng($final, '1_.png');
          }

          Собственно что там изменил
          1. у вас опечатка, где то пишите $filnal, где то $final, наверное всё таки переменная $final
          2. поменял round на ceil — округление в большую сторону
          3. закомментил
          // $black = imagecolorallocatealpha($final, 0, 0, 0, 127);

          // imagecolortransparent($final, $black);

          Может что то ещё поменял. Сравните ваш и мой код. Когда включил отображение ошибок error_reporting(E_ALL), там столько полетело ошибок 🙂
          У меня этот код работает.

  4. Семен:

    Я делаю погодный информер и задачу поставили не сохранить кучу всяких «картинок» а делать наложением с момощью этих функций в PHP , все вроде работает нормально, все картинки видно и первую и вторую и наложились они нормально , но на фоне во все 40 на 40 пикселей черный фон, что делать? (чего только не перепробовал)
    //——————————————————————————
    Вывожу через картинку скриптом.

    //——————————————————————————
    $sun_image = ImageCreateFromPNG(«pic/weather_lblue_big/day.png»);

    $res_image = imagecreatetruecolor(40,40);
    imagealphablending($res_image, true);
    imagesavealpha($res_image, true);
    imagecopyresampled($res_image, $sun_image, 0, 0, 0, 0, 40, 40,40,40);

    $cloud_image = ImageCreateFromPNG(«pic/weather_lblue_big/bcloud.png»);

    imagecopyresampled($res_image, $cloud_image, 0, 0, 0, 0, 40, 40,40,40);

    imagejpeg($res_image);

    ImageDestroy($res_image);
    ImageDestroy($sun_image);
    ImageDestroy($cloud_image);

    • admin:

      здравствуйте, извините, но сейчас нет времени проверить на практике Ваш скрипт,
      думаю надо не imagealphablending($res_image, true);, а imagealphablending($res_image, false);

    • admin:

      ещё вы зачем то под конец используете imagejpeg, а не imagepng
      ещё перед выводом в браузер не указываете тип контента

    • admin:

      я тут поигрался с imagealphablending, с разными параметрами
      короче у меня работает следующий скрипт
      < ?php //—————————————————————————— // Вывожу через картинку скриптом. //—————————————————————————— $sun_image = ImageCreateFromPNG("sun.png"); $res_image = imagecreatetruecolor(60, 60); imagealphablending($res_image, false); imagesavealpha($res_image, true); imagecopyresampled($res_image, $sun_image, 0, 0, 0, 0, 60, 60,100,100); $cloud_image = ImageCreateFromPNG("cloud.png"); imagealphablending($res_image, true); imagecopyresampled($res_image, $cloud_image, 0, 0, 0, 0, 60, 60,100,100); header("Content-Type: image/png;"); imagepng($res_image); ImageDestroy($res_image); ImageDestroy($sun_image); ImageDestroy($cloud_image); ?>

      • admin:

        ну размеры изображения свои подставите, у меня просто были исходные по 100 на 100 пикселей, итоговый на выходе сделал 60 на 60 пикселей

  5. Гость:

    Спасибо большое за статью, очень помогла!

  6. Спасибо за
    imageAlphaBlending($tmp, false);
    imageSaveAlpha($tmp, true);
    Помогло!


Ответить Pavel

*