Можно ли сохранить прозрачность изображения 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 92

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 иначе это не работает.

также я заметил две мелочи в коде:

  1. вам не нужно звонить getimagesize() чтобы получить ширину/высоту imagecopyresmapled()
  2. 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);

обратите внимание на исходное изображение width и height значения, которые передаются в

Я объединил ответы от 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);