I have been looking at (and trying) different ways to crop or trim whitespace from a PNG image using PHP 5.6:
Crop whitespace from image in PHP
https://gist.github.com/ericpedia/3583170
http://php.net/manual/en/function.imagecropauto.php
https://deano.me/2015/01/trim-an-image-using-php-gd/
I've also read about Imagick, but the download contains a lot of source files and I'm worried it could be cumbersome to install and get running locally and on my server. In any case, I don't want a heavy library like this that does 100X more than what I need -- I just want to trim whitespace, that's it.
Here's what I have tried:
function CropPNG($img){
//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;
//top
for(; $b_top < imagesy($img); ++$b_top) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
break 2; //out of the 'top' loop
}
}
}
//bottom
for(; $b_btm < imagesy($img); ++$b_btm) {
for($x = 0; $x < imagesx($img); ++$x) {
if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0xFFFFFF) {
break 2; //out of the 'bottom' loop
}
}
}
//left
for(; $b_lft < imagesx($img); ++$b_lft) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
break 2; //out of the 'left' loop
}
}
}
//right
for(; $b_rt < imagesx($img); ++$b_rt) {
for($y = 0; $y < imagesy($img); ++$y) {
if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0xFFFFFF) {
break 2; //out of the 'right' loop
}
}
}
$newimg = imagecreatetruecolor(imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm));
imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));
imagepng($newimg);
return $newimg;
}
function imagetrim($im, $bgcol, $pad=null){
// Calculate padding for each side.
if (isset($pad)){
$pada = explode(' ', $pad);
if (isset($pada[3])){
$p = array((int) $pada[0], (int) $pada[1], (int) $pada[2], (int) $pada[3]);
}else if (isset($pada[2])){
$p = array((int) $pada[0], (int) $pada[1], (int) $pada[2], (int) $pada[1]);
}else if (isset($pada[1])){
$p = array((int) $pada[0], (int) $pada[1], (int) $pada[0], (int) $pada[1]);
}else{
$p = array_fill(0, 4, (int) $pada[0]);
}
}else{
$p = array_fill(0, 4, 0);
}
// Get the width and height of the image.
$imw = imagesx($im);
$imh = imagesy($im);
// Set the X variables.
$xmin = $imw;
$xmax = 0;
// find the endges.
for ($iy=0; $iy<$imh; $iy++) {
$first = true;
for ($ix=0; $ix<$imw; $ix++) {
$ndx = imagecolorat($im, $ix, $iy);
if ($ndx != $bgcol) {
if ($xmin > $ix) { $xmin = $ix; }
if ($xmax < $ix) { $xmax = $ix; }
if (!isset($ymin)) { $ymin = $iy; }
$ymax = $iy;
if ($first) { $ix = $xmax; $first = false; }
}
}
}
// The new width and height of the image. (not including padding)
$imw = 1+$xmax-$xmin; // Image width in pixels
$imh = 1+$ymax-$ymin; // Image height in pixels
// Make another image to place the trimmed version in.
$im2 = imagecreatetruecolor($imw+$p[1]+$p[3], $imh+$p[0]+$p[2]);
// Make the background of the new image the same as the background of the old one.
$bgcol2 = imagecolorallocate($im2, ($bgcol >> 16) & 0xFF, ($bgcol >> 8) & 0xFF, $bgcol & 0xFF);
imagefill($im2, 0, 0, $bgcol2);
// Copy it over to the new image.
imagecopy($im2, $im, $p[3], $p[0], $xmin, $ymin, $imw, $imh);
// To finish up, return the new image.
return $im2;
}
function ConvertBase64ImageDataToPNG($imgData, $path){
$image_parts = explode(";base64,", $imgData);
$image_type_aux = explode("image/", $image_parts[0]);
$image_type = $image_type_aux[1];
$img = base64_decode($image_parts[1]);
//$img = CropPNG($img);
//$img = imagecropauto($img, IMG_CROP_DEFAULT);
//$img = imagetrim($img, imagecolorallocate($img, 0xFF, 0xFF, 0xFF), 1);
file_put_contents($path, $img);
}
Notice my final function ConvertBase64ImageDataToPNG()
- that works perfectly, it just doesn't crop/trim. The 3 commented-out lines are what I have tried for cropping, and none work. I get a PNG file written to disk, but it's corrupt and won't display. In the case of CropPNG()
which I got from here, I think my last 2 lines are wrong. I modified because it said to use header()
which is only needed if streaming the png to the browser I believe, which I'm not--I just want to write it to disk.
I don't need anything fancy, exotic, or flexible - I just want a simple method to crop out whitespace from PNG signature files (handwriting) that will be uploaded into my PHP webapp. Many times these PNG signature files contain a lot of empty space around the signature which I need to trim off.
Thanks in advance for any help.