Как я могу обрезать только левую и правую часть изображения, используя Imagemagick в PHP?

Я пытаюсь обрезать переменное количество пробелов в изображении только левой и правой стороной, используя 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\">";
?>

Ответ 1

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

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

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

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

Ответ 2

Я думаю, что вы на правильном пути с оператором 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 hereenter 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

Ответ 3

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

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

код автозагрузки

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

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

Ответ 4

Использование 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;
}

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

Ответ 5

Вместо этого используйте 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);

Ответ 6

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

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

Трюк вычисляет ширину (изображение). Смотрите: Как настроить автоматическую настройку ширины GD-сгенерированного изображения в соответствии с текстом?

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