Created
July 13, 2011 18:16
-
-
Save makoni/1080919 to your computer and use it in GitHub Desktop.
PHP function for resizing animated GIF with Imagick
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Функция для дебага в браузере | |
* @param $smth - что выводить | |
* @param boolean $stop - остановить скрипт после вывода | |
*/ | |
function dbg( $smth, $stop = false ) { | |
echo "<xmp>"; | |
print_r( $smth ); | |
echo "</xmp>"; | |
if ( false !== $stop ) { | |
exit; | |
} | |
} | |
/** | |
* Функция создания квадратного изображения с кадрированием. | |
* @param string $sourceFile - путь до исходного файла | |
* @param string $destinationFile - путь файла, в который сохраняется результат | |
* @param integer $biggestSideSize - размер стороны квадратного изображения | |
* @param boolean $makeSquare - пока бесполезно, скорее задел на будущее, чтобы 1 функцией работать с Imagick | |
* @return | |
*/ | |
function resizeImagick( $sourceFile, $destinationFile, $biggestSideSize, $makeSquare = false ){ | |
$info = getimagesize( $sourceFile ); | |
$destinationFile = $destinationFile . image_type_to_extension( $info[2] ); | |
# проверяем на формат входного файла | |
if ( false === in_array( $info[2], array( IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG ) ) ) | |
return false; | |
$originalWidth = $info[0]; | |
$originalHeight = $info[1]; | |
# создаём новый пустой объект | |
$newFileObj = new \Imagick(); | |
# оригинальное изображение | |
$im = new \Imagick( $sourceFile ); | |
if ( true === $makeSquare ){ | |
if ( $originalWidth < $originalHeight ) { | |
$newWidth = $biggestSideSize; | |
$newHeight = 0; | |
} else { | |
$newWidth = 0; | |
$newHeight = $biggestSideSize; | |
} | |
$original_ratio = $originalWidth / $originalHeight; | |
if ($original_ratio >= 1) { | |
# ширина уменьшенной картинки (высота равна $biggestSideSize ) | |
$src_w = ( $originalWidth * $biggestSideSize ) / $originalHeight; | |
$src_x = ( $src_w - $biggestSideSize) / 2; | |
$src_y = 0; | |
} | |
else { | |
$src_h = ( $originalHeight * $biggestSideSize) / $originalWidth; | |
$src_x = 0; | |
$src_y = ( $src_h - $biggestSideSize) / 2; | |
} | |
switch ( $info[2] ){ | |
case IMAGETYPE_GIF: | |
$im = $im->coalesceImages(); | |
foreach ( $im as $newFileObj ) { | |
$newFileObj->setFormat("gif"); | |
$new_x = 0; | |
$new_y = 0; | |
$tmp_new_width = $newWidth; | |
$tmp_new_height = $newHeight; | |
$imagePage = $newFileObj->getImagePage(); | |
# ширина и высота обрезаемой области | |
# вертикальная картинка | |
if ( $originalWidth < $originalHeight ) { | |
$cutedWidth = $originalWidth; | |
$cutedHeight = $originalWidth; | |
} else { | |
#горизонтальная картинка | |
$cutedWidth = $originalHeight; | |
$cutedHeight = $originalHeight; | |
} | |
$resize_ratio = $cutedHeight / $biggestSideSize ; | |
$offset_y = $imagePage['y']; | |
# если размер кадра не совпадает с размером самой картинки | |
if ( $newFileObj->getImageWidth() < $newWidth ) { | |
$tmp_new_width = round( $newFileObj->getImageWidth() / $resize_ratio ); | |
$tmp_new_height = round( $newFileObj->getImageHeight() / $resize_ratio ); | |
$offset_x = $imagePage['x']; | |
$new_x = round( $offset_x / $resize_ratio ); | |
$new_y = round( $offset_y / $resize_ratio ); | |
} else if ( $newFileObj->getImageHeight() < $newHeight ) { | |
$tmp_new_width = round( $newFileObj->getImageWidth() / $resize_ratio ); | |
$tmp_new_height = round( $newFileObj->getImageHeight() / $resize_ratio ); | |
$offset_x = $imagePage['x'] - ( $originalWidth - $cutedWidth )/2; | |
$new_x = round( $offset_x / $resize_ratio ); | |
$new_y = round( $offset_y / $resize_ratio ); | |
#dbg( 'Кадр:' . $newFileObj->getImageWidth() . 'x' . $newFileObj->getImageHeight() ); | |
#dbg( 'Уменьшен до:' . $tmp_new_width . 'x' . $tmp_new_height ); | |
#dbg( 'Будет размещен: ' . $new_x . ',' . $new_y . ' в поле ' . $biggestSideSize . 'x' . $biggestSideSize ); | |
} | |
//Выполняется resize до 200 пикселей поширине и сколько получится по высоте (с соблюдением пропорций конечно) | |
$newFileObj->thumbnailImage( $tmp_new_width, $tmp_new_height ); | |
#dbg('Кропнуть: ' . $biggestSideSize . 'x' . $biggestSideSize . ' коорд. ' . $src_x . ',' . $src_y ); | |
#dbg( 'Кадр до кропа:' . $newFileObj->getImageWidth() . 'x' . $newFileObj->getImageHeight() ); | |
if ( $newFileObj->getImageHeight() >= $biggestSideSize || $newFileObj->getImageWidth() >= $biggestSideSize ) { | |
$newFileObj->cropImage( $biggestSideSize, $biggestSideSize, $src_x, $src_y ); | |
} | |
else { | |
$newFileObj->cropImage( $biggestSideSize, $biggestSideSize, 0, $src_y ); | |
} | |
$newFileObj->setImagePage( $newFileObj->getImageWidth(), $newFileObj->getImageHeight(), $new_x, $new_y ); | |
#dbg( 'Кадр после кропа:' . $newFileObj->getImageWidth() . 'x' . $newFileObj->getImageHeight() ); | |
#dbg('........................'); | |
} | |
$newFileObj->writeImages( $destinationFile, true); | |
return image_type_to_extension( $info[2], false ); | |
break; | |
case IMAGETYPE_PNG: | |
$im->thumbnailImage( $newWidth, $newHeight ); | |
$im->cropImage( $biggestSideSize, $biggestSideSize, $src_x, $src_y ); | |
#$im->setImageCompressionQuality(90); | |
$im->writeImages( $destinationFile, true); | |
return image_type_to_extension( $info[2], false ); | |
break; | |
case IMAGETYPE_JPEG: | |
$im->thumbnailImage( $newWidth, $newHeight ); | |
$im->cropImage( $biggestSideSize, $biggestSideSize, $src_x, $src_y ); | |
$im->setImageCompressionQuality(95); | |
$im->writeImages( $destinationFile, true); | |
return image_type_to_extension( $info[2], false ); | |
break; | |
} | |
} | |
switch ( $info[2] ){ | |
case IMAGETYPE_PNG: | |
$newFileObj->setFormat("png"); | |
$im->thumbnailImage( $newWidth, $newHeight ); | |
return $im->writeImages( $destinationFile, true); | |
break; | |
case IMAGETYPE_JPEG: | |
$newFileObj->setFormat("jpeg"); | |
$im->thumbnailImage( $newWidth, $newHeight ); | |
return $im->writeImages( $destinationFile, true); | |
break; | |
case IMAGETYPE_GIF: | |
$newFileObj->setFormat("gif"); | |
foreach ( $im as $newFileObj ) { | |
//Выполняется resize до 200 пикселей поширине и сколько получится по высоте (с соблюдением пропорций конечно) | |
$newFileObj->thumbnailImage( $newWidth, $newHeight ); | |
$newFileObj->setImagePage( $newFileObj->getImageWidth(), $newFileObj->getImageHeight(), 0, 0 ); | |
} | |
return $newFileObj->writeImages( $destinationFile, true); | |
break; | |
default: | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
А можно как то оптимизировать полученный GIF ? Ато сейчас на выходе он весит больше чем на входе :)