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

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

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

edit: Кто-то из претензий PHP docs imagealphablending должен быть правдой, а не ложью. YMMV.

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

Я полагаю, что это может сделать трюк:

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

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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