2008-08-28 15 views
90

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

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

ответ

178
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

не работал для меня :( – sandeepKumar 2012-09-10 13:42:47

+8

Я бы поднял это 3 раза, если бы мог. – 2012-09-12 10:50:59

+2

wow, работал как очарование спасибо :-) – 2012-10-10 13:02:10

9

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

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

редактировать: Кто в PHP документации утверждает imagealphablending должно быть истинным, а не ложным. YMMV.

+2

Использование `imagealphablending` либо с истинным, либо с ложным я всегда получаю черный фон. – aesede 2014-09-29 15:17:53

+0

PHP7 - Работа для меня – Yehonatan 2017-01-25 10:59:30

+0

Играли с ним (PHP 7.x): PNG: imagealphablending ($ targetImage, false); // если true в PNG: черный фон GIF: imagealphablending ($ targetImage, true); // если false на GIF: черный фон – Jonny 2017-04-18 12:07:41

2

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

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

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

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

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

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

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

9

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

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

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

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

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

6

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

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

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

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