Forum Moderators: coopster

Message Too Old, No Replies

Converting a 24bit PNG into a JPEG with GD

         

grahama

2:30 am on Dec 2, 2006 (gmt 0)

10+ Year Member



Is there some trick to getting PHP GD to properly convert a 24bit PNG[with alpha] into a JPEG without garbling the image output?

The below WILL output the jpg image, but it appears that the alpha channel from the original png is not being replace by the new background color.

To no avail, I tried:
* Setting imageAlphaBlending and imageSaveAlpha to 'false' and 'true' and '1' and '0'.
* Setting the jpeg quality to 90 and 100.
* Trying imagecopy and imagecopymerge with a background-color image built from imagecreate
* ditching the background image and just using imagefill directly on the png

At this point, I am blindly throwing darts at a wall.

many thanks in advance

example url:
get_image.php?url=24bit.png&type=jpg&color=420000

<?php

isset($_GET["type"])?$type=htmlentities($_GET["type"] ):$type="jpg";
isset($_GET["url"])?$url=realpath($_GET["url"]): $url="blank.png";
isset($_GET["color"])?$color= ($_GET["color"]):$color="#ffffff";

$path_parts= pathinfo($url);
$file= explode(".",$path_parts['basename']);
$image_name=$file[0];
$image_output = '$image_name'.'.'.$type;
list($sx, $sy)=getimagesize($url);

//colored background image
$bg_image=imagecreate($sx,$sy);
list($R,$G,$B)= (HEX2RGB($color));
$mycolor= ImageColorAllocate($bg_image, $R,$G,$B);
ImageFill($bg_image, 0, 0, $mycolor);

//the 24bit png with an alpha channel
$image = imagecreatefrompng($url);
imageAlphaBlending($image,true);
imageSaveAlpha($image, true);

//Neither one of these works outputs properly
//imagecopy($bg_image, $image, 0, 0, 0, 0, $sx, $sy);
imagecopymerge($bg_image,$image, 0, 0, 0, 0, $sx,$sy, 100);

header('Content-type:image/jpeg');
imagejpeg($bg_image,'',95);
imagedestroy($bg_image);
imagedestroy($image);

function HEX2RGB($color){
$color_array = array();
$hex_color = strtoupper($color);
for($i = 0; $i < 6; $i++){
$hex = substr($hex_color,$i,1);
switch($hex){
case "A": $num = 10; break;
case "B": $num = 11; break;
case "C": $num = 12; break;
case "D": $num = 13; break;
case "E": $num = 14; break;
case "F": $num = 15; break;
default: $num = $hex; break;
}
array_push($color_array,$num);
}
$R = (($color_array[0] * 16) + $color_array[1]);
$G = (($color_array[2] * 16) + $color_array[3]);
$B = (($color_array[4] * 16) + $color_array[5]);
return array($R,$G,$B);
unset($color_array,$hex,$R,$G,$B);
}

?>

DeathRay2K

3:10 am on Dec 4, 2006 (gmt 0)

10+ Year Member



You're really making this unnecessarily complicated.

Anyways, your problem is that you're using imagecreate when you should be using imagecreatetrucolor, and imagealphablending should be false.

With the changes, and a bit of cleaning, you end up with this:

<?php

$type = isset($_GET['type'])? htmlentities($_GET['type']) : 'jpg';
$url = isset($_GET['url'])? realpath($_GET['url']) : 'blank.png';
$color = isset($_GET['color'])? $_GET['color']: 'ffffff';

$file = explode('.', basename($url));
$image_name = $file[0];
$image_output = "{$image_name}.{$type}";
list($sx, $sy) = getimagesize($url);

//colored background image
$bg_image = imagecreatetruecolor($sx,$sy);
list($R, $G, $B)= (hex2rgb($color));
$mycolor = ImageColorAllocate($bg_image, $R,$G,$B);
imagefill($bg_image, 0, 0, $mycolor);

//the 24bit png with an alpha channel
$image = imagecreatefrompng($url);
imagealphablending($image, false);
imagesavealpha($image, true);

imagecopy($bg_image, $image, 0, 0, 0, 0, $sx, $sy);

header('Content-type:image/jpeg');
imagejpeg($bg_image,'',95);
imagedestroy($bg_image);
imagedestroy($image);

function &hex2rgb($hex)
{
if (0 === strpos($hex, '#')) {
$hex = substr($hex, 1);
} else if (0 === strpos($hex, '&H')) {
$hex = substr($hex, 2);
}

$cutpoint = ceil(strlen($hex) / 2)-1;
$rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3);

$rgb[0] = (isset($rgb[0])? hexdec($rgb[0]) : 0);
$rgb[1] = (isset($rgb[1])? hexdec($rgb[1]) : 0);
$rgb[2] = (isset($rgb[2])? hexdec($rgb[2]) : 0);

return $rgb;
}
?>