PHP htaccess Watermark PNG

I have a PHP script which places a watermark on images on my site.  It exports the images with a content type of JPEG but I'm wondering how I could modify my script so that if the image that the watermark is being placed on could export with a content type of PNG so it doesn't increase the file size of the image.

Here's my code:

<?php
    
    /*
     * This script places a watermark on a given jpeg, png or gif image.
     */
    
      // loads a png, jpeg or gif image from the given file name
      function imagecreatefromfile($image_path) {
        // retrieve the type of the provided image file
        list($width, $height, $image_type) = getimagesize($image_path);
    
        // select the appropriate imagecreatefrom* function based on the determined
        // image type
        switch ($image_type)
        {
          case IMAGETYPE_GIF: return imagecreatefromgif($image_path); break;
          case IMAGETYPE_JPEG: return imagecreatefromjpeg($image_path); break;
          case IMAGETYPE_PNG: return imagecreatefrompng($image_path); break;
          default: return ''; break;
        }
      }
    
      // load source image to memory
      $image = imagecreatefromfile($_GET['image']);
      if (!$image) die('Unable to open image');
    
      // load watermark to memory
      $watermark = imagecreatefromfile($_GET['watermark']);
      if (!$image) die('Unable to open watermark');
    
      // calculate the position of the watermark in the output image (the
      // watermark shall be placed in the lower right corner)
      $watermark_pos_x = imagesx($image) - imagesx($watermark);
      $watermark_pos_y = imagesy($image) - imagesy($watermark);
    
      // merge the source image and the watermark
      imagecopy($image, $watermark,  $watermark_pos_x, $watermark_pos_y, 0, 0,
        imagesx($watermark), imagesy($watermark));
    
      // output watermarked image to browser
      header('Content-Type: image/jpeg');
      imagejpeg($image, '', 85);  // use best image quality (100)
    
      // remove the images from memory
      imagedestroy($image);
      imagedestroy($watermark);
    
    ?>

Open in new window


Not sure if this matters but here's my .htaccess code:
RewriteEngine on
    RewriteRule ^(.*\.(jp?g))$ /videogames/watermark.php?image=$1&watermark=watermark.png [NC]

Open in new window


Thanks.
davideo7Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

designatedinitializerCommented:
try changing this:
 // output watermarked image to browser
      header('Content-Type: image/jpeg');
      imagejpeg($image, '', 85);  // use best image quality (100)

Open in new window


to this:
 // output watermarked image to browser
      header('Content-Type: image/png');
      imagepng($image, '', 100);  // use best image quality (100)

Open in new window

davideo7Author Commented:
designatedinitializer: That actually doesn't work, not sure why but it just doesn't place the watermark on the image when I do that.
designatedinitializerCommented:
sorry about that.
I see now.
The script loads a watermark file with the same file type as the image requested.
You need a little more programming in there.
We must create a new image resource and copy the resulting merged image into it so we can output it as a PNG, regardless of the original file types.
I unindented the lines of code I changed/added:

...
...    
      // merge the source image and the watermark
      imagecopy($image, $watermark,  $watermark_pos_x, $watermark_pos_y, 0, 0, imagesx($watermark), imagesy($watermark));
    
 // create new blank image with the same size as the original
$finalimage = imagecreatetruecolor(imagesx($image), imagesy($image));
// copy merged image to final destination
imagecopy($finalimage, $image, 0,0,0,0,imagesx($image),imagesy($image));

// output watermarked image to browser
header('Content-Type: image/png');
imagepng($finalimage, '', 100);  // use best image quality (100)
    
// remove the images from memory
imagedestroy($finalimage);
      imagedestroy($image);
      imagedestroy($watermark);
...

Open in new window

Protecting & Securing Your Critical Data

Considering 93 percent of companies file for bankruptcy within 12 months of a disaster that blocked access to their data for 10 days or more, planning for the worst is just smart business. Learn how Acronis Backup integrates security at every stage

davideo7Author Commented:
Same thing happened as before.

Here's what my code looks like with your modification, just want to make sure I implemented your modified code properly:

<?php
    
    /*
     * This script places a watermark on a given jpeg, png or gif image.
     */
    
      // loads a png, jpeg or gif image from the given file name
      function imagecreatefromfile($image_path) {
        // retrieve the type of the provided image file
        list($width, $height, $image_type) = getimagesize($image_path);
    
        // select the appropriate imagecreatefrom* function based on the determined
        // image type
        switch ($image_type)
        {
          case IMAGETYPE_GIF: return imagecreatefromgif($image_path); break;
          case IMAGETYPE_JPEG: return imagecreatefromjpeg($image_path); break;
          case IMAGETYPE_PNG: return imagecreatefrompng($image_path); break;
          default: return ''; break;
        }
      }
    
      // load source image to memory
      $image = imagecreatefromfile($_GET['image']);
      if (!$image) die('Unable to open image');
    
      // load watermark to memory
      $watermark = imagecreatefromfile($_GET['watermark']);
      if (!$image) die('Unable to open watermark');
    
      // calculate the position of the watermark in the output image (the
      // watermark shall be placed in the lower right corner)
      $watermark_pos_x = imagesx($image) - imagesx($watermark);
      $watermark_pos_y = imagesy($image) - imagesy($watermark);
    
           // merge the source image and the watermark
      imagecopy($image, $watermark,  $watermark_pos_x, $watermark_pos_y, 0, 0, imagesx($watermark), imagesy($watermark));
    
 // create new blank image with the same size as the original
$finalimage = imagecreatetruecolor(imagesx($image), imagesy($image));
// copy merged image to final destination
imagecopy($finalimage, $image, 0,0,0,0,imagesx($image),imagesy($image));

// output watermarked image to browser
header('Content-Type: image/png');
imagepng($finalimage, '', 100);  // use best image quality (100)
    
// remove the images from memory
imagedestroy($finalimage);
      imagedestroy($image);
      imagedestroy($watermark);
    
    ?>

Open in new window

Ray PaseurCommented:
In my experience, a PNG image is almost always larger than a JPG version of the same image.  PNG has some compression and remains faithful to the original image, and I see that as its largest advantage.  It does not have as much compression as JPG.
Ray PaseurCommented:
David S.Commented:
In my experience, a PNG image is almost always larger than a JPG version of the same image.  PNG has some compression and remains faithful to the original image, and I see that as its largest advantage.  It does not have as much compression as JPG.
Often, yes, but it really depends on the image. One of the biggest factors is the number of colors used in the image. Recently I converted a 54kb JPEG to a 9KB PNG. In that case the image was only using 77 colors, so it could be converted to a PNG-8 (which can use up to 256 colors in the image; in comparison, a PNG-24 can use as many colors as a JPEG).

JPEG is a "lossy" format, while PNG is a "lossless" format (unless of course you reduce an image that used more than 256 colors into a PNG-8). One problem with JPEGs is that each time one is (re-)saved it loses quality.
Ray PaseurCommented:
@Kravimir: Agreed that it depends on the image.  A photographic image is likely to be larger in PNG than a JPG, however many graphic images will be nicely rendered with only 256 colors or less.  As a quick test I took an 8MB JPG photo and saved it in PNG format using Photoshop CS5.  It blew up to 23MB.  (The in-Photoshop memory was 51MB)  Saving photos with 256 colors usually results in posterization.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Apache Web Server

From novice to tech pro — start learning today.