[font=trebuchet ms]Hello fellas,
For the past few weeks, I’ve been working on a small webapp, and I need it to convert PNGs with alpha transparency into grayscale. I’ve built all the necessary functions to get GIFs, PNGs, and JPGs appear in grayscale, but PNGs with alpha transparency don’t work — the area that was previously semi- or fully-transparent have an opaque color (usually black, but not always). Additionally, the image becomes aliased, and I want it to be antialiased. Can someone point me in the right direction, please? I’ve experimented for 3 days with this thing, and usually 3 days is more than enough time for me to figure something out in PHP.
I’ll post the code upon request (it’s a little long).[/font]
[code=php]
# This function converts palette images
# into truecolor images. This is for
# GIFs and PNGs, mostly.
function imagepalettetotruecolor($img)
{
if (!imageistruecolor($img))
{
$w = imagesx($img);
$h = imagesy($img);
$img1 = imagecreatetruecolor($w,$h);
imagecopy($img1,$img,0,0,0,0,$w,$h);
$img = $img1;
}
return $img;
}
function greyImage($url){
$type = 'jpeg';
$fullPath = explode(".",$url);
$lastIndex = sizeof($fullPath)-1;
$extension = $fullPath[$lastIndex];
if (preg_match("/jpg|jpeg/i", $extension)){
$sourceImage = imagecreatefromjpeg($url);
$type = 'jpeg';
} else if(preg_match("/gif/i", $extension)){
$sourceImage = imagecreatefromgif ($url);
$type = 'gif';
} else if(preg_match("/png/i", $extension)){
$sourceImage = imagecreatefrompng ($url);
$type = 'png';
}
if(!imageistruecolor($sourceImage)){
$sourceImage = imagepalettetotruecolor($sourceImage);
}
$img_width = imageSX($sourceImage);
$img_height = imageSY($sourceImage);
for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x <$img_width; $x++) {
$rgb = imagecolorat($sourceImage, $x, $y);
$red = ($rgb >> 16) & 255;
$green = ($rgb >> 8) & 255;
$blue = $rgb & 255;
$alpha = ($rgb >> 24) & 255;
$gray = round(.299*$red + .587*$green + .114*$blue);
$grayR = $gray << 16; // R: red
$grayG = $gray << 8; // G: green
$grayB = $gray; // B: blue
$grayColor = $grayR | $grayG | $grayB;
$grayColor = $grayR | $grayG | $grayB;
if($type == 'png'){
$grayColor = imagecolorallocatealpha($sourceImage, $gray, $gray, $gray, $alpha);
} else {
$grayColor = imagecolorallocate ($sourceImage, $gray, $gray, $gray);
}
imagesetpixel ($sourceImage, $x, $y, $grayColor);
}
}
$destinationImage = ImageCreateTrueColor($img_width, $img_height);
imagecopy($destinationImage, $sourceImage, 0, 0, 0, 0, $img_width, $img_height);
if($type == 'jpeg'){
$return = imagejpeg($destinationImage);
} else if($type == 'gif'){
$return = imagegif($destinationImage);
} else if($type == 'png'){
$return = imagepng($destinationImage);
}
imagedestroy($destinationImage);
imagedestroy($sourceImage);
return $return;
}
[/code]
[code=php]Code removed... See post #11[/code]
[code=php]Code removed... See post #11[/code]
[font=trebuchet ms]Question–why do you convert the image from truecolor to palette? Doesn’t a PNG24 have to be truecolor in order for it to maintain its alpha channels?[/font][/QUOTE]To be honest I just did that to save on file size and didn't see any side affect when I tested it. You should just be able to comment that line out. Anyway I am going to look at your images now.
[code=php]#imagetruecolortopalette($slate, false, 256);[/code]
[/I] and then manually enter a transparency value it is possible to get the image looking like yours:[code=php]$pixel_color = ImageColorAllocateAlpha($slate, $average, $average, $average, 105/*$alpha*/);[/code]
So now we need to back track to find out why it is not happening automatically.[code=php]<?php
function grayscale($source, $destination = NULL, $bias = array('r'=>50,'g'=>35,'b'=>15))
{
###############################################################################
## ##
## Function: grayscale ##
## Author: "Bokeh" ##
## Website: http://bokehman.com/ ##
## Send mods to: http://bokehman.com/email ##
## Forum thread: https://webdeveloper.com/forum/showthread.php?t=97163 ##
## ##
## Converts true colour and palette images to grayscale ##
## ##
## Works on all file types on which it was tested (PNG8, PNG24, GIF & JPEG) ##
## ##
## grayscale( string source, [string destination, [array bias]]) ##
## ##
## 'source': the path and filename of the source image. ##
## 'destination': path and filename to which the image will be saved. ##
## 'bias': the weight the respect colors exert on the final image. ##
## ##
## If 'destination' is NULL, headers and the grayscale image will be output ##
## to the user agent. Destination image will be output with the same file ##
## type as the source file. ##
## ##
## The combined additive values of 'bias' should be 100. ##
## ##
###############################################################################
# probe the source file and open it if possible
file_exists($source) or die($source.' does not exist');
is_readable($source) or die($source.' is not readable');
$image_details = @getimagesize($source) or die($source.' is not a valid image');
$image = @imagecreatefromstring(
@file_get_contents($source))
or die($source.' could not be opened');
# get source image dimmensions
$w = imagesx($image);
$h = imagesy($image);
# create a slate to draw on
$slate = imagecreate($w, $h);
# build the grayscale image
for ($x = 0; $x < $w; $x++)
{
for ($y = 0; $y < $h; $y++)
{
$colors = imagecolorsforindex($image, ImageColorAt($image,$x,$y));
$average = round(($colors['red']*($bias['r']/100)) +
($colors['green']*($bias['g']/100)) +
($colors['blue']*($bias['b']/100)));
if($average > 255) $average = 255;
elseif($average < 0) $average = 0;
if(($pixel_color = imagecolorexactAlpha($slate, $average, $average, $average, $colors['alpha'])) === (-1))
{
$pixel_color = ImageColorAllocateAlpha($slate, $average, $average, $average, $colors['alpha']);
}
ImageSetPixel($slate, $x, $y, $pixel_color);
}
}
# GIF transparency
if(($image_details['mime'] === 'image/gif') and (false !== ($trans_colors = @imagecolorsforindex($image, imagecolortransparent($image)))))
{
$average = round(($trans_colors['red']*($bias['r']/100)) +
($trans_colors['green']*($bias['g']/100)) +
($trans_colors['blue']*($bias['b']/100)));
imagecolortransparent($slate, imagecolorexactAlpha($slate, $average, $average, $average, $trans_colors['alpha']));
}
# output the image to browser ($destination = NULL)
# or output the image to the path/filename in $destination
if(!$destination) header('Content-Type: '.$image_details['mime']);
preg_match('@image/(.+?)$@', $image_details['mime'], $matches);
$eval = ($destination)
?'@image'.$matches[1].'($slate, $destination)
or die('Directory permission problem');'
:'@image'.$matches[1].'($slate);';
eval($eval);
if(!$destination) exit;
return TRUE;
}
?>[/code]
[font=trebuchet ms]I hope you won’t mind my linking to your site and attributing you credit for assisting with the construction of the webapp, with your permission.[/font][/QUOTE]You're welcome to link to my site.
I wish there were more like it.[/QUOTE]
i have no clue how to work with images in php..[/QUOTE]Well the truth is I had no clue how I would go about it until someone asked the question and I attempted to answer it. I didn't look at any tutirials either (there don't seem to be any). Anyway I started working on my script before Jona posted his but we must have been thinking on similar lines, the for loop for example, but if you look closer Jona is scanning left to right and I am scanning top to bottom. Left to right seems more logical but I did it the other way for no other reason than x comes before y alphabetically.
0.1.9 — BETA 6.17