i'm trying to write a little application that lets the users of my site create a little picture of themselves to use as an avatar for the forums. the pictures are made up from a number of .pngs that contain a type of hairstyle or a set of eyes that are merged together using the imagecopy() function.

all the images display correctly (ie. with transparency) before the merging in ie and netscape.

problem is when the images are merged by php they loose their transparency - the transparent pixels are replaced by white ones. which kind of ballses up the stacking effect... 🙁

i'm using photoshop's save for web feature to create the .png's and have tried saving the palette in different orders etc but to no avail.

any ideas?

    I'd suggest opening them and saving in The Gimp as it's png support is better, I think. Next, instead of using built in php functions, use http://www.imagemagick.org/

      Use ImageAlphaBlending() function. But you need to have gd ver 2.0.1 or later. Do it as follows:

      Set the blending mode on for the image on which you are copying the png image with transparency.

      like: ImageAlphaBlending($image, true);
      ImageCopy($image, $png_image, 0, .....);

      This will work, Iam dead sure about that.

        toma42 - you were right. the gimp does have nicer support for .png - and more subtle control for indexing colours imho. the imagemagick suggestion was appreciated but unfortunately is not an option as my website is hosted.

        arun_desh - ImageAlphaBlending() worked a treat. the only problem is that it requires 24 bit .pngs (as they have an alpha channel). internet explorer's lame support for alpha transparency in 24 bit .pngs makes it a bit pointless for the time being.

        a bit of experimenting has revealed that ImageCopyMerge() results in the loss of transparency for both images and ImageCopy() results in the top image overwriting the bottom one but retaining its transparency.

        arrrgh.

        incidentally the code i'm using is a simple (we like simple) modification of a function found on the php online documentation pages that goes something like this:

        function mergePix($sourcefile, $insertfile, $targetfile)
        	{
        	$sourcefile_id = ImageCreateFromPNG($sourcefile);
        	$insertfile_id = ImageCreateFromPNG($insertfile);
        
        ImageCopy($sourcefile_id, $insertfile_id, 0, 0, 0, 0, 50, 75);
        
        ImagePNG($sourcefile_id, $targetfile);
        
        ImageDestroy($sourcefile_id);
        ImageDestroy($insertfile_id);	
        }

        (all images in question being 50x75px and layered directly on top of each other)

        php version 4.2.2
        gd version 2.0 or higher

          right. i've got it to work by going round the houses - starting with a blank 24 bit png (cheers arun_desh) and then converting it to an 8 bit png.

          the code is thus:

          function mergePix($sourcefile, $insertfile, $targetfile)
          	{
          
          // create a 24 bit blank image with a white background
          
          $base =  ImageCreateTrueColor(50, 75);
          $white = ImageColorAllocate($base, 255, 255, 255);
          
          // tell it to respect transparency
          
          ImageAlphaBlending($base, true); 
          
          // get pointers for files to be inserted (both 24 bit images)
          
          $sourcefile_id = ImageCreateFromPNG($sourcefile);
          $insertfile_id = ImageCreateFromPNG($insertfile);	
          
          // insert them.  could use an array and a while loop instead.
          
          ImageCopy($base, $insertfile_id, 0, 0, 0, 0, 50, 75);
          ImageCopy($base, $sourcefile_id, 0, 0, 0, 0, 50, 75);
          
          // convert it all to 8 bit with a 256 colour palette
          
          ImageTrueColorToPalette($base, false, 256);
          
          // loose the white background
          
          $thecolour = ImageColorClosest($base, 255, 255, 255);
          ImageColorTransparent($base, $thecolour);
          
          // save it
          
          ImagePNG($base, $targetfile);
          
          // clean up
          
          ImageDestroy($base);
          ImageDestroy($sourcefile_id);
          ImageDestroy($insertfile_id);
          }

          not very elegant at all. there must be a better way to do this and there probably is but it's gone 5am and i'm off to bed...

            Write a Reply...