2008-08-28 12 views
90

次のPHPコードスニペットでは、GDを使用してブラウザでアップロードされたPNGのサイズを128x128に変更しています。私の場合、原画像の透明領域が単色の黒に置き換えられている点を除いて、素晴らしい作品です。PHPのGDlib imagecopyresampledを使用しているときに、PNGイメージの透明度を保持できますか?

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); 

答えて

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

ありがとうceejayoz。

メモ、ターゲットイメージにはソースイメージではなく、アルファ設定が必要です。

編集: 完全な置換コード。以下の回答とそのコメントも参照してください。これは決して完璧であるとは保証されませんが、当時の私のニーズを達成しました。

[はいなどの他の記事のimagesavealpha(に記載された、透明性を維持する機密レベル変更
$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); 
+2

は私のために働いていませんでした:( – sandeepKumar

+8

私は可能な場合、これを3回upvoteします。 –

+2

うわー、魅力のように働きました:-) –

9

私は、これはトリックを行う必要があります信じる:

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

編集:PHPのドキュメントで誰かがimagealphablendingが偽、真実ではないべきであると主張しています。 YMMV。

+2

'imagealphablending'をtrueまたはfalseで使用すると、常に黒い背景が表示されます。 – aesede

+0

PHP7 - 私のために働いています – Yehonatan

+0

その周りで遊んで(PHP 7.x): PNG: imagealphablending($ targetImage、false); // PNGの場合:黒の背景 GIF: imagealphablending($ targetImage、true); GIFでfalseの場合:黒い背景 – Jonny

2

)アルファフラグimagealphablendingを(使用するために、trueに設定する必要がありますが)、それは動作しませんそれ以外の場合はfalseに設定する必要があります。

はまた、私はあなたのコードで2つのマイナーなものを発見:

  1. あなたはimagecopyresmapled()
  2. $uploadWidth$uploadHeight以来、-1値である必要がありますのための幅/高さを取得するためにgetimagesize()を呼び出す必要はありません座標は0で始まり、1ではないので、空のピクセルにコピーします。それを次のように置き換えてください:imagesx($targetImage) - 1imagesy($targetImage) - 1は、これと関係しています:
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]); 
+0

私のためにきれいに働きました。小さなnは完璧に動作します.... – user1589754

+0

うまくいかなかった、私はまだこの画像で黒い背景があります:http://www.seomofo.com/downloads/new-google-logo-knockoff。 png – aesede

+1

グーグルで多くのことをしてくれてありがとう、ありがとう –

4

私は、これはトリックを行うかもしれないこととします

$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%緑色の画素を剥奪されるということです。いずれにせよ、それが役に立てば幸い:)

+0

イメージがほとんど使われない非常に醜い色に設定すると、非常に役立ちます。 – Cory

+1

@cory極端に醜い色? –

+1

受け入れられた答えが私のために働かなかった。この答えを 'imagecreate(...)'と一緒に使ってもうまくいきました。イメージを作成します。イメージは、割り当てた最初の色で塗りつぶします。次に、その色を透明に設定します。アルファブレンディングがターゲットイメージに対してtrueに設定されている場合、両方のイメージがマージされ、透明度が正しく機能します。 – Sumurai8

9

何人かの人々を助けるかもしれない追加:イメージを構築しながら

imagealphablendingを切り替えることが可能です。私はこれを必要とする特定のケースで、半透明のPNGを透明な背景に組み合わせたいと思っていました。

まず、imagealphablendingをfalseに設定して、新しく作成したトゥルーカラーイメージを透明な色で塗りつぶします。 imagealphablendingが真の場合、透明な塗りつぶしが黒のデフォルトの背景とマージして黒になるため、何も起こりません。

次に、imagealphablendingをtrueに切り替え、いくつかのPNG画像をキャンバスに追加して、一部の背景を見えるようにします(つまり、画像全体がいっぱいにならないようにします)。

結果は、透明な背景といくつかの結合されたPNG画像を持つ画像です。

+0

この追加情報を追加していただきありがとうございます。これは私を夢中にさせていた。 – zaf

6

私はまだそこに透明性を保つcopyimageresampleとPNG画像をJPEG/GIF/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; 
} 
+1

すべてのコードを読んで、透明性がこのコードの中で問題のコードに保存されている理由を理解することはむしろ面倒です。 – eh9

+0

私はこれら2つの行をスキップし、それでも動作しました: '$ transparent = imagecolorallocatealpha($ tmp、255、255、255、127);' 'imagefilledrectangle($ tmp、0、$ newwidth、$ newheight、 $透明); ' –

0

は私の総テストコードです。これはimagecopyresampled関数に渡されたソース画像のwidthheight値に私

$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

ご注意のために動作します。それらが実際のソースイメージサイズより大きい場合、残りのイメージ領域は黒色で塗りつぶされます。