본문 바로가기

Web Program/PHP

워터마크 함수 기능 보강 및 종합 썸네일함수 버그 수정


php > 내가 만들어 쓰는 함수 > 워터마크 함수 기능 보강 및 종합 썸네일함수 버그 수정

이전에는 종합 썸네일 함수를 만들어 보았습니다.
이번에는 워터마크 함수의 기능 보강과 종합 썸네일 함수의 버그을 수정해 보겠습니다.

기존 워터마크 함수는 투명 이미지는 사용할수 없었습니다.
이유는 선명도($sharpness) 때문입니다. 투명이미지 이기 때문에 선명도를 줄수 없기 때문입니다.
그래서 php의 내장함수인 imagecopymerge 는 불투명 이미지로 간주하고 이미지를 처리하기 때문에 투명 이미지를 사용할 경우에는 불투명 하게 제대로 워터마크 처리 되지 않았습니다.

좀 더 유연한 워터마크의 처리를 위해서 선명도가 100 일 경우에는 imagecopymerge 대신 imagecopyresampled 를 사용하여 투명이미지를 워터마크로 사용할수 있도록 처리하겠습니다.

예제1 : proc_watermark 수정

function proc_watermark($src, $src_w, $src_h, $path_mark_file, $pos, $sharpness, $padding=0){

  if (empty($src))  {//원본의 리소스 id 가 빈값일 경우

    $GLOBALS['errormsg'] = '원본 리소스가 없습니다.';

    return false;
  }

  //정수형이 아니라면 정수형으로 강제 형변환
  if (!is_int($src_w)) settype($src_w, 'int');
  if (!is_int($src_h)) settype($src_h, 'int');
  if (!is_int($sharpness)) settype($sharpness, 'int');
  if (!is_int($padding)) settype($padding, 'int');



  if ($src_w < 1 || $src_h < 1){//원본의 너비와 높이가 둘중에 하나라도 0보다 큰 정수가 아닐경우

    $GLOBALS['errormsg'] = "원본의 너비와 높이가 0보다 큰 정수가 아닙니다. ($src_w, $src_h)";

    return false;
  }



  if (empty($path_mark_file)) {//워터마크 이미지 경로값이 없다면

    $GLOBALS['errormsg'] = '워터마크 이미지경로값이 없습니다.';

    return false;
  }

  list($mark, $mark_w, $mark_h) = get_image_resource_from_file ($path_mark_file);

  if (empty($mark)) return false;//에러 메시지 작성은 get_image_resource_from_file 내부에서 함



  if ($src_w < $mark_w + (2 * $padding)) {//원본너비가 워터마크 이미지 너비보다 작으면 워터마크 처리 안함, return true;

    return true;
  }

  if ($src_h < $mark_h + (2 * $padding)) {//원본높이가 워터마크 이미지 높이보다 작으면 워터마크 처리 안함, return true;

    return true;
  }



  if ($sharpness < 0 || $sharpness > 100) $sharpness = 30;//$sharpness 가 지정된 범위 이상의 숫자라면 30으로 강제 재설정

  if ($padding < 0 || $padding > $mark_w || $padding > $mark_h) $padding = 10;//$padding이 0보다 작거나 워터마크의 너비나 높이보다 크면 10으로 강제 재설정



  if ($pos == 10) {//워터마크 전체로 찍을 경우의 처리

    $w_max = $src_w - $padding;
    $h_max = $src_h - $padding;

    //x 축으로 워터마크를 몇번 찍을 것인지 계산, 패딩을 더해서 나눔
    $x_max = ceil($w_max / ($mark_w + $padding));

    //y 축으로 워터마크를 몇번 찍을 것인지 계산
    $y_max = ceil($h_max / ($mark_h + $padding));

    //루프를 돌리면서 워터마크를 찍음
    for($x = 0; $x < $x_max; $x++){

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

        //기준점을 구한다.
        $src_x = $x * ($mark_w + $padding) + $padding;
        $src_y = $y * ($mark_h + $padding) + $padding;

        $copy_w = $mark_w;
        $copy_h = $mark_h;

        if ($src_x + $mark_w > $w_max) $copy_w = $w_max - $src_x;
        if ($src_y + $mark_h > $h_max) $copy_h = $h_max - $src_y;

        if ($sharpness != 100) {//선명도가 100 이 아닐경우에는 선명도를 사용할수 있는 imagecopymerge 사용

          $result_watermark = imagecopymerge($src, $mark, $src_x, $src_y, 0, 0, $copy_w, $copy_h, $sharpness);
        }
        else {//선명도가 100 일 경우에는 투명이미지를 사용할수 있는 imagecopyresampled 사용

          $result_watermark = imagecopyresampled ($src , $mark , $src_x, $src_y, 0 , 0 , $copy_w, $copy_h , $copy_w, $copy_h);
        }

        if ($result_watermark === false) {

          @imagedestroy($mark);

          $GLOBALS['errormsg'] = "워터마크 처리에 실패하였습니다.";

          return false;
        }
      }
    }
  }
  else {//워터마크를 하나만 찍을 경우에의 처리

    //워터마크의 복사할 너비, 높이 기본값 지정
    $copy_w = $mark_w;
    $copy_h = $mark_h;

    switch($pos){

      case 1 : //상단 왼쪽

        $src_x = 0 + $padding;
        $src_y = 0 + $padding;

        break;

      case 2 : //상단 오른쪽

        $src_x = $src_w - $mark_w - $padding;
        $src_y = 0 + $padding;

        break;

      case 3 : //하단 왼쪽

        $src_x = 0 + $padding;
        $src_y = $src_h - $mark_h - $padding;

        break;

      case 4 : //하단 오른쪽

        $src_x = $src_w - $mark_w - $padding;
        $src_y = $src_h - $mark_h - $padding;

        break;

      case 5 : //중앙

        $src_x = ceil(($src_w - $mark_w) / 2);
        $src_y = ceil(($src_h - $mark_h) / 2);

        break;

      default : // 그 밖의 값은 전부 상단 왼쪽 치부

        $src_x = 0 + $padding;
        $src_y = 0 + $padding;

    }

    if ($sharpness != 100) {//선명도가 100 이 아닐경우에는 선명도를 사용할수 있는 imagecopymerge 사용

      $result_watermark = imagecopymerge($src, $mark, $src_x, $src_y, 0, 0, $copy_w, $copy_h, $sharpness);
    }
    else {//선명도가 100 일 경우에는 투명이미지를 사용할수 있는 imagecopyresampled 사용

      $result_watermark = imagecopyresampled ($src , $mark , $src_x, $src_y, 0 , 0 , $copy_w, $copy_h , $copy_w, $copy_h);
    }

    @imagedestroy($mark);

    if ($result_watermark === false) {

      $GLOBALS['errormsg'] = "워터마크 처리에 실패하였습니다.";

      return false;
    }
  }

  return true;
}


이전시간에 만들어 보았던 종합 썸네일 테스트 함수인 thumnail_test1 은 약간의 버그가 있었습니다.
버그의 내용은 썸네일의 너비와 높이중 둘중 하나의 값이 0 일경우 내부적으로 정비율로 리사이즈하는 부분이 있는데, 리사이즈후 계산된 너비와 높이를 받아오지 않아서 워터마크가 작동하지 않는 부분이 있었습니다. 리사이즈나 크롭을 처리한후에 생성된 썸네일의 리소스로부터 다시 실제 너비와 높이를 받아오는 부분을 넣음으로서 이 버그를 해결 하였습니다.

예제2 : thumnail_test1 수정

function thumnail_test1($path_src_file, $path_save_file, $save_w, $save_h=0, $options=Array()){

  //기본값 설정
  $save_quality = 70;//저장 품질 : 70 %
  $save_force = 2;//저장형태 : 파일 덮어씌움

  $crop_use = 0;//크롭 사용여부
  $crop_pos_width = 2;//너비 기준 크롭시 중앙을 기준
  $crop_pos_height = 1;//높이 기준 크롭시 상단을 기준

  $watermark_path_file = '';//워터마크로 사용할 파일 경로 : 없음
  $watermark_pos = 4;//워터마크 찍는 위치 : 하단 오른쪽
  $watermark_sharpness = 30;//워터마크 이미지의 선명도 : 30 %
  $watermark_padding = 10;//원본과 워터마크 사이의 여백 : 10px

  //기본값 재설정
  if (!empty($options)) @extract($options);

  //원본 리소스 생성
  list($src, $src_w, $src_h) = get_image_resource_from_file ($path_src_file);
  if (empty($src)) return false;

  //리사이즈 또는 크롭 리사이즈
  if ($crop_use == 1) {//크롭 리사이즈

    $dst = get_image_cropresize($src, $src_w, $src_h, $save_w, $save_h, $crop_pos_width, $crop_pos_height);
  }
  else {//리사이즈

    $dst = get_image_resize($src, $src_w, $src_h, $save_w, $save_h);
  }

  @imagedestroy($src);
  if (empty($dst)) return false;

  $save_w = imagesx($dst);//생성된 썸네일 리소스에서 실제 너비를 구한다.
  $save_h = imagesy($dst);//생성된 썸네일 리소스에서 실제 높이를 구한다.

  //워터마크 이미지가 파일일 경우, 워터마크 처리
  if (!empty($watermark_path_file) && is_file($watermark_path_file)) {

    $result_watermark = proc_watermark($dst, $save_w, $save_h, $watermark_path_file, $watermark_pos, $watermark_sharpness, $watermark_padding);

    if (empty($result_watermark)) return false;
  }

  $result_save = save_image_from_resource ($dst, $path_save_file, $save_quality, $save_force);

  @imagedestroy($dst);

  return $result_save;
}

썸네일 리소스로부터 실제 너비와 높이를 구할때 imagesx 와 imagesy php 내장함수가 사용되었습니다.
이 두 함수는 각각 이미지 리소스로 부터 너비와 높이를 구해주는 함수입니다.


다음 예제를 통해 투명이미지의 워터마크 사용과 불투명 이미지의 워터마크 사용을 처리해 보도록 하겠습니다.

예제3 : test17.php

<?php

//이미지 처리 함수 인클루드
include_once 'lib/image_proc.function.php';



$path_src_file = 'sample_image/test.jpg';//원본파일
$path_mark_file1 ='sample_image/php.png';//워터마크에 사용할 파일, 불투명
$path_mark_file2 ='sample_image/noback.png';//워터마크에 사용할 파일, 투명

$path_400X0_file = 'sample_image/test_400X0.jpg';//원본파일을 너비 400으로 정비율 리사이즈



//원본을 너비 400 정비율 리사이즈, $path_400X0_file 에 기본 저장 옵션
$save_w = 400;

$result = thumnail_test1($path_src_file, $path_400X0_file, $save_w);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
너비 $save_w 으로 정비율 리사이즈 <br />
<img src='$path_400X0_file'> <br /><br />
";
flush();



//$path_400X0_file을 너비 300 정비율 리사이즈, 불투명 워터마크 사용
$save_w = 300;
$save_h = 0;

$options = Array();//옵션설정

$options['watermark_path_file'] = $path_mark_file1;//워터마크 이미지
$options['watermark_sharpness'] = 50;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_1.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
너비 $save_w 으로 정비율 리사이즈, 불투명 워터마크 사용 <br />
<img src='$path_save_file'> <br /><br />
";
flush();



//$path_400X0_file을 너비 300 정비율 리사이즈, 투명 워터마크 사용
$save_w = 300;
$save_h = 0;

$options = Array();//옵션설정

$options['watermark_path_file'] = $path_mark_file2;//워터마크 이미지
$options['watermark_sharpness'] = 100;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_2.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
너비 $save_w 으로 정비율 리사이즈, 투명 워터마크 사용 <br />
<img src='$path_save_file'> <br /><br />
";
flush();



//$path_400X0_file을 높이 300 정비율 리사이즈, 불투명 워터마크 사용
$save_w = 0;
$save_h = 300;

$options = Array();//옵션설정

$options['watermark_path_file'] = $path_mark_file1;//워터마크 이미지
$options['watermark_sharpness'] = 50;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_1.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
높이 $save_h 으로 정비율 리사이즈, 불투명 워터마크 사용 <br />
<img src='$path_save_file'> <br /><br />
";
flush();



//$path_400X0_file을 높이 300 정비율 리사이즈, 투명 워터마크 사용
$save_w = 0;
$save_h = 300;

$options = Array();//옵션설정

$options['watermark_path_file'] = $path_mark_file2;//워터마크 이미지
$options['watermark_sharpness'] = 100;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_2.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
높이 $save_h 으로 정비율 리사이즈, 투명 워터마크 사용 <br />
<img src='$path_save_file'> <br /><br />
";
flush();



//$path_400X0_file을 너비 300, 높이 300 강제 리사이즈, 불투명 워터마크 사용
$save_w = 300;
$save_h = 300;

$options = Array();//기본옵션
$options['watermark_path_file'] = $path_mark_file1;//워터마크 이미지
$options['watermark_sharpness'] = 50;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_1.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
너비 $save_w, 높이 $save_h 강제 리사이즈 <br />
<img src='$path_save_file'> <br /><br />
";
flush();



//$path_400X0_file을 너비 300, 높이 300 강제 리사이즈, 투명 워터마크 사용
$save_w = 300;
$save_h = 300;

$options = Array();//기본옵션
$options['watermark_path_file'] = $path_mark_file2;//워터마크 이미지
$options['watermark_sharpness'] = 100;
$options['watermark_pos'] = 10;

$path_save_file = 'sample_image/test_' . $save_w . 'X' . $save_h . '_2.jpg';

$result = thumnail_test1($path_400X0_file, $path_save_file, $save_w, $save_h, $options);
if (empty($result)) die($GLOBALS['errormsg'] . "<br />\n");

echo "
너비 $save_w, 높이 $save_h 강제 리사이즈 <br />
<img src='$path_save_file'> <br /><br />
";
flush();

?>

[출처 : PHPSCHOOL. 유창화님]