Подтвердить что ты не робот

Обрезать пробелы из изображения в PHP

Можно ли удалить пробел, окружающий изображение в PHP?

ПРИМЕЧАНИЕ. Чтобы уточнить, я имею в виду что-то вроде функции обрезки photoshop.

Спасибо.

4b9b3361

Ответ 1

Чтобы обрезать все пробелы, как вы его называете, окружая интересную часть изображения, сначала мы узнаем, где останавливается "пробел", а затем мы копируем все внутри этих границ.

//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");

Ответ 2

Gnud script избыточно вызывает imagesx и imagesy. Он также выполняет итерацию каждого пикселя со всех сторон, даже когда углы перекрываются. Эта улучшенная версия исключает избыточные вызовы функций и проверяет каждый пиксель только один раз, обеспечивая значительное увеличение скорости. Функция возвращает статус ($ result ['#']), равный 2, если каждый пиксель обрезается.

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
);
}

Ответ 3

Я знаю, что это довольно старый, но если у вас включен ImageMagick, вы можете использовать этот метод

Trim Image

Ответ 4

Я понимаю, что это довольно старый, но я немного по-другому беру на обрезку изображения через GD. Вместо того, чтобы делать только одну сторону за раз - все четыре. В какой-то степени это быстрее и дешевле cpu-wise. Однако, если вы остановите цикл 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% случаев прозрачного (или фонового) цвета. Кроме того, смещение $(для меня) означает, что я знаю, что изображение будет только таким широким и таким высоким. Поэтому, если я нарисую что-то, что составляет максимум 256 на 256, но я помещаю его на фон 1024 x 1024, я могу отбросить часть этого фона и сделать смещение 255, тем самым делая цикл FOR только от 255 до (1024 -255) или 769.

Хорошо - прежде чем кто-то спросит - ПОЧЕМУ Я бы сделал такое - потому что некоторые шрифты (например, Bastarda) не имеют в них правильной информации о шрифтах, а 256-разрядный вывод буквы "z" создает изображение, "z" проходит мимо 256 (вплоть до примерно 512), поэтому, чтобы получить весь образ, вы должны начать (или закончить) дальше, чем то, что, по вашему мнению, будет идти. Поэтому я разделил разницу и ударил 255 пикселей с обоих концов. Это было после того, как он увидел, что это делает Бастарда.

Некоторые дополнительные примечания:

1. PNG-изображения, которые вы можете настроить как изображения GIF, но обычно вам нужно будет указать, какой будет цвет фона.
2. Изображения JPEG НЕ разматывают точно так же каждый раз. Поэтому даже сравнение одного и того же изображения, которое вы загрузили дважды, может не работать одинаково и может давать разные размеры.
3. Эти процедуры лучше всего работают на простых черно-белых (или двухцветных) изображениях. Несколько цветов могут отбросить эти процедуры. Особенно, если вы решите использовать допуски.
4. Чтобы использовать допуски, чтобы определить, нашли ли вы край изображения, все, что вам нужно сделать, это предварительно вычислить как высокий, так и низкий допуск (т.е. Если у вас есть допущение пяти (5) на красном компоненте, то вы можете вычислить допуск как X-5-x-x + 5 или x-2,5-x + 2,5 в зависимости от того, хотите ли вы, чтобы допуск был диапазоном WHOLE или только диапазоном +/-). Вы можете иметь допуск для красных, зеленых, голубых и ALPHA частей цвета или всего цвета. Таким образом, существует несколько разных допусков, которые вы можете вычислить, если хотите, и все они - правильный способ сделать это в зависимости от ваших потребностей.

Ответ 5

Ознакомьтесь с библиотекой ImageMagick на PHP. Он имеет хорошие методы работы с изображениями (включая обрезка).

Вам нужно выяснить, где "пробел" вокруг изображения. Это может быть сложной задачей, поскольку "пробел" может быть цветом белого, другого цвета, прозрачности и т.д.

Ответ 6

PHP gd-библиотека имеет функцию imagecropauto:

<?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 будет пытаться обрезать с использованием прозрачности, а затем вернуться к использованию четырех углов изображения, чтобы попытаться обнаружить фон для обрезки; У меня также был успех со следующими константами вместо IMG_CROP_AUTO в приведенном выше примере:

  • IMG_CROP_BLACK - Полезно для изображений с черным фоном
  • IMG_CROP_WHITE - Полезно для изображений с белым фоном
  • IMG_CROP_THRESHOLD - Позволяет установить цвет и порог для использования при обрезке

imagecropauto был включен в php с версии 5.5, для получения дополнительной информации см. Документация по PHP для imagecropauto здесь.