PHP imagesharpen()
The following example codes are
for 16 × 16 pixel images (favicons) mainly.
It's not that difficult to adopt this code for larger images
(basically replace
0x10 with $height/$width
in the for loops, see below).
However, it's not a good idea
to sharpen large images using these functions
because they are horrible slow
(about 8 seconds for a 800 × 600 pixel image).
favicon_sharpen_fast() takes 0.0039 seconds
for a 16 × 16 pixel image
(on my machine, of course).
It uses only two surrounding pixels for the calculations.
favicon_sharpen_precise() takes 0.0043 seconds.
That's 15% slower but looks a little bit better.
It uses all four surrounding pixels for the calculations.
These functions are based on code by Alex R. Austin
found in the user notes at
php.net
but are faster (even imagesharpen_precise() is faster
than the code at php.net,
e.g. 8 instead of 9 seconds for a 800 × 600 pixel image).
Example script
$thumbnail = imagecreatefromjpeg("thumbnail.jpg");
$favicon = imagecreatetruecolor(16, 16);
imagecopyresampled($favicon, $thumbnail,
0, 0, 0, 0,
16, 16, imagesx($thumbnail), imagesy($thumbnail));
favicon_sharpen_precise($favicon);
header("Content-type: image/png");
imagepng($favicon);
imagedestroy($favicon);
imagedestroy($thumbnail);
Fast sharpen a 16 × 16 pixel image
function favicon_sharpen_fast($favicon)
{
$rs = array(); $gs = array(); $bs = array();
for ($y = 0; $y < 0x10; ++$y)
{
for ($x = 0; $x < 0x10; ++$x)
{
$rgb = imagecolorat($favicon, $x, $y);
$rs[$y][$x] = $rgb >> 0x10;
$gs[$y][$x] = $rgb >> 0x08 & 0xFF;
$bs[$y][$x] = $rgb & 0xFF;
}
}
for ($y = 1; $y < 0x10; ++$y)
{
$rd = $rs[$y][0];
$gd = $gs[$y][0];
$bd = $bs[$y][0];
$yd = $y - 1;
for ($x = 1; $x < 0x10; ++$x)
{
$r = -($rs[$yd][$x] + $rd) / 2;
$g = -($gs[$yd][$x] + $gd) / 2;
$b = -($bs[$yd][$x] + $bd) / 2;
$r += 2 * $rd = $rs[$y][$x];
$g += 2 * $gd = $gs[$y][$x];
$b += 2 * $bd = $bs[$y][$x];
if ($r < 0) $r = 0;
elseif ($r > 255) $r = 255;
if ($g < 0) $g = 0;
elseif ($g > 255) $g = 255;
if ($b < 0) $b = 0;
elseif ($b > 255) $b = 255;
imagesetpixel($favicon, $x, $y,
$r << 0x10 | $g << 0x08 | $b);
}
}
}
Precise sharpen a 16 × 16 pixel image
function favicon_sharpen_precise($favicon)
{
$rs = array(); $gs = array(); $bs = array();
for ($y = 0; $y < 0x10; ++$y)
{
for ($x = 0; $x < 0x10; ++$x)
{
$rgb = imagecolorat($favicon, $x, $y);
$rs[$y][$x] = $rgb >> 0x10;
$gs[$y][$x] = $rgb >> 0x08 & 0xFF;
$bs[$y][$x] = $rgb & 0xFF;
}
}
for ($y = 1; $y < 0x0F; ++$y)
{
$rd = $rs[$y][0];
$gd = $gs[$y][0];
$bd = $bs[$y][0];
$yd = $y - 1;
$yi = $y + 1;
for ($x = 1; $x < 0x0F; ++$x)
{
$r = -($rs[$yd][$x] + $rs[$yi][$x] +
$rd + $rs[$y][$x + 1]) / 4;
$g = -($gs[$yd][$x] + $gs[$yi][$x] +
$gd + $gs[$y][$x + 1]) / 4;
$b = -($bs[$yd][$x] + $bs[$yi][$x] +
$bd + $bs[$y][$x + 1]) / 4;
$r += 2 * $rd = $rs[$y][$x];
$g += 2 * $gd = $gs[$y][$x];
$b += 2 * $bd = $bs[$y][$x];
if ($r < 0) $r = 0;
elseif ($r > 255) $r = 255;
if ($g < 0) $g = 0;
elseif ($g > 255) $g = 255;
if ($b < 0) $b = 0;
elseif ($b > 255) $b = 255;
imagesetpixel($favicon, $x, $y,
$r << 0x10 | $g << 0x08 | $b);
}
}
}
Precise sharpen any image
function imagesharpen_precise($image)
{
$height = imagesy($image);
$width = imagesx($image);
$rs = array(); $gs = array(); $bs = array();
for ($y = 0; $y < $height; ++$y)
{
for ($x = 0; $x < $width; ++$x)
{
$rgb = imagecolorat($image, $x, $y);
$rs[$y][$x] = $rgb >> 0x10;
$gs[$y][$x] = $rgb >> 0x08 & 0xFF;
$bs[$y][$x] = $rgb & 0xFF;
}
}
$height--; $width--;
for ($y = 1; $y < $height; ++$y)
{
$rd = $rs[$y][0];
$gd = $gs[$y][0];
$bd = $bs[$y][0];
$yd = $y - 1;
$yi = $y + 1;
for ($x = 1; $x < $width; ++$x)
{
$r = -($rs[$yd][$x] + $rs[$yi][$x] +
$rd + $rs[$y][$x + 1]) / 4;
$g = -($gs[$yd][$x] + $gs[$yi][$x] +
$gd + $gs[$y][$x + 1]) / 4;
$b = -($bs[$yd][$x] + $bs[$yi][$x] +
$bd + $bs[$y][$x + 1]) / 4;
$r += 2 * $rd = $rs[$y][$x];
$g += 2 * $gd = $gs[$y][$x];
$b += 2 * $bd = $bs[$y][$x];
if ($r < 0) $r = 0;
elseif ($r > 255) $r = 255;
if ($g < 0) $g = 0;
elseif ($g > 255) $g = 255;
if ($b < 0) $b = 0;
elseif ($b > 255) $b = 255;
imagesetpixel($image, $x, $y,
$r << 0x10 | $g << 0x08 | $b);
}
}
}