2013-04-27 4 views
5

Я вращаю и обрезаю изображение с помощью PHP, но получаю черную рамку, я знаю, что вы можете изменить цвет фона, но я хочу повернуть и обрезать изображение, чтобы заполнить все изображение. В основном что-то похожее на background-size: cover; (слева) в CSS по сравнению с background-size: contain; (справа).Поворот и обрезка

См. Изображение ниже, справа - это то, что я получил сейчас, слева - это то, чего я хочу достичь. Число градусов для вращения является динамическим, а изображение должно быть произведено, а исходное изображение - квадратным (200x200).

Illustration of problem

EDIT: Вот мой быстрый и грязный код:

$rotate = imagecreatefromjpeg($image); 
// part of code created by www.thewebhelp.com, modified 
$square_size = 200; 
$original_width = imagesx($rotate); 
$original_height = imagesy($rotate); 
if($original_width > $original_height){ 
    $new_height = $square_size; 
    $new_width = $new_height*($original_width/$original_height); 
} 
if($original_height > $original_width){ 
    $new_width = $square_size; 
    $new_height = $new_width*($original_height/$original_width); 
} 
if($original_height == $original_width){ 
    $new_width = $square_size; 
    $new_height = $square_size; 
} 

$new_width = round($new_width); 
$new_height = round($new_height); 

$smaller_image = imagecreatetruecolor($new_width, $new_height); 
$square_image = imagecreatetruecolor($square_size, $square_size); 

imagecopyresampled($smaller_image, $rotate, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height); 

if($new_width>$new_height){ 
    $difference = $new_width-$new_height; 
    $half_difference = round($difference/2); 
    imagecopyresampled($square_image, $smaller_image, 0-$half_difference+1, 0, 0, 0, $square_size+$difference, $square_size, $new_width, $new_height); 
} 
if($new_height>$new_width){ 
    $difference = $new_height-$new_width; 
    $half_difference = round($difference/2); 
    imagecopyresampled($square_image, $smaller_image, 0, 0-$half_difference+1, 0, 0, $square_size, $square_size+$difference, $new_width, $new_height); 
} 
if($new_height == $new_width){ 
    imagecopyresampled($square_image, $smaller_image, 0, 0, 0, 0, $square_size, $square_size, $new_width, $new_height); 
} 

$degrees = rand(1,360); 
$square_image = imagerotate($square_image, $degrees, 0); 
imagejpeg($square_image,NULL,100); 
+0

Показать Ваш код. – sachleen

+0

Я думаю, что ваша аналог «фона-размера» не согласуется с тем, что вам нужно. – Ejaz

+0

http://stackoverflow.com/a/22511805/2106820 –

ответ

5

Заменить эти строки примерно в конце кода:

$degrees = rand(1,360); 
$square_image = imagerotate($square_image, $degrees, 0); 
imagejpeg($square_image,NULL,100); 

С этим:

$degrees = rand(1,360); 
$square_image = imagerotate($square_image, $degrees, 0); 

$rotated_size = imagesx($square_image); 
$enlargement_coeff = ($rotated_size - $square_size) * 1.807; 
$enlarged_size = round($rotated_size + $enlargement_coeff); 
$enlarged_image = imagecreatetruecolor($enlarged_size, $enlarged_size); 
$final_image = imagecreatetruecolor($square_size, $square_size); 

imagecopyresampled($enlarged_image, $square_image, 0, 0, 0, 0, $enlarged_size, $enlarged_size, $rotated_size, $rotated_size); 
imagecopyresampled($final_image, $enlarged_image, 0, 0, round($enlarged_size/2) - ($square_size/2), round($enlarged_size/2) - ($square_size/2), $square_size, $square_size, $square_size, $square_size); 

imagejpeg($final_image,NULL,100); 

Вот логика, что:

1) После выполнения imagerotate() наших новый образ изменил свои размеры, так как каждый поворот обычно приводит к более крупному изображению. Поскольку источник представляет собой квадратное изображение, мы берем либо ширину, либо высоту, чтобы определить размеры повернутого изображения.

