Можно ли сохранить прозрачность изображения в формате PNG при использовании PHP GDlib imagecopyresampled? - PullRequest
95 голосов
/ 28 августа 2008

В следующем фрагменте кода 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 ]

189 голосов
/ 28 августа 2008
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

сделал это для меня. Спасибо ceejayoz.

обратите внимание, целевое изображение нуждается в настройках альфа, а не в исходном изображении.

Edit: полный код замены. Смотрите также ответы ниже и их комментарии. Это никоим образом не гарантирует, что оно будет идеальным, но в то время я действительно достиг своих потребностей.

$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 );
21 голосов
/ 15 ноября 2008

Почему ты делаешь такие сложные вещи? Вот что я использую, и пока он выполнил эту работу за меня.

$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]);
10 голосов
/ 28 августа 2008

Я считаю, что это должно сработать:

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

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

9 голосов
/ 06 января 2011

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

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

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

Затем вы переключаете imagealphablending в true и добавляете несколько изображений PNG на холст, оставляя часть видимого фона (то есть не заполняя все изображение).

В результате получается изображение с прозрачным фоном и несколькими комбинированными изображениями PNG.

6 голосов
/ 11 октября 2011

Я сделал функцию изменения размера изображения, например 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;
}
4 голосов
/ 20 августа 2009

Полагаю, это может помочь:

$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% зеленых пикселей. Во всяком случае, надеюсь, что это помогает:)

2 голосов
/ 01 сентября 2008

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

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

  1. Вам не нужно звонить getimagesize(), чтобы получить ширину / высоту для imagecopyresmapled()
  2. $uploadWidth и $uploadHeight должны быть -1 значением, поскольку кординаты начинаются с 0, а не 1, поэтому он скопирует их в пустой пиксель. Заменив его на: imagesx($targetImage) - 1 и imagesy($targetImage) - 1, релятивно должен сделать:)
0 голосов
/ 12 августа 2018

Я объединил ответы от 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);
0 голосов
/ 07 сентября 2017

Обратите внимание на значения width и height исходного изображения, которые передаются в функцию imagecopyresampled. Если они больше, чем фактический размер исходного изображения, остальная часть изображения будет заполнена черным цветом.

0 голосов
/ 17 июня 2016

Вот мой общий тестовый код. У меня работает

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