Можно ли сохранить прозрачность изображения PNG при использовании PHP GDlib imagecopyresampled?

Следующий фрагмент кода PHP использует GD для изменения размера загружаемого браузером PNG до 128×128. Он отлично работает, за исключением того, что прозрачные области в исходном изображении заменяются сплошным цветным-черным в моем случае.

Несмотря на то, что 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); 

edit: Кто-то из требований документации к документам PHP, должно быть true, а не false. YMMV.

Это может помочь некоторым людям:

При построении изображения можно переключаться между изображениями. Я конкретный случай, что мне это нужно, я хотел объединить некоторые полупрозрачные PNG на прозрачном фоне.

Сначала вы устанавливаете для изображения false false и заполняете вновь созданное истинное цветное изображение прозрачным цветом. Если было выполнено истинное изображение, то ничего не произойдет, потому что прозрачная заливка будет сливаться с черным фоном по умолчанию и приведет к черному.

Затем вы переключаете изображение с привязки на 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% зеленых пикселей. Во всяком случае, надеюсь, что это поможет 🙂

Регламентируя прозрачность сохранения, тогда да, как указано в других сообщениях, для изображенияaveavealpha () должно быть установлено значение true, чтобы использовать альфа-флаг imagealphablending (), должен быть установлен в false, иначе он не будет работать.

Также я заметил в вашем коде две незначительные вещи:

  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 . Если они больше фактического размера исходного изображения, остальная область изображения будет заполнена черным цветом.