사이트 내 전체검색
PHP
resize and/or crop an animated GIF , gif 까지 줄여주는 섬네일 처리
로빈
https://cmd.kr/php/949 URL이 복사되었습니다.

본문

imagick 라이브리가 필요하다.

apt-get install php-imagick
설치확인
php -m | grep imagick
service apache2 restart

예)
chat_thumbnail($_FILES['upfile']['tmp_name'], $thumb_file, 60, 60);





function chat_thumbnail($source_file, $thumb_file, $thumb_width, $thumb_height)
{

$is_crop=true;
$crop_mode='center';
$is_sharpen=false;
$um_value='80/0.5/3';
    if(!$thumb_width && !$thumb_height)
        return;
    if(!is_file($source_file)) // 원본 파일이 없다면
        return;

    $size = @getimagesize($source_file);
    if($size[2] < 1 || $size[2] > 3) // gif, jpg, png 에 대해서만 적용
        return;

$target_path=dirname($thumb_file);
    if (!is_dir($target_path)) return;

    // 디렉토리가 존재하지 않거나 쓰기 권한이 없으면 썸네일 생성하지 않음
    if(!(is_dir($target_path) && is_writable($target_path))) return;

    // Animated GIF는 썸네일 생성하지 않음
    if($size[2] == 1 && is_animated_gif($source_file)) {
$image = new Imagick($source_file);

$image = $image->coalesceImages();

$dst_w = $thumb_width;
$dst_h = $thumb_height;
$src_w = $size[0];
$src_h = $size[1];
$ratio = $dst_h / $dst_w;
if($size[1] / $size[0] >= $ratio) {
$src_h = round($src_w * $ratio);
$src_y = round(($size[1] - $src_h) / 2);
} else {
$src_w = round($size[1] / $ratio);
$src_x = round(($size[0] - $src_w) / 2);
}

foreach ($image as $frame) {
$frame->cropImage($src_w, $src_h, $src_x, $src_y);
$frame->thumbnailImage($thumb_width, $thumb_height);
$frame->setImagePage($thumb_width, $thumb_height, 0, 0);
}
$image = $image->deconstructImages();
$image->writeImages($thumb_file, true);
    }

    // 원본파일의 GD 이미지 생성
    $src = null;
    $degree = 0;

    if ($size[2] == 1) {
        $src = @imagecreatefromgif($source_file);
        $src_transparency = @imagecolortransparent($src);
    } else if ($size[2] == 2) {
        $src = @imagecreatefromjpeg($source_file);

        if(function_exists('exif_read_data')) {
            // exif 정보를 기준으로 회전각도 구함
            $exif = @exif_read_data($source_file);
            if(!empty($exif['Orientation'])) {
                switch($exif['Orientation']) {
                    case 8:
                        $degree = 90;
                        break;
                    case 3:
                        $degree = 180;
                        break;
                    case 6:
                        $degree = -90;
                        break;
                }

                // 회전각도 있으면 이미지 회전
                if($degree) {
                    $src = imagerotate($src, $degree, 0);

                    // 세로사진의 경우 가로, 세로 값 바꿈
                    if($degree == 90 || $degree == -90) {
                        $tmp = $size;
                        $size[0] = $tmp[1];
                        $size[1] = $tmp[0];
                    }
                }
            }
        }
    } else if ($size[2] == 3) {
        $src = @imagecreatefrompng($source_file);
        @imagealphablending($src, true);
    } else {
        return;
    }

    if(!$src)
        return;

    $is_large = true;
    // width, height 설정

    if($thumb_width) {
        if(!$thumb_height) {
            $thumb_height = round(($thumb_width * $size[1]) / $size[0]);
        } else {
            if($size[0] < $thumb_width || $size[1] < $thumb_height)
                $is_large = false;
        }
    } else {
        if($thumb_height) {
            $thumb_width = round(($thumb_height * $size[0]) / $size[1]);
        }
    }

    $dst_x = 0;
    $dst_y = 0;
    $src_x = 0;
    $src_y = 0;
    $dst_w = $thumb_width;
    $dst_h = $thumb_height;
    $src_w = $size[0];
    $src_h = $size[1];

    $ratio = $dst_h / $dst_w;

    if($is_large) {
        // 크롭처리
        if($is_crop) {
            switch($crop_mode)
            {
                case 'center':
                    if($size[1] / $size[0] >= $ratio) {
                        $src_h = round($src_w * $ratio);
                        $src_y = round(($size[1] - $src_h) / 2);
                    } else {
                        $src_w = round($size[1] / $ratio);
                        $src_x = round(($size[0] - $src_w) / 2);
                    }
                    break;
                default:
                    if($size[1] / $size[0] >= $ratio) {
                        $src_h = round($src_w * $ratio);
                    } else {
                        $src_w = round($size[1] / $ratio);
                    }
                    break;
            }

            $dst = imagecreatetruecolor($dst_w, $dst_h);

            if($size[2] == 3) {
                imagealphablending($dst, false);
                imagesavealpha($dst, true);
            } else if($size[2] == 1) {
                $palletsize = imagecolorstotal($src);
                if($src_transparency >= 0 && $src_transparency < $palletsize) {
                    $transparent_color  = imagecolorsforindex($src, $src_transparency);
                    $current_transparent = imagecolorallocate($dst, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
                    imagefill($dst, 0, 0, $current_transparent);
                    imagecolortransparent($dst, $current_transparent);
                }
            }
        } else { // 비율에 맞게 생성
            $dst = imagecreatetruecolor($dst_w, $dst_h);
            $bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색

if($src_w > $src_h) {
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
}
            if($size[2] == 3) {
                $bgcolor = imagecolorallocatealpha($dst, 0, 0, 0, 127);
                imagefill($dst, 0, 0, $bgcolor);
                imagealphablending($dst, false);
                imagesavealpha($dst, true);
            } else if($size[2] == 1) {
                $palletsize = imagecolorstotal($src);
                if($src_transparency >= 0 && $src_transparency < $palletsize) {
                    $transparent_color  = imagecolorsforindex($src, $src_transparency);
                    $current_transparent = imagecolorallocate($dst, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
                    imagefill($dst, 0, 0, $current_transparent);
                    imagecolortransparent($dst, $current_transparent);
                } else {
                    imagefill($dst, 0, 0, $bgcolor);
                }
            } else {
                imagefill($dst, 0, 0, $bgcolor);
            }
        }
    } else {
        $dst = imagecreatetruecolor($dst_w, $dst_h);
        $bgcolor = imagecolorallocate($dst, 255, 255, 255); // 배경색

//이미지 썸네일을 비율 유지하며 썸네일 생성합니다.
if($src_w < $dst_w) {
if($src_h >= $dst_h) {
if( $src_h > $src_w ){
$tmp_w = round(($dst_h * $src_w) / $src_h);
$dst_x = round(($dst_w - $tmp_w) / 2);
$dst_w = $tmp_w;
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$src_h = $dst_h;
if( $dst_w > $src_w ){
$dst_w = $src_w;
}
}
} else {
$dst_x = round(($dst_w - $src_w) / 2);
$dst_y = round(($dst_h - $src_h) / 2);
$dst_w = $src_w;
$dst_h = $src_h;
}
} else {
if($src_h < $dst_h) {
if( $src_w > $dst_w ){
$tmp_h = round(($dst_w * $src_h) / $src_w);
$dst_y = round(($dst_h - $tmp_h) / 2);
$dst_h = $tmp_h;
} else {
$dst_y = round(($dst_h - $src_h) / 2);
$dst_h = $src_h;
$src_w = $dst_w;
}
}
}

        if($size[2] == 3) {
            $bgcolor = imagecolorallocatealpha($dst, 0, 0, 0, 127);
            imagefill($dst, 0, 0, $bgcolor);
            imagealphablending($dst, false);
            imagesavealpha($dst, true);
        } else if($size[2] == 1) {
            $palletsize = imagecolorstotal($src);
            if($src_transparency >= 0 && $src_transparency < $palletsize) {
                $transparent_color  = imagecolorsforindex($src, $src_transparency);
                $current_transparent = imagecolorallocate($dst, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
                imagefill($dst, 0, 0, $current_transparent);
                imagecolortransparent($dst, $current_transparent);
            } else {
                imagefill($dst, 0, 0, $bgcolor);
            }
        } else {
            imagefill($dst, 0, 0, $bgcolor);
        }
    }

    imagecopyresampled($dst, $src, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);

    if($size[2] == 1) {
        imagegif($dst, $thumb_file);
    } else if($size[2] == 3) {
$png_compress = 3;
        imagepng($dst, $thumb_file, $png_compress);
    } else {
$jpg_quality = 70;
        imagejpeg($dst, $thumb_file, $jpg_quality);
    }
    imagedestroy($src);
    imagedestroy($dst);
    return true;
}


function is_animated_gif($filename) {
    if(!($fh = @fopen($filename, 'rb')))
        return false;
    $count = 0;
    // 출처 : http://www.php.net/manual/en/function.imagecreatefromgif.php#104473
    // an animated gif contains multiple "frames", with each frame having a
    // header made up of:
    // * a static 4-byte sequence (\x00\x21\xF9\x04)
    // * 4 variable bytes
    // * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)

    // We read through the file til we reach the end of the file, or we've found
    // at least 2 frame headers
    while(!feof($fh) && $count < 2) {
        $chunk = fread($fh, 1024 * 100); //read 100kb at a time
        $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
  }

    fclose($fh);
    return $count > 1;
}

댓글목록

등록된 댓글이 없습니다.

PHP
871 (1/18P)

Search

Copyright © Cmd 명령어 3.145.151.141