PHP의 GDlib imagecopyresampled를 사용할 때 PNG 이미지 투명도를 유지할 수 있습니까?


101

다음 PHP 코드 스 니펫은 GD를 사용하여 브라우저에 업로드 된 PNG의 크기를 128x128로 조정합니다. 제 경우에는 원본 이미지의 투명 영역이 단색 검정으로 대체된다는 점을 제외하면 훌륭하게 작동합니다.

imagesavealpha설정되어 있지만 뭔가 잘못되었습니다.

리샘플링 된 이미지에서 투명도를 유지하는 가장 좋은 방법은 무엇입니까?

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile );    
imagesavealpha( $targetImage, true );

$targetImage = imagecreatetruecolor( 128, 128 );
imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );

답변:


199
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

나를 위해 해냈어. 감사합니다 ceejayoz.

대상 이미지에는 소스 이미지가 아닌 알파 설정이 필요합니다.

편집 : 전체 대체 코드. 아래 답변과 의견도 참조하십시오. 이것은 어떤 식 으로든 완벽하다고 보장되지는 않지만 당시 내 요구를 충족 시켰습니다.

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile ); 

$targetImage = imagecreatetruecolor( 128, 128 );   
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );

5
FIY, 이것은 대상 이미지가 생성 된 이후 여야합니다. 이 경우 imagecreatetruecolor 이후입니다.
RisingSun 2013

alphablending = false여기서 왜 중요한지 궁금 하십니까? 문서에 따르면 ... " imagealphablending($im, false)사용하려면 알파 블렌딩 ( ) 설정을 해제해야 합니다."
eightyfive

2
이 답변은 정확하고 유용 할뿐만 아니라 PHP 문서에 대한 첫 번째 주석 (작성 당시) 이 set되어야한다고 imagecreatefrompng()제안 하기 때문에 특히 유용합니다 . 대단히 감사합니다. imagealphablendingtrue
spikyjt

3
이 솔루션은 내 경우에는 PNG에 주변 투명 영역과 같은 "일반적인"투명 영역이 있고 투명도가있는 이미지의 내부 부분과 같이 복잡한 영역이있는 경우에만 GD가 잘 작동합니다. 항상 실패하고 검은 색 배경이 표시됩니다. 예를 들어이 이미지는 실패합니다 : seomofo.com/downloads/new-google-logo-knockoff.png . 아무도 이것을 시도하고 확인할 수 있습니까?
aesede 2014 년

2
일부 투명한 png 파일에서 작동하지 않는 것 같습니다. jpg에서 이미지를 만들고 내부에 투명한 png를 복사하려고했습니다. aesede가 지적했듯이 결과는 검은 색 사각형입니다.
RubbelDeCatc

21

왜 그렇게 복잡하게 만드나요? 다음은 내가 사용하는 것이며 지금까지 나를 위해 일했습니다.

$im = ImageCreateFromPNG($source);
$new_im = imagecreatetruecolor($new_size[0],$new_size[1]);
imagecolortransparent($new_im, imagecolorallocate($new_im, 0, 0, 0));
imagecopyresampled($new_im,$im,0,0,0,0,$new_size[0],$new_size[1],$size[0],$size[1]);

작동하지 않았습니다.이 이미지로 여전히 검은 색 배경이 나타납니다. seomofo.com/downloads/new-google-logo-knockoff.png
aesede

두 가지 솔루션을 모두 시도했습니다. 귀하와 위의 솔루션은 150 표가 넘었습니다. 솔루션은 GIF에 적합합니다. 위의 파일은 PNG 파일에서 가장 잘 작동하는 반면 솔루션은 축소판을 만들 때 가장 잘 볼 수있는 앤티 앨리어싱을 잃어 버립니다 (블록 모양, 픽셀 화됨).
Jonny

11

나는 이것이 트릭을해야한다고 믿는다.

$srcImage = imagecreatefrompng($uploadTempFile);
imagealphablending($srcImage, false);
imagesavealpha($srcImage, true);

편집 : PHP 문서 주장의 누군가는 imagealphablending거짓이 아니라 참이어야합니다. YMMV.


2
imagealphablendingtrue 또는 false와 함께 사용하면 항상 검정색 배경이 나타납니다.
aesede 2014 년

PHP7 - 나를 위해 작동
Yehonatan

(PHP 7.x) : PNG : imagealphablending ($ targetImage, false); // PNG에서 true 인 경우 : 검정색 배경 GIF : imagealphablending ($ targetImage, true); // GIF에서 거짓 인 경우 : 검정색 배경
Jonny

9

일부 사람들에게 도움이 될 수있는 추가 :

이미지를 빌드하는 동안 이미지 알파 블렌딩을 전환 할 수 있습니다. 저는 이것이 필요한 특정 경우에 투명한 배경에 반투명 PNG를 결합하고 싶었습니다.

먼저 imagealphablending을 false로 설정하고 새로 만든 트루 컬러 이미지를 투명한 색상으로 채 웁니다. imagealphablending이 true이면 투명 채우기가 검정색 기본 배경과 병합되어 검정색이되기 때문에 아무 일도 일어나지 않습니다.

그런 다음 imagealphablending을 true로 전환하고 일부 PNG 이미지를 캔버스에 추가하여 배경의 일부를 표시합니다 (예 : 전체 이미지를 채우지 않음).

그 결과 배경이 투명한 이미지와 여러 개의 결합 된 PNG 이미지가 생성됩니다.


6

JPEG / GIF / PNG와 같은 이미지 크기를 조정하는 기능을 만들었 copyimageresample으며 PNG 이미지는 여전히 투명성을 유지합니다.

$myfile=$_FILES["youimage"];

function ismyimage($myfile) {
    if((($myfile["type"] == "image/gif") || ($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") || ($myfile["type"] == "image/png")) && ($myfile["size"] <= 2097152 /*2mb*/) ) return true; 
    else return false;
}

function upload_file($myfile) {         
    if(ismyimage($myfile)) {
        $information=getimagesize($myfile["tmp_name"]);
        $mywidth=$information[0];
        $myheight=$information[1];

        $newwidth=$mywidth;
        $newheight=$myheight;
        while(($newwidth > 600) || ($newheight > 400 )) {
            $newwidth = $newwidth-ceil($newwidth/100);
            $newheight = $newheight-ceil($newheight/100);
        } 

        $files=$myfile["name"];

        if($myfile["type"] == "image/gif") {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefromgif($myfile["tmp_name"]);
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagegif($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con){
                return true;
            } else {
                return false;
            }
        } else if(($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") ) {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefromjpeg($myfile["tmp_name"]); 
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagejpeg($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con) {  
                return true;
            } else {
                return false;
            }
        } else if($myfile["type"] == "image/png") {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefrompng($myfile["tmp_name"]);
            imagealphablending($tmp, false);
            imagesavealpha($tmp,true);
            $transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127);
            imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent); 
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagepng($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con) {
                return true;
            } else {
                return false;
            }
        }   
    } else
          return false;
}

3
질문의 코드에 대해이 코드에서 투명성이 유지되는 이유를 파악하기 위해 모든 코드를 읽는 것은 다소 번거 롭습니다.
eh9

나는이 두 줄을 건너 뛰고 여전히 작동했습니다. $transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127); imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent);
santiago arizti

이 답변은 stackoverflow.com/a/279310/470749 와 매우 유사 합니다.
Ryan

5

이것이 트릭을 할 수 있다고 생각합니다.

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile );

$targetImage = imagecreatetruecolor( 128, 128 );

$transparent = imagecolorallocate($targetImage,0,255,0);
imagecolortransparent($targetImage,$transparent);
imagefilledrectangle($targetImage,0,0,127,127,$transparent);

imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );

단점은 이미지가 100 % 녹색 픽셀마다 제거된다는 것입니다. 어쨌든 도움이되기를 바랍니다. :)


이미지가 거의 사용되지 않는 매우 추악한 색상으로 설정하면 매우 유용 할 수 있습니다.
Cory

1
받아 들여진 대답은 저에게 효과적이지 않았습니다. 이 대답을 사용하면 imagecreate(...)작동합니다. 할당 한 첫 번째 색상으로 채워지는 이미지를 만듭니다. 그런 다음 해당 색상을 투명으로 설정합니다. 대상 이미지에 대해 alphablending이 true로 설정되면 두 이미지가 병합되고 투명도가 올바르게 작동합니다.
Sumurai8

2

투명도 유지를 다시 변경하면 다른 게시물에서 설명한 것처럼 yes, imageavealpha ()를 true로 설정해야하며, 알파 플래그를 사용하려면 imagealphablending ()을 false로 설정해야합니다. 그렇지 않으면 작동하지 않습니다.

또한 코드에서 두 가지 사소한 점을 발견했습니다.

  1. getimagesize()너비 / 높이를 얻기 위해 호출 할 필요가 없습니다.imagecopyresmapled()
  2. $uploadWidth하고 $uploadHeight있어야한다 -1cordinates의가에서 시작하기 때문에, 값 0이 아니라 1, 하늘의 픽셀에 복사 할 수 있도록. 로 바꾸면 : imagesx($targetImage) - 1and imagesy($targetImage) - 1, 상대적으로해야합니다 :)

0

다음은 전체 테스트 코드입니다. 그것은 나를 위해 작동합니다

$imageFileType = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
$filename = 'test.' . $imageFileType;
move_uploaded_file($_FILES["image"]["tmp_name"], $filename);

$source_image = imagecreatefromjpeg($filename);

$source_imagex = imagesx($source_image);
$source_imagey = imagesy($source_image);

$dest_imagex = 400;
$dest_imagey = 600;
$dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey);

imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey);

imagesavealpha($dest_image, true);
$trans_colour = imagecolorallocatealpha($dest_image, 0, 0, 0, 127);
imagefill($dest_image, 0, 0, $trans_colour);

imagepng($dest_image,"test1.png",1);

0

함수에 전달되는 소스 이미지 widthheight값에 주의하십시오 imagecopyresampled. 실제 소스 이미지 크기보다 크면 나머지 이미지 영역이 검은 색으로 채워집니다.


0

ceejayoz와 Cheekysoft의 답변을 결합하여 가장 좋은 결과를 얻었습니다. imagealphablending () 및 imagesavealpha () 없이는 이미지가 명확하지 않습니다.

$img3 = imagecreatetruecolor(128, 128);
imagecolortransparent($img3, imagecolorallocate($img3, 0, 0, 0));
imagealphablending( $img3, false );
imagesavealpha( $img3, true );
imagecopyresampled($img3, $srcImage, 0, 0, 0, 0, 128, 128, $uploadWidth, $uploadHeight);
imagepng($img3, 'filename.png', 9);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.