PHPで画像を囲む空白を削除することは可能ですか?
注:明確にするために、私はフォトショップのトリム機能のようなものを意味します。
ありがとう。
画像の興味深い部分を囲むすべての空白をトリミングするには、最初に「空白」が停止する場所を見つけ、次にそれらの境界内のすべてをコピーします。
//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");
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
);
}
これはかなり古いことは知っていますが、ImageMagickを有効にしている場合は、この方法を使用できます
PHPのGdライブラリには imagecropauto
関数(PHPバージョン5.5以降)があります。
<?php
$img=imagecreatefrompng("Tux.png"); // Load and instantiate the image
if($img) {
$cropped=imagecropauto($img,IMG_CROP_DEFAULT); // Auto-crop the image
imagedestroy($img); // Clean up as $img is no longer needed
header("Content-type: image/png"); // Set the appropriate header so the browser
// knows how to present it
imagepng($cropped); // Return the newly cropped image
}
デフォルトでは、imagecropauto
は透明度を使用してトリミングを試み、次に画像の4つの角を使用してフォールバックし、トリミングする背景を検出しようとします。上記の例では、IMG_CROP_AUTO
の代わりに次の定数を使用して成功しました。
IMG_CROP_BLACK
-背景が黒の画像に便利IMG_CROP_WHITE
-背景が白の画像に便利IMG_CROP_THRESHOLD
-トリミング時に使用する色としきい値を設定できますこれはかなり古いと思いますが、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。
わかりました-誰かが尋ねる前に-なぜ私はそのようなことをするのですか-一部のフォント(バスタルダのような)には正しいフォント情報がなく、文字「z」の256pt出力は「」の下部に画像を生成するためですz "は256を超えます(512のようなものになります)ので、画像全体を取得するには、フォントが行くと思うよりもはるかに下に開始(または終了)する必要があります。だから私は違いを分割し、両端から255ピクセルを叩き落とします。これは、バスターダがこれを行うのを実際に見た後のことでした。
いくつかの追加の注意:
1. GIF画像のように設定できるPNG画像ですが、通常は背景色を指定する必要があります。
2。 JPEG画像は、毎回まったく同じ方法で解凍されるわけではありません。したがって、2回ロードした同じ画像を比較しても、同じように機能せず、サイズが異なる場合があります。
3。これらのルーチンは、単純な白黒(または2色)画像で最適に機能します。複数の色がこれらのルーチンを失敗させる可能性があります。特に公差を使用することにした場合。
4。公差を使用して画像のエッジを見つけたかどうかを判断するには、高公差と低公差の両方を事前に計算するだけです(つまり、赤のコンポーネントに5の公差がある場合は、許容誤差を全体の範囲にするか、または単にするかによって、許容誤差をX-5-to-x + 5 OR x-2.5-to-x + 2.5 +/-範囲)。色の赤、緑、青、アルファの部分または色全体に許容値を設定できます。したがって、必要に応じて計算できるさまざまな許容値がいくつかあり、それらはすべて正しいです。あなたのニーズに応じてそれを行う方法。
PHPの ImageMagick ライブラリをチェックしてください。画像を操作および操作するための優れた方法があります( crop を含む)。
「空白」が画像の周囲のどこにあるかを把握する必要があります。 「空白」は白、その他の色、透明度などである可能性があるため、難しい場合があります。