29

PHPで画像を囲む空白を削除することは可能ですか?

注: 明確にするために、Photoshop のトリム機能のようなものを意味します。

ありがとう。

4

7 に答える 7

57

画像の興味深い部分を囲むすべての空白をトリミングするには、最初に「空白」が停止する場所を見つけ、次にそれらの境界線の内側にあるすべてをコピーします。

//load the image
$img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg");

//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
    }
  }
}

//copy the contents, excluding the border
$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));

//finally, output the image
header("Content-Type: image/jpeg");
imagejpeg($newimg);

私の古い例では、コメントを明確にするために、画像のすべての面で同じ「境界線」を想定しています:)

//load the image
$img = imagecreatefromjpeg("img.jpg");

//find the size of the border.
$border = 0;
while(imagecolorat($img, $border, $border) == 0xFFFFFF) {
  $border++;
}

//copy the contents, excluding the border
//This code assumes that the border is the same size on all sides of the image.
$newimg = imagecreatetruecolor(imagesx($img)-($border*2), imagesy($img)-($border*2));
imagecopy($newimg, $img, 0, 0, $border, $border, imagesx($newimg), imagesy($newimg));

//finally, if you want, overwrite the original image
imagejpeg($newimg, "img.jpg");
于 2009-11-03T19:51:14.043 に答える
13

Gnud のスクリプトは、imagesx と imagesy を重複して呼び出します。また、角が重なっている場合でも、すべての側面のすべてのピクセルを繰り返します。この改善されたバージョンでは、冗長な関数呼び出しが排除され、すべてのピクセルが 1 回だけチェックされるため、速度が大幅に向上します。すべてのピクセルがトリミングされている場合、関数は 2 に等しいステータス ($result['#']) を返します。

example();
function example(){
    $img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg");

    // find the trimmed image border
    $box = imageTrimBox($img);

    // copy cropped portion
    $img2 = imagecreate($box['w'], $box['h']);
    imagecopy($img2, $img, 0, 0, $box['l'], $box['t'], $box['w'], $box['h']);

    // output cropped image to the browser
    header('Content-Type: image/png');
    imagepng($img2);

    imagedestroy($img);
    imagedestroy($img2);
}



function imageTrimBox($img, $hex=null){
if (!ctype_xdigit($hex)) $hex = imagecolorat($img, 0,0);
$b_top = $b_lft = 0;
$b_rt = $w1 = $w2 = imagesx($img);
$b_btm = $h1 = $h2 = imagesy($img);

do {
    //top
    for(; $b_top < $h1; ++$b_top) {
        for($x = 0; $x < $w1; ++$x) {
            if(imagecolorat($img, $x, $b_top) != $hex) {
                break 2;
            }
        }
    }

    // stop if all pixels are trimmed
    if ($b_top == $b_btm) {
        $b_top = 0;
        $code = 2;
        break 1;
    }

    // bottom
    for(; $b_btm >= 0; --$b_btm) {
        for($x = 0; $x < $w1; ++$x) {
            if(imagecolorat($img, $x, $b_btm-1) != $hex) {
                break 2;
            }
        }
    }

    // left
    for(; $b_lft < $w1; ++$b_lft) {
        for($y = $b_top; $y <= $b_btm; ++$y) {
            if(imagecolorat($img, $b_lft, $y) != $hex) {
                break 2;
            }
        }
    }

    // right
    for(; $b_rt >= 0; --$b_rt) {
        for($y = $b_top; $y <= $b_btm; ++$y) {
            if(imagecolorat($img, $b_rt-1, $y) != $hex) {
                break 2;
            }
        }

    }

    $w2 = $b_rt - $b_lft;
    $h2 = $b_btm - $b_top;
    $code = ($w2 < $w1 || $h2 < $h1) ? 1 : 0;
} while (0);

// result codes:
// 0 = Trim Zero Pixels
// 1 = Trim Some Pixels
// 2 = Trim All Pixels
return array(
    '#'     => $code,   // result code
    'l'     => $b_lft,  // left
    't'     => $b_top,  // top
    'r'     => $b_rt,   // right
    'b'     => $b_btm,  // bottom
    'w'     => $w2,     // new width
    'h'     => $h2,     // new height
    'w1'    => $w1,     // original width
    'h1'    => $h1,     // original height
);
}
于 2012-08-23T13:11:34.403 に答える
9

これはかなり古いことは知っていますが、ImageMagick が有効になっている場合は、このメソッドを使用できます

画像のトリミング

于 2010-08-26T22:20:13.043 に答える
2

これはかなり古いことだと思いますが、GD を介して画像をトリミングする方法は少し異なります。一度に片側だけを行うのではなく、4 つすべてを行います。いくつかの点で、CPU に関しては高速で安価です。ただし、上下左右の辺を見つけた瞬間に FOR ループを停止すると、これよりも高速になります。

まず、次のとおりです。

#
#   Do all four sides at once
#
        echo "Finding the top-left-bottom-right edges of the image...please wait.\n";
        $top = 99999;
        $bot = -99999;
        $left = 99999;
        $right = -99999;
        for( $x=$offset; $x<($w-$offset); $x++ ){
            for( $y=$offset; $y<($h-$offset); $y++ ){
                $rgb = imagecolorat( $gd, $x, $y );
                if( $color != $rgb ){
                    $left = ($x < $left) ? $x : $left;
                    $right = ($x > $right) ? $x : $right;
                    $top = ($y < $top) ? $y : $top;
                    $bot = ($y > $bot) ? $y : $bot;
                    }
                }
            }

そして、次のとおりです。

#
#   Top
#
            echo "Finding the top of the image\n";
            $top = null;
            for( $y=$offset; $y<($h-$offset); $y++ ){
                for( $x=$offset; $x<($w-$offset); $x++ ){
                    $rgb = imagecolorat( $gd, $x, $y );
                    if( $color != $rgb ){ $top = $y; break; }
                    }

                if( !is_null($top) ){ break; }
                }
#
#   Bottom
#
            echo "Finding the bottom of the image\n";
            $bot = null;
            for( $y=($h-$offset); $y>$offset; $y-- ){
                for( $x=$offset; $x<($w-$offset); $x++ ){
                    $rgb = imagecolorat( $gd, $x, $y );
                    if( $color != $rgb ){ $bot = $y; break; }
                    }

                if( !is_null($bot) ){ break; }
                }
#
#   Left
#
            echo "Finding the left of the image\n";
            $left = null;
            for( $x=$offset; $x<($w-$offset); $x++ ){
                for( $y=$offset; $y<($h-$offset); $y++ ){
                    $rgb = imagecolorat( $gd, $x, $y );
                    if( $color != $rgb ){ $left = $x; break; }
                    }

                if( !is_null($left) ){ break; }
                }
#
#   right
#
            echo "Finding the right of the image\n";
            $right = null;
            for( $x=($w-$offset); $x>$offset; $x-- ){
                for( $y=$offset; $y<($h-$offset); $y++ ){
                    $rgb = imagecolorat( $gd, $x, $y );
                    if( $color != $rgb ){ $right = $x; break; }
                    }

                if( !is_null($right) ){ break; }
                }

どちらの場合も、$color 変数には画像の最初のカラー ドットが含まれます。

$color = imagecolorat( $gd, 0, 0 );

これは、GIF 画像では最初のドットが 99% の確率で透明 (または背景) 色であるためです。また、$offset は (私にとって) 画像が非常に広く、非常に高いだけであることを知っていることを示す方法です。したがって、最大で 256 x 256 しかないものを描画し、それを 1024 x 1024 の背景に配置すると、その背景の一部を叩いて 255 のオフセットを作成できるため、FOR ループは 255 から (1024 -255) または 769。

わかりました-誰かが尋ねる前に-なぜ私はそのようなことをするのでしょうか-一部のフォント(Bastardaなど)には正しいフォント情報が含まれておらず、文字「z」の256pt出力は「 z" は 256 を超える (512 のような値まで) ため、イメージ全体を取得するには、フォントが想定するよりも下から開始 (または終了) する必要があります。だから私は違いを分割し、両端から 255 ピクセルを叩き落とします。これは、Bastarda がこれを行うのを実際に見た後でした。

いくつかの追加メモ:

1. PNG 画像は GIF 画像のように設定できますが、通常は背景色を指定する必要があります。
2. JPEG 画像は、毎回まったく同じ方法で解凍されるわけではありません。そのため、2 回読み込んだ同じ画像を比較しても、同じようには機能せず、サイズが異なる場合があります。
3. これらのルーチンは、単純な白黒 (または 2 色) の画像に最適です。複数の色を使用すると、これらのルーチンが台無しになる可能性があります。特に公差を使用することにした場合。
4. 許容値を使用して画像のエッジが見つかったかどうかを判断するには、高許容値と低許容値の両方を事前に計算するだけです (つまり、赤のコンポーネントの許容値が 5 の場合)。の場合、公差を範囲全体にするか、+/- 範囲にするかによって、公差を X-5-to-x+5 または x-2.5-to-x+2.5 として計算できます)。色の RED、GREEN、BLUE、および ALPHA 部分、または色自体全体に対して許容範囲を設定できます。したがって、必要に応じて計算できるいくつかの異なる公差があり、それらはすべて、ニーズに応じて計算する正しい方法です。

于 2015-12-29T07:23:51.107 に答える
1

PHPのImageMagickライブラリをチェックしてください。画像( cropを含む)を操作および操作するための優れた方法があります。

「空白」が画像の周囲のどこにあるかを把握する必要があります。「空白」は白、他の色、透明度などである可能性があるため、難しい場合があります。

于 2009-11-03T19:50:30.817 に答える