[PHP] 샤픈 효과를 적용한 썸네일 생성함수

이전에 만들었던 썸네일 관련 함수의 기능도 문제지만 썸네일의 품질이 너무 마음에 들지 않아 또 삽질을 시작!!

이번 함수의 가장 큰 특징은 썸네일에 샤픈 효과를 적용해 이미지 품질이 많이 좋아졌다는 것이다. 다만 적용된

일부 함수때문에 PHP4에서는 사용할 수 없다. 제대로 사용하기 위해서는 PHP 5.2 이상이어야 할 것이다.

<?php

$source_file = ‘./DSC_4180.jpg’;

$target_file = ‘./resize_DSC_4180.jpg’;

$target_file2 = ‘./resize2_DSC_4180.jpg’;

$result = pl_resizer($source_file, $target_file, 100, 100, true, ‘center’, true);

$result2 = pl_resizer($source_file, $target_file2, 100, 100, true, ‘center’);

?>

<!doctype html>

<html lang=”ko”>

<head>

<meta charset=”utf-8″>

<title>리사이징 테스트</title>

</head>

<body>

<table cellpadding=”10″ cellspacing=”0″ align=”center”>

<tr>

    <td><img src=”<?php echo $result; ?>” /></td>

    <td><img src=”<?php echo $result2; ?>” /></td>

</tr>

</table>

</body>

</html>

<?php

function pl_resizer($source_file, $target_file, $width=0, $height=0, $is_crop=false, $crop_mode=’center’, $step_resize=false)

{

    $size = @getimagesize($source_file);

    // gif, jpg, png 에 대해서만 적용

    if($size[2] < 1 || $size[2] > 3)

        return;

    // Animated GIF 체크

    if($size[2] == 1) {

        if(is_animated_gif($source_file))

            return;

    }

    if($width) {

        if($height) {

            if($size[0] < $width || $size[1] < $height)

                return;

        } else {

            $height = round(($width * $size[1]) / $size[0]);

        }

    } else {

        if($height) {

            $width = round(($height * $size[0]) / $size[1]);

        } else {

            return;

        }

    }

    $src = null;

    if ($size[2] == 1) {

        $src = imagecreatefromgif($source_file);

    } else if ($size[2] == 2) {

        $src = imagecreatefromjpeg($source_file);

    } else if ($size[2] == 3) {

        $src = imagecreatefrompng($source_file);

    } else {

        return;

    }

    $dst_x = 0;

    $dst_y = 0;

    $src_x = 0;

    $src_y = 0;

    $dst_w = $width;

    $dst_h = $height;

    $src_w = $size[0];

    $src_h = $size[1];

    $ratio = $dst_h / $dst_w;

    // 크롭처리

    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;

        }

    } else {

        if($size[1] / $size[0] >= $ratio) {

            $src_h = round($src_w * $ratio);

        } else {

            $src_w = round($size[1] / $ratio);

        }

    }

    /* sharpen 설정 */

    $sharpenMatrix = array

    (

        array(-1.2, -1, -1.2),

        array(-1, 20, -1),

        array(-1.2, -1, -1.2)

    );

    // calculate the sharpen divisor

    $divisor = array_sum(array_map(‘array_sum’, $sharpenMatrix));

    $offset = 0;

    /* sharpen 설정 */

    /* 다단계 리사이즈 시작 */

    if($step_resize)

    {

        $w = $dst_w;

        $w_count = 0;

        while(1) {

            $w = $w * 2;

            if($w >= $src_w)

                break;

            $w_count++;

        }

        $h = $dst_h;

        $h_count = 0;

        while(1) {

            $h = $h * 2;

            if($h >= $src_h)

                break;

            $h_count++;

        }

        $resize_count = min($w_count, $h_count);

        if($resize_count > 1) {

            $dst_w = round($src_w / 2);

            $dst_h = round($src_h / 2);

        } else {

            $dst_w = $width;

            $dst_h = $height;

        }

        $count = 0;

        while($count<=$resize_count)

        {

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

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

            $src = $dst;

            $src_x = 0;

            $src_y = 0;

            $src_w = $dst_w;

            $src_h = $dst_h;

            $dst_w = round($src_w / 2);

            $dst_h = round($src_h / 2);

            if($dst_w <= $width || $dst_h <= $height) {

                $dst_w = $width;

                $dst_h = $height;

            }

            $count++;

        }

    }

    /* 다단계 리사이즈 끝 */

    else

    {

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

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

    }

    /* sharpen 적용 */

    imageconvolution($dst, $sharpenMatrix, $divisor, $offset);

    imagejpeg($dst, $target_file, 90);

    return $target_file;

}

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 (x00x21xF9x04)

    // * 4 variable bytes

    // * a static 2-byte sequence (x00x2C) (some variants may use x00x21 ?)

    // 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(‘#x00x21xF9x04.{4}x00(x2C|x21)#s’, $chunk, $matches);

   }

    fclose($fh);

    return $count > 1;

}