2) Когда исходное изображение повернуто, хотя бы немного, размеры самого большого квадрата используемых пиксельных данных из исходного изображения всегда будут меньше, чем исходное невращающееся квадратное изображение. Поэтому, чтобы создать новое квадратное изображение того же размера, что и начальное квадратное изображение, но без артефакта «черной границы», как вы его называете, нам нужно увеличить повернутое изображение, так что наибольший квадрат используемого пикселя данные из исходного изображения во вращающемся изображении могут достигать начального квадратного изображения.

Ключевое значение здесь 1.807. Это значение в основном показывает, сколько пикселей вам нужно увеличить повернутое изображение для каждого пикселя разницы между его размерами и размерами исходного невращенного изображения. Вероятно, есть лучшая математическая формула для извлечения этого значения, к сожалению, я сосать в Math, так что это трудный способ придумать это значение.

  • Вращение 45/135/225/315 градусов всегда будет производить наибольшее изображение с наименьшим квадратом данных пиксельных данных.
  • Зная это, вы сравниваете размеры исходного изображения и его версию с 45 градусами поворота. В нашем случае исходное изображение - 200x200, а версия с 45 градусами - около 283x283.
  • . .
  • . В программе, подобной Photoshop, вы определяете, сколько раз вам нужно увеличить 45-градусную версию изображения, чтобы иметь возможность извлекать из него квадрат размером 200 × 200 без «черной границы» - в нашем случае изображение 283х283 должно быть увеличено до изображения 433x433, поэтому мы могли бы извлечь квадрат 200 × 200
  • 433 - 283 = 150 -> значение нам нужно увеличить максимально возможное повернутое изображение с 150 пикселями, чтобы извлечь из него квадрат размером 200x200.
  • 283 - 200 = 83 -> 83 пикселей - это разница между максимально возможным поворотным изображением и оригинальным невращаемым изображением.
  • «Маленькое» преобразование - «большая» площадь, которую мы можем использовать, и, следовательно, «меньший» объем расширения, который нам нужно применить. И поскольку поворот на 45 градусов привел к разнице в 83 пикселя между исходным изображением и преобразованным изображением, которое требовало увеличения на 150 пикселей, мы можем сделать:
  • 150/83 = 1.807 -> означает разницу в 1 пиксель между Исходное изображение и повернутое изображение требует, чтобы повернутое изображение увеличивается с 1.807 пикселей, так что мы можем извлечь квадрат из него, что имеет те же размеры, что и исходное изображение

3) Зная, что для каждой разности 1 пиксель нам нужно увеличить с 1,807 пикселями, мы проверим, в чем разница между нашим размером вращения и размером оригинального изображения и умножьте его на это значение, чтобы увидеть, какие размеры должны иметь увеличенное изображение:

$enlargement_coeff = ($rotated_size - $square_size) * 1.807; 
$enlarged_size = round($rotated_size + $enlargement_coeff); 

4) Мы идем вперед и генерируем увеличенное повернутое изображение.

imagecopyresampled($enlarged_image, $square_image, 0, 0, 0, 0, $enlarged_size, $enlarged_size, $rotated_size, $rotated_size); 

5) Наконец, мы извлечь 200x200 квадрат из нашего расширенного повернутого изображения, используя его координаты центра в качестве ссылки

imagecopyresampled($final_image, $enlarged_image, 0, 0, round($enlarged_size/2) - ($square_size/2), round($enlarged_size/2) - ($square_size/2), $square_size, $square_size, $square_size, $square_size); 

Чтобы разрушить это ($square_size/2) возвращает X и Y координаты центральной точки в увеличенном повернутом изображении. возвращает количество пикселей, которое вам нужно, от центра вдоль оси X и над центром вдоль оси Y, чтобы получить квадрат 200 × 200.


Я надеюсь, вы понимаете логику, хотя я понять мое объяснение может показаться немного неоднозначным, поэтому, пожалуйста, не стесняйтесь спрашивать больше!

+0

Вау! Спасибо за подробное объяснение. Ваше решение работает, но есть много потери качества из-за изменения размера, вы можете это исправить? – aNewStart847

Смежные вопросы