PHP の GDlib imagecopyresampled を使用する場合、PNG 画像の透明度は維持できますか?

StackOverflow https://stackoverflow.com/questions/32243

質問

次の 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 );
役に立ちましたか?

解決

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

他のヒント

なぜ物事をそんなに複雑にするのですか?以下は私が使用しているもので、これまでのところそれは私にとって仕事をしてくれました。

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

これでうまくいくはずだと思います:

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

編集: PHPドキュメントの誰かが主張しています imagealphablending falseではなく、trueである必要があります。YMMV。

一部の人にとって役立つかもしれない追加:

イメージの構築中にイメージアルファブレンディングを切り替えることができます。これが必要な具体的なケースとしては、透明な背景に半透明の PNG をいくつか組み合わせたいと考えていました。

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

次に、imagealphablending を true に切り替え、いくつかの PNG 画像をキャンバスに追加し、背景の一部を表示したままにします (つまり、画像全体を埋めるわけではありません)。

結果は、透明な背景と複数の PNG 画像が結合された画像になります。

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

これでうまくいくかもしれないと思います:

$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% の緑色のピクセルがすべて削除されることです。とにかく、それが役立つことを願っています:)

透明度の保持を再評価するには、他の投稿で述べたように、imagesavealpha() を true に設定する必要があります。アルファ フラグを使用するには、imagealphablending() を false に設定する必要があります。そうしないと機能しません。

また、コード内に 2 つの小さな点も見つかりました。

  1. 電話する必要はありません getimagesize() 幅/高さを取得するには imagecopyresmapled()
  2. $uploadWidth そして $uploadHeight あるべきです -1 座標は次から始まるので、その値 0 そしてそうではありません 1, 、したがって、それらを空のピクセルにコピーします。これを次のように置き換えます。 imagesx($targetImage) - 1 そして imagesy($targetImage) - 1, 、比較的そうするべきです:)

これが私の全体的なテストコードです。わたしにはできる

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

ソース画像に注意してください width そして height に渡される値 imagecopyresampled 関数。実際のソース画像サイズよりも大きい場合、画像領域の残りの部分は黒色で塗りつぶされます。

ceejayoz と Cheekysoft からの回答を組み合わせたところ、私にとって最良の結果が得られました。imagealphablending() と imageavealpha() がないと、画像は鮮明ではありません。

$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);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top