//include this file whenever you have to use imageconvolution…

//you can use in your project, but keep the comment below :)

//great for any image manipulation library

//Made by Chao Xu(Mgccl) 2/28/07

//www.webdevlogs.com

//V 1.0

if(!function_exists(‘imageconvolution’)){

    function imageconvolution($src, $filter, $filter_div, $offset){

        if ($src==NULL) {

            return 0;

        }

        $sx = imagesx($src);

        $sy = imagesy($src);

        $srcback = ImageCreateTrueColor ($sx, $sy);

        ImageCopy($srcback, $src,0,0,0,0,$sx,$sy);

        if($srcback==NULL){

            return 0;

        }

        #FIX HERE

        #$pxl array was the problem so simply set it with very low values

        $pxl = array(1,1);

        #this little fix worked for me as the undefined array threw out errors

        for ($y=0; $y<$sy; ++$y){

            for($x=0; $x<$sx; ++$x){

                $new_r = $new_g = $new_b = 0;

                $alpha = imagecolorat($srcback, $pxl[0], $pxl[1]);

                $new_a = $alpha >> 24;

                for ($j=0; $j<3; ++$j) {

                    $yv = min(max($y – 1 + $j, 0), $sy – 1);

                    for ($i=0; $i<3; ++$i) {

                            $pxl = array(min(max($x – 1 + $i, 0), $sx – 1), $yv);

                        $rgb = imagecolorat($srcback, $pxl[0], $pxl[1]);

                        $new_r += (($rgb >> 16) & 0xFF) * $filter[$j][$i];

                        $new_g += (($rgb >> 8) & 0xFF) * $filter[$j][$i];

                        $new_b += ($rgb & 0xFF) * $filter[$j][$i];

                    }

                }

                $new_r = ($new_r/$filter_div)+$offset;

                $new_g = ($new_g/$filter_div)+$offset;

                $new_b = ($new_b/$filter_div)+$offset;

                $new_r = ($new_r > 255)? 255 : (($new_r < 0)? 0:$new_r);

                $new_g = ($new_g > 255)? 255 : (($new_g < 0)? 0:$new_g);

                $new_b = ($new_b > 255)? 255 : (($new_b < 0)? 0:$new_b);

                $new_pxl = ImageColorAllocateAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);

                if ($new_pxl == -1) {

                    $new_pxl = ImageColorClosestAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);

                }

                if (($y >= 0) && ($y < $sy)) {

                    imagesetpixel($src, $x, $y, $new_pxl);

                }

            }

        }

        imagedestroy($srcback);

        return 1;

    }

}

?>

아직 완성된 함수는 아니다. 예외처리 등의 코드를 더 추가해야하는데.. 간단히 테스트해볼 정도는 된다. 샤픈 효과에

더불어 다단계 리사이즈 기능을 구현해보려고 삽질을 했는데.. 제대로 된 것인지는 모르겠다. 작동은 하는데.. 뭔가

이미지 품질에서 차이가 없다고 해야할까? 결과물만 보면 굳이 다단계 리사이즈라는 게 필요할까 싶은 생각도 든다.

암튼 좀 더 함수를 다듬어야 한다. 근데.. 이건 또 언제할지.. ㅋ 퇴근 후에 해야하는 것이라 여유가 많지 않다.

편리

PHP와 MariaDB, jQuery 등을 사용해 게시판, 쇼핑몰 솔루션을 개발합니다. 그누보드5와 영카트5 개발에 참여 했습니다. Linux와 Nginx는 물론 WordPress, Git 등에도 관심이 많습니다. 자전거 타기 및 사진 촬영을 취미로 하고 있습니다.

카카오톡 플러스친구 채팅 : NCUBE.NET

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.