Можно ли сохранить прозрачность изображения PNG при использовании PHP GDlib imagecopyresampled?
следующий фрагмент кода 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 );
10 ответов:
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 docs утверждает
imagealphablending
должно быть true, а не false. МММ.
дополнение, которое может помочь некоторым людям:
можно переключать imagealphablending при построении изображения. Я конкретный случай, что мне это нужно, я хотел объединить некоторые полупрозрачные PNG на прозрачном фоне.
сначала вы устанавливаете imagealphablending в false и заполняете вновь созданное изображение истинного цвета прозрачным цветом. Если бы imagealphablending был истинным, ничего не произошло бы, потому что прозрачная заливка слилась бы с черным фон по умолчанию и результат в черном цвете.
затем вы переключаете 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 иначе это не работает.
также я заметил две мелочи в коде:
- вам не нужно звонить
getimagesize()
чтобы получить ширину/высотуimagecopyresmapled()
- The
$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);
Я объединил ответы от 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);