How to make the code written for image-resizing workable and optimized for all kinds of image extensions?
Asked Answered
A

2

6

Basically, I'm using PHP and HTML for my website. I'm a newbie to PHP. So I request you to please correct me if I've made any mistake in my code or approach.

I've written code for re-sizing the image uploaded by user to specific size(i.e. specific width and height). I want to make the uploaded image of dimension 940 px * 370 px. But while doing so I want to take care of following issues :

  1. The overall quality of image saved to the server after modification of it's dimensions should be equal as of the image uploaded by user. It shouldn't get shrink or stretch, it's original colors shouldn't get disturbed, etc. All the content of image should be as it is but within the dimensions of 940 px * 370 px.
  2. Black colored background should not be added to the image saved on server.
  3. The code should be workable for all standard image formats. That is if the image uploaded by user is in any of the standard image formats it should get re-sized otherwise not.

So for achieving above functionalities I've written following code :

HTML Code(upload_file.html):

<html>
  <body>
    <form action="upload_file.php" method="post" enctype="multipart/form-data">
      <label for="file">Filename:</label>
      <input type="file" name="file" id="file"><br>
      <input type="submit" name="submit" value="Submit">
    </form>
  </body>
</html>

PHP Code(upload_file.php):

<?php
  $allowedExts = array("gif", "jpeg", "jpg", "png");
  $temp = explode(".", $_FILES["file"]["name"]);
  $extension = end($temp);

  if ((($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/jpg")
    || ($_FILES["file"]["type"] == "image/pjpeg")
    || ($_FILES["file"]["type"] == "image/x-png")
    || ($_FILES["file"]["type"] == "image/png"))
    && ($_FILES["file"]["size"] < 5242880)
    && in_array($extension, $allowedExts)) {
      if ($_FILES["file"]["error"] > 0) {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
      } else {
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
        if (file_exists("upload/upload" . $_FILES["file"]["name"])) {
          echo $_FILES["file"]["name"] . " already exists. ";
        } else {
          //Store the name of the temporary copy of the file stored on the server
          $images = $_FILES["file"]["tmp_name"];         

          /*Create a new file name for uploaded image file :
           *prepend the string "upload" to it's original file name
          */
          $new_images = "upload".$_FILES["file"]["name"];


          //Copies a file contents from one file to another
          //copy($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);

          $width = 940;

          //Determine the size of a given image file and return the dimensions along with the file type 
          $size=GetimageSize($images);

          //$height=round($width*$size[1]/$size[0]);

          $height = 370;

          //Create a new image from file or URL & returns an image identifier representing the image obtained from the given filename.
          $images_orig = ImageCreateFromJPEG($images);

          //Get image width of originally uploaded image
          $photoX = ImagesX($images_orig);

          //Get image height of originally uploaded image
          $photoY = ImagesY($images_orig);

          $scaleX = $width / $photoX;
          $scaleY = $height / $photoY;
          $scale = min($scaleX, $scaleY);

          $scaleW = $scale * $photoX;
          $scaleH = $scale * $photoY;

          /*$width = $scale * $photoX;
          $height = $scale * $photoY;*/

          //Create a new true color image & returns an image identifier representing a black image of the specified size.
          $images_fin = ImageCreateTrueColor($width, $height);

          $background = ImageColorAllocate($images_fin, 0, 0, 0);

          ImageFill($images_fin, 0, 0, $background);

          /*Copy and resize part of an image with resampling
           *copies a rectangular portion of one image to another image, 
           *smoothly interpolating pixel values so that, in particular, 
           *reducing the size of an image still retains a great deal of clarity. 
          */
          /*ImageCopyResampled($images_fin, $images_orig, 0, 0, 0, 0, $width+1, $height+1, $photoX, $photoY);*/
          ImageCopyResampled($images_fin, $images_orig, $width / 2 - $scaleW / 2, $height / 2 - $scaleH / 2, 0, 0, $scaleW+1, $scaleH+1, $photoX, $photoY);

          /*Output image to browser or file
           *creates a JPEG file from the given image.
          */  
          ImageJPEG($images_fin,"upload/".$new_images);

          /*Destroy an image
           *frees any memory associated with image image.  
          */
          ImageDestroy($images_orig);
          ImageDestroy($images_fin);

          echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
        }
      }
    } else {
      echo "Invalid file";
    }
?>

Note : To test the above code and see the uploaded image please create a folder with titled "upload" proper permissions in the same directory where the files upload_file.html and upload_file.php are present.

Actually, the above code is working for me but it has few issues as follows:

  1. It's giving warnings for image files with extensions other than .jpg. It should not happen.
  2. The image is saving to the server after modifications in it's dimensions (940 px * 370px). The quality of image saved to the server is same as of original image uploaded by user but it's adding additional black space in the background to the image. It should not happen.

You can check the code functionality on your local machine by uploading images whose dimensions are higher than 940 px * 370 px and size not greater than 5 MB.

It would be immensely helpful for me if someone could help me in resolving above two issues.

Adopted answered 11/10, 2014 at 6:58 Comment(1)
Didn't Zebra Image library worked for you?Prostyle
H
12

Answer to your first question

It's giving warnings for image files with extensions other than .jpg. It should not happen.

You get warnings because you are opening your image whatever the format using the JPEG-specific function:

// line 48
$images_orig = ImageCreateFromJPEG($images);

To fix this issue, you you can use the generic imagecreatefromstring function, which opens images without taking care of their format.

// line 48
$images_orig = ImageCreateFromString(file_get_contents($images));

Resources:


Answer to your second question

the image is saving to the server after modifications in it's dimensions (940 px * 370px). The quality of image saved to the server is same as of original image uploaded by user but it's adding additional black space in the background to the image. It should not happen.

There are 2 mistakes here:

  • You are resampling your image without specifying that the target gd image should support transparency
  • You are saving the result as JPEG, but JPEG does not support transparency.

You are resampling your image without specifying that the target gd image should support transparency.

To implement it, you should first choose the transparent color in the target image: I am used to use light pink (#FF00FF) as transparent as this is not a common color on images (if you're uploading flowers pics, choose another color :-)). Then, before copying the source image to the target image, set the background color to light pink: the whole image will become transparent instead of black.

Replace:

     // line 67
     $images_fin = ImageCreateTrueColor($width, $height);

     $background = ImageColorAllocate($images_fin, 0, 0, 0);

     ImageFill($images_fin, 0, 0, $background);

By the following lines:

     $images_fin = ImageCreateTrueColor($width, $height);

     $transparent = ImageColorAllocate($images_fin, 255, 0, 255);
     ImageFill($images_fin, 0, 0, $transparent);
     ImageColorTransparent($images_fin, $transparent);

You are saving the result as JPEG, but JPEG does not support transparency.

To fix this issue, just replace:

     // line 31
     $new_images = "upload" . $_FILES["file"]["name"];
     // line 85
     ImageJPEG($images_fin, "upload/" . $new_images);
     // line 93
     echo "Stored in: " . "upload/" . $_FILES["file"]["name"];

By:

     // line 31
     $new_images = "upload" . $_FILES["file"]["name"] . '.png';
     // line 85
     ImagePNG($images_fin, "upload/" . $new_images);
     // line 93
     echo "Stored in: " . "upload/" . $new_images;

Resources:


Your code, with the fixes above

<?php

$allowedExts = array ("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);

if ((($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/jpg") || ($_FILES["file"]["type"] == "image/pjpeg") || ($_FILES["file"]["type"] == "image/x-png") || ($_FILES["file"]["type"] == "image/png")) && ($_FILES["file"]["size"] < 5242880) && in_array($extension,
      $allowedExts))
{
   if ($_FILES["file"]["error"] > 0)
   {
      echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
   }
   else
   {
      echo "Upload: " . $_FILES["file"]["name"] . "<br>";
      echo "Type: " . $_FILES["file"]["type"] . "<br>";
      echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
      echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
      if (file_exists("upload/upload" . $_FILES["file"]["name"]))
      {
         echo $_FILES["file"]["name"] . " already exists. ";
      }
      else
      {
         //Store the name of the temporary copy of the file stored on the server
         $images = $_FILES["file"]["tmp_name"];

         /* Create a new file name for uploaded image file :
          * prepend the string "upload" to it's original file name
          */
         $new_images = "upload" . $_FILES["file"]["name"] . '.png';


         //Copies a file contents from one file to another
         //copy($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);

         $width = 940;

         //Determine the size of a given image file and return the dimensions along with the file type
         $size = GetimageSize($images);

         //$height=round($width*$size[1]/$size[0]);

         $height = 370;

         //Create a new image from file or URL & returns an image identifier representing the image obtained from the given filename.
         $images_orig = ImageCreateFromString(file_get_contents($images));

         //Get image width of originally uploaded image
         $photoX = ImagesX($images_orig);

         //Get image height of originally uploaded image
         $photoY = ImagesY($images_orig);

         $scaleX = $width / $photoX;
         $scaleY = $height / $photoY;
         $scale = min($scaleX, $scaleY);

         $scaleW = $scale * $photoX;
         $scaleH = $scale * $photoY;

         /* $width = $scale * $photoX;
           $height = $scale * $photoY; */

         //Create a new true color image & returns an image identifier representing a black image of the specified size.
         $images_fin = ImageCreateTrueColor($width, $height);
         $transparent = imagecolorallocate($images_fin, 255, 0, 255);
         imagefill($images_fin, 0, 0, $transparent);
         imagecolortransparent($images_fin, $transparent);

         /* Copy and resize part of an image with resampling
          * copies a rectangular portion of one image to another image,
          * smoothly interpolating pixel values so that, in particular,
          * reducing the size of an image still retains a great deal of clarity.
          */
         /* ImageCopyResampled($images_fin, $images_orig, 0, 0, 0, 0, $width+1, $height+1, $photoX, $photoY); */
         ImageCopyResampled($images_fin, $images_orig, $width / 2 - $scaleW / 2, $height / 2 - $scaleH / 2, 0, 0,
            $scaleW + 1, $scaleH + 1, $photoX, $photoY);

         /* Output image to browser or file
          * creates a JPEG file from the given image.
          */
         ImagePNG($images_fin, "upload/" . $new_images);

         /* Destroy an image
          * frees any memory associated with image image.
          */
         ImageDestroy($images_orig);
         ImageDestroy($images_fin);

         echo "Stored in: " . "upload/" . $new_images;
      }
   }
}
else
{
   echo "Invalid file";
}

enter image description here

Huysmans answered 14/10, 2014 at 9:54 Comment(0)
R
0

These are the things that you may want to work on:

  1. To create the image resource you always use the ImageCreateFromJPEG function, that handles only jpeg images, but you have to use the correct function for different types, for example ImageCreateFromPNG.
  2. You save the resulting image in JPEG, but the jpeg format doesn't support transparency. ImagePNG is the right function to use.
  3. You create a solid color for your background. It must be transparent. Edit:here is the relevant part of the code to make it really transparent:

      $images_fin = ImageCreateTrueColor($width, $height);
      imagesavealpha($images_fin, true); 
      $background = ImageColorAllocateAlpha($images_fin, 0x00,0x00,0x00, 127);          
      imagefill($images_fin, 0, 0, $background);
    

Here it is a working version of your code. Keep in mind that you may want to add more cases in the switch statement that takes care of the first problem.

<?php
  $allowedExts = array("gif", "jpeg", "jpg", "png");
  $temp = explode(".", $_FILES["file"]["name"]);
  $extension = end($temp);

  if ((($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/jpg")
    || ($_FILES["file"]["type"] == "image/pjpeg")
    || ($_FILES["file"]["type"] == "image/x-png")
    || ($_FILES["file"]["type"] == "image/png"))
    && ($_FILES["file"]["size"] < 5242880)
    && in_array($extension, $allowedExts)) {
      if ($_FILES["file"]["error"] > 0) {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
      } else {
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
        if (file_exists("upload/upload" . $_FILES["file"]["name"])) {
          echo $_FILES["file"]["name"] . " already exists. ";
        } else {
          //Store the name of the temporary copy of the file stored on the server
          $images = $_FILES["file"]["tmp_name"];         

          /*Create a new file name for uploaded image file :
           *prepend the string "upload" to it's original file name
          */
          $new_images = "upload".$_FILES["file"]["name"];




          //Copies a file contents from one file to another
          //copy($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);

          $width = 940;

          //Determine the size of a given image file and return the dimensions along with the file type 
          $size=GetimageSize($images);

          //$height=round($width*$size[1]/$size[0]);

          $height = 370;

          //Create a new image from file or URL & returns an image identifier representing the image obtained from the given filename.


          switch ($_FILES["file"]["type"]) {
            case '"image/gif"':
               $images_orig = imagecreatefromgif($images);
              break;
            case "image/png":
               $images_orig = ImageCreateFromPNG($images);
              break;
            case "image/jpg":
               $images_orig = ImageCreateFromJPEG($images);
              break;
            #TODO more cases for all the image types you want to support
            default:
              # code to handle other images type.
              break;
          }

          //Get image width of originally uploaded image
          $photoX = ImagesX($images_orig);

          //Get image height of originally uploaded image
          $photoY = ImagesY($images_orig);

          $scaleX = $width / $photoX;
          $scaleY = $height / $photoY;
          $scale = min($scaleX, $scaleY);

          $scaleW = $scale * $photoX;
          $scaleH = $scale * $photoY;

          /*$width = $scale * $photoX;
          $height = $scale * $photoY;*/

          //Create a new true color image & returns an image identifier representing a black image of the specified size.
          $images_fin = ImageCreateTrueColor($width, $height);

          //added these calls to handle transparency.
          imagesavealpha($images_fin, true);     
          $background = ImageColorAllocateAlpha($images_fin, 0x00,0x00,0x00, 127);          
          imagefill($images_fin, 0, 0, $background);

          /*Copy and resize part of an image with resampling
           *copies a rectangular portion of one image to another image, 
           *smoothly interpolating pixel values so that, in particular, 
           *reducing the size of an image still retains a great deal of clarity. 
          */

          ImageCopyResampled($images_fin, $images_orig, $width / 2 - $scaleW / 2, $height / 2 - $scaleH / 2, 0, 0, $scaleW+1, $scaleH+1, $photoX, $photoY);


          /*Output image to browser or file
           *creates a PNG file from the given image.
          */  
          ImagePNG($images_fin,"upload/".$new_images);

          /*Destroy an image
           *frees any memory associated with image image.  
          */
          ImageDestroy($images_orig);
          ImageDestroy($images_fin);

          echo "Stored in: " . "upload/" . $_FILES["file"]["name"];

        }
      }
    } else {
      echo "Invalid file";
    }
?>
Redeemable answered 13/10, 2014 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.