doubipiao1611 2018-11-08 13:06
浏览 80

无法从PHP中的PNG裁剪/修剪空白

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.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 #MATLAB仿真#车辆换道路径规划
    • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
    • ¥15 数据可视化Python
    • ¥15 要给毕业设计添加扫码登录的功能!!有偿
    • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
    • ¥15 微信公众号自制会员卡没有收款渠道啊
    • ¥100 Jenkins自动化部署—悬赏100元
    • ¥15 关于#python#的问题:求帮写python代码
    • ¥20 MATLAB画图图形出现上下震荡的线条
    • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