Как я могу обрезать только левую и правую сторону изображения, используя Imagemagick в PHP? - PullRequest
13 голосов
/ 22 октября 2011

Я пытаюсь обрезать переменное количество пробелов в изображении только с левой и правой сторон, используя ImageMagick и PHP. Кто-нибудь знает, как это сделать (возможно, используя что-то, кроме imagemagick?)?

Вот пример.

У меня есть два изображения:
Test
Test Again
Каждый из них имеет переменное количество текста, которое динамически создается в изображении с фиксированной шириной. Что мне нужно сделать, это обрезать фон справа и слева, чтобы изображения выглядели так:
TestResult
Test Again Result

Если ImageMagick не может этого сделать, я готов использовать что-то еще, но мне понадобится помощь в том, как именно, потому что я не очень программист. Спасибо!

Вот мой текущий код, который обрезает все стороны изображения:

<?php
/* Create the object and read the image in */
$i = '3';
$im = new Imagick("test".$i.".png");

/* Trim the image. */
$im->trimImage(0);

/* Ouput the image */
//header("Content-Type: image/" . $im->getImageFormat());
//echo $im;
/*** Write the trimmed image to disk ***/
$im->writeImage(dirname(__FILE__) . '/test'.$i.'.png');
/*Display Image*/
echo $img = "<img src=\"test".$i.".png\">";
?>

Ответы [ 6 ]

17 голосов
/ 01 марта 2015

Я думаю, что вы на правильном пути с оператором ImageMagick -trim 1) , но хитрость заключается в том, чтобы заставить его сказать вам, что он будет делать без на самом деле этого, а затем измените это, чтобы сделать то, что вы действительно хотите ...

Итак, чтобы получить триммер ImageMagick рассчитывает для вашего первого изображения, вы делаете это:

convert -fuzz 10% image.jpg -format "%@" info:
60x29+21+31

Это прямоугольник размером 60x29 пикселей со смещением 21 в поперечном направлении и 31 в нижнем левом углу. Теперь мы хотим получить эти значения в bash переменных, поэтому я установил IFS (Разделитель входных полей) для разделения полей на пробелы, x, а также + знаков:

#!/bin/bash
IFS=" x+" read a b c d < <(convert -fuzz 10% image.jpg -format "%@" info:)

echo $a $b $c $d
60 29 21 31

Теперь я могу игнорировать 29 и 31, потому что нас интересует только обрезка по ширине и обрезка следующим образом:

convert image.jpg -crop "${a}x+${c}+0" out.jpg

Итак, для ваших 2-х изображений я получаю:

enter image description here enter image description here

и полная процедура такова:

#!/bin/bash
IFS=" x+" read a b c d < <(convert -fuzz 10% image.jpg -format "%@" info:)
convert image.jpg -crop "${a}x+${c}+0" out.jpg

Примечания

1) -format %@ - это просто сокращение для оператора -trim, которое будет полностью

convert image.jpg -trim info:
image.jpg JPEG 72x40 200x100+16+24 8-bit sRGB 0.000u 0:00.000
5 голосов
/ 30 октября 2011

Библиотека на основе GD WideImage имеет нечто подобное.Он называется autoCrop, по умолчанию он работает со всех четырех сторон.

Однако вы можете просто добавить другой параметр и на его основе обрезать только верх / низ или влево / вправо.

код autoCrop

Это довольно хорошо задокументировано.$img - это тип WideImage_Image.Существует также интерактивная демоверсия .

Вопрос по теме: Удаление черных полос с миниатюры видео .

4 голосов
/ 29 октября 2011

Из того, что я вижу в документах ImageMagick о обрезке и границах , это кажется невозможным.

Вы не можете указать ребро для "интеллектуального" кадрирования (в командной строке это называется -trim), и для всех методов кадрирования, которые принимают аргумент геометрии, для кадрирования требуется фиксированное число.

Единственная идея, которая приходит на ум, - получить цвет бритой области в отдельном вызове, запустить trimImage и добавить потерянные области обратно, используя -border.

Редактировать: Руководство по IM предлагает что-то подобное. Посмотрите Обрезка только одной стороны изображения. Я не знаком с расширением IM для PHP для перевода кода в вызовы PHP, но оно должно быть наполовину простым.

2 голосов
/ 29 октября 2011

Использование GD:

function imageautocrop( &$img) {
    $emptycol = function ( $img, $x, $min, $max) {
        for( $y=$min; $y<$max; $y++) {
            $col = imagecolorsforindex( $img, imagecolorat( $img, $x, $y));
            if( $col['alpha'] != 127) return false;
        }
        return true;
    }
    $trim = Array('top'=>0,'bot'=>0,'lft'=>0,'rgt'=>0);
    $size = Array('x'=>imagesx($img)-1,'y'=>imagesy($img)-1);
    // code for affecting rows removed due to question asked
    while( $emptycol( $img, $trim['lft'], $trim['top'], $size['y']-$trim['bot'])) $trim['lft']++;
    while( $emptycol( $img, $size['x']-$trim['rgt'], $trim['top'], $size['y']-$trim['bot'])) $trim['rgt']++;
    $newimg = imagecreate( $size['x']-$trim['lft']-$trim['rgt']+1, $size['y']-$trim['top']-$trim['bot']+1);
    imagecopy( $newimg, $img, 0, 0, $trim['lft'], $trim['top'], imagesx($newimg)+1, imagesy($newimg)+1);
    imagedestroy($img);
    $img = $newimg;
}

Это мой очень старый код, поэтому, вероятно, не оптимальный, но он выполняет свою работу.

0 голосов
/ 04 ноября 2011

Это двухэтапный процесс, поскольку текст генерируется динамически

  • Сгенерировать текстовое изображение, определить ширину (изображение)
  • Наложить текстовое изображение на фон, определить ширину (фон)
  • Используйте один из инструментов, упомянутых выше, кадрирование (ширина (фон) - ширина (изображение) / 2 с обеих сторон

Хитрость в определении ширины (изображение). См .: Как автоматически настроить ширину сгенерированного GD изображения, чтобы он соответствовал тексту?

Опять же, если вы знаете ширину (изображение), вы можете сначала обрезать ширину (фон) перед наложением

0 голосов
/ 22 октября 2011

Используйте cropImage () вместо этого. Примерно так, возможно:

$img_x_size = 800;    // Set these to relevant values
$img_y_size = 600;

$crop_pixels = 20;    // How many pixels to crop

// cropImage(XsizeOfCrop, YsizeOfCrop, CropXPos, CropYPos)
$im->cropImage($img_x_size - $crop_pixels, $img_y_size, 0, $crop_pixels / 2);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...