Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recreated png image is black

example image

Note : SO has converted the above reference image to jpeg. Here is the transparent PNG.


Following is an example code which recreates a png image on a new canvas and preserves the transparency. As you can see, it also allows pixel level manipulation eg. with a custom function like custom_func($r, $g, $b), which is illustrated better at the bottom of this question.

Basically this code recreates/redraws the above image on a new canvas successfully as it is. Please note, that sky is completely transparent in the above image.

    $image = imagecreatefrompng('grass.png');

    $x_dimension = imagesx($image);
    $y_dimension = imagesy($image);
    $new_image = imagecreatetruecolor($x_dimension, $y_dimension);

    // create a transparent canvas
   $trans_color = imagecolorallocatealpha($new_image, 0x00, 0x00, 0x00, 127);
   imagefill($new_image, 0, 0, $trans_color);

     for ($x = 0; $x < $x_dimension; $x++) {
          for ($y = 0; $y < $y_dimension; $y++) {
          $rgb = imagecolorat($image, $x, $y);
          $r = ($rgb >> 16) & 0xFF;
          $g = ($rgb >> 8) & 0xFF;
          $b = $rgb & 0xFF;
          $alpha = ($rgb & 0x7F000000) >> 24;
          //$pixel = custom_function($r, $g, $b);
          imagesetpixel($new_image, $x, $y, imagecolorallocatealpha($image, $r, $g, $b, $alpha));
      }
      }
     imagesavealpha($new_image, true);
     imagepng($new_image, 'grass-result.png');

However when I run the same code on this particular png image below.

problematic png image

It gives me an almost black image like this.

very dark blue - almost black recreated image


I would like to understand what is happening here and why ? Most importantly, I would like to know about possible factors that could influence the process, so I could look into it. Why is it that the result differs from one png to another ?

Ideally, I would like my code to be able to preserve and transfer the transparency state ( transparent, semi-transparent or opaque ) of the source png image, as it is, to the recreated image. As you can see, I have been able to achieve it, except for the case above.


Just in case, here is my environment. Windows 7 - 64 bit ** Wampserver2.5 ** Apache-2.4.9 ** Mysql-5.6.17 ** php5.5.12-64b. Also here is a var_dump of the image with getimagesize() :

array (size=6)
  0 => int 228
  1 => int 230
  2 => int 3
  3 => string 'width="228" height="230"' (length=24)
  'bits' => int 8
  'mime' => string 'image/png' (length=9)

UPDATE Here is the proof that the example image is indeed transparent and also that it can be manipulated, while keeping the transparency. Notice the bottom of the image is more brownish now. This was achieved by a slight modification of this line imagesetpixel($new_image, $x, $y, imagecolorallocatealpha($image, 100, $g, $b, $alpha));

manipulated transparent image

like image 620
gurung Avatar asked Nov 09 '22 03:11

gurung


1 Answers

Your second image is 8-bit, meaning it only supports a maximum of 256 colours. This makes it a 'palette-based' image and as such it doesn't support alpha transparency.

By simply adding the following line after creating $image you can fix the problem:

imagepalettetotruecolor($image);

This doesn't have any impact on images that are already true colour, so grass.png continues to be processed correctly. From the PHP manual page:

Returns TRUE if the conversion was complete, or if the source image already is a true color image, otherwise FALSE is returned.

like image 200
timclutton Avatar answered Nov 15 '22 12:11

timclutton