Thread: Image MIME type

    #1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Posts
    113
    Rep Power
    0

    Image MIME type


    Hello

    I have a class I've been using to resize an image as part of uploading an image and creating a database entry.

    The problem is, some images upload fine, whereas others don't.

    I've narrowed it down to the resize class. It that some of the images I've been testing have the appropriate file extension (PNG, JPEG, JPG, GIF), but when PHP checks the MIME type, the PHP error displayed says the file isn't a valid JPEG, JPG, PNG, GIF file.

    The class I'm using is:

    Code:
    <?php
    /**
     * Resize image class will allow you to resize an image
     *
     * Can resize to exact size
     * Max width size while keep aspect ratio
     * Max height size while keep aspect ratio
     * Automatic while keep aspect ratio
     */
    class ResizeImage
    {
    	private $ext;
    	private $image;
    	private $newImage;
    	private $origWidth;
    	private $origHeight;
    	private $resizeWidth;
    	private $resizeHeight;
    	/**
    	 * Class constructor requires to send through the image filename
    	 *
    	 * @param string $filename - Filename of the image you want to resize
    	 */
    	public function __construct( $filename )
    	{
    		if(file_exists($filename))
    		{
    			$this->setImage( $filename );
    		} else {
    			throw new Exception('Image ' . $filename . ' can not be found, try another image.');
    		}
    	}
    	/**
    	 * Set the image variable by using image create
    	 *
    	 * @param string $filename - The image filename
    	 */
    	private function setImage( $filename )
    	{
    		$size = getimagesize($filename);
    		$this->ext = $size['mime'];
    		switch($this->ext)
    	    {
    	    	// Image is a JPG
    	        case 'image/jpg':
    	        case 'image/jpeg':
    	        	// create a jpeg extension
    	            $this->image = imagecreatefromjpeg($filename);
    	            break;
    	        // Image is a GIF
    	        case 'image/gif':
    	            $this->image = @imagecreatefromgif($filename);
    	            break;
    	        // Image is a PNG
    	        case 'image/png':
    	            $this->image = @imagecreatefrompng($filename);
    	            break;
    	        // Mime type not found
    	        default:
    	            throw new Exception("File is not an image, please use another file type.", 1);
    	    }
    		
    	    $this->origWidth = imagesx($this->image);
    	    $this->origHeight = imagesy($this->image);
    	}
    	/**
    	 * Save the image as the image type the original image was
    	 *
    	 * @param  String[type] $savePath     - The path to store the new image
    	 * @param  string $imageQuality 	  - The qulaity level of image to create
    	 *
    	 * @return Saves the image
    	 */
    	public function saveImage($savePath, $imageQuality="100", $download = false)
    	{
    	    switch($this->ext)
    	    {
    	        case 'image/jpg':
    	        case 'image/jpeg':
    	        	// Check PHP supports this file type
    	            if (imagetypes() & IMG_JPG) {
    	                imagejpeg($this->newImage, $savePath, $imageQuality);
    	            }
    	            break;
    	        case 'image/gif':
    	        	// Check PHP supports this file type
    	            if (imagetypes() & IMG_GIF) {
    	                imagegif($this->newImage, $savePath);
    	            }
    	            break;
    	        case 'image/png':
    	            $invertScaleQuality = 9 - round(($imageQuality/100) * 9);
    	            // Check PHP supports this file type
    	            if (imagetypes() & IMG_PNG) {
    	                imagepng($this->newImage, $savePath, $invertScaleQuality);
    	            }
    	            break;
    	    }
    	    if($download)
    	    {
    	    	header('Content-Description: File Transfer');
    			header("Content-type: application/octet-stream");
    			header("Content-disposition: attachment; filename= ".$savePath."");
    			readfile($savePath);
    	    }
    	    imagedestroy($this->newImage);
    	}
    	/**
    	 * Resize the image to these set dimensions
    	 *
    	 * @param  int $width        	- Max width of the image
    	 * @param  int $height       	- Max height of the image
    	 * @param  string $resizeOption - Scale option for the image
    	 *
    	 * @return Save new image
    	 */
    	public function resizeTo( $width, $height, $resizeOption = 'default' )
    	{
    		switch(strtolower($resizeOption))
    		{
    			case 'exact':
    				$this->resizeWidth = $width;
    				$this->resizeHeight = $height;
    			break;
    			case 'maxwidth':
    				$this->resizeWidth  = $width;
    				$this->resizeHeight = $this->resizeHeightByWidth($width);
    			break;
    			case 'maxheight':
    				$this->resizeWidth  = $this->resizeWidthByHeight($height);
    				$this->resizeHeight = $height;
    			break;
    			default:
    				if($this->origWidth > $width || $this->origHeight > $height)
    				{
    					if ( $this->origWidth > $this->origHeight ) {
    				    	 $this->resizeHeight = $this->resizeHeightByWidth($width);
    			  			 $this->resizeWidth  = $width;
    					} else if( $this->origWidth < $this->origHeight ) {
    						$this->resizeWidth  = $this->resizeWidthByHeight($height);
    						$this->resizeHeight = $height;
    					}
    				} else {
    		            $this->resizeWidth = $width;
    		            $this->resizeHeight = $height;
    		        }
    			break;
    		}
    		$this->newImage = imagecreatetruecolor($this->resizeWidth, $this->resizeHeight);
        	imagecopyresampled($this->newImage, $this->image, 0, 0, 0, 0, $this->resizeWidth, $this->resizeHeight, $this->origWidth, $this->origHeight);
    	}
    	/**
    	 * Get the resized height from the width keeping the aspect ratio
    	 *
    	 * @param  int $width - Max image width
    	 *
    	 * @return Height keeping aspect ratio
    	 */
    	private function resizeHeightByWidth($width)
    	{
    		return floor(($this->origHeight/$this->origWidth)*$width);
    	}
    	/**
    	 * Get the resized width from the height keeping the aspect ratio
    	 *
    	 * @param  int $height - Max image height
    	 *
    	 * @return Width keeping aspect ratio
    	 */
    	private function resizeWidthByHeight($height)
    	{
    		return floor(($this->origWidth/$this->origHeight)*$height);
    	}
    }
    ?>

    Does anyone know how to overcome this? Or is it that the images I've been trying aren't usable?

    Many thanks
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2003
    Posts
    3,553
    Rep Power
    595
    Please enclose your code in [ PHP ] tags. See the sticky at the top of this forum that says READ THIS BEFORE POSTING.

    At a quick glance, your case statement is missing "jpeg". However, you should print $this->ext to make sure you are not getting something unexpected.
    There are 10 kinds of people in the world. Those that understand binary and those that don't.
  4. #3
  5. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Hi,

    the getimagesize() function does not use the file extension to determine the file type. In fact, it ignores the extension completely. It analyzes the first few bytes of the file.

    Anyway, we can't help you without you doing some basic debugging first:

    • Does the error happen with all pictures of a particular type or only certain ones?
    • What's the exact error message?
    • What exactly happens? Does PHP fail to analyze the image altogether? Or is it simply an extension which is not allowed by "your" class?
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Posts
    113
    Rep Power
    0
    Originally Posted by Jacques1
    • Does the error happen with all pictures of a particular type or only certain ones?
    • What's the exact error message?
    • What exactly happens? Does PHP fail to analyze the image altogether? Or is it simply an extension which is not allowed by "your" class?
    • Does the error happen with all pictures of a particular type or only certain ones?

      It appears only to be JPEGS's with the testing I've done so far. Some JPEG's will upload fine, others wont.
    • What's the exact error message?

      Code:
      Warning:  imagecreatefromjpeg() function.imagecreatefromjpeg gd-jpeg: JPEG library reports unrecoverable error:  in /home/bytet231/public_html/includes/imageresize.php on line 43
      
      Warning:  imagecreatefromjpeg() function.imagecreatefromjpeg '/home/bytet231/public_html/myfitfinder.co.uk/images/uploads/31e539dd88097a309661ede469e720dc.jpg' is not a valid JPEG file in /home/bytet231/public_html/myfitfinder.co.uk/includes/imageresize.php on line 43
      
      Warning:  imagesx() expects parameter 1 to be resource, boolean given in /home/bytet231/public_html/myfitfinder.co.uk/includes/imageresize.php on line 45
      
      Warning:  imagesy() expects parameter 1 to be resource, boolean given in /home/bytet231/public_html/myfitfinder.co.uk/includes/imageresize.php on line 46
      There's a load of other error messages too, which I think will be resolved once the above errors are.
    • What exactly happens? Does PHP fail to analyze the image altogether? Or is it simply an extension which is not allowed by "your" class?

      The images I've tested that fail are allowed by the script. I've tested JPG's and PNG (JPG, PNG and GIF are allowed, but I haven't tested GIF as I'm not all that bothered about supporting it). I think PHP is analysing it using imagecreatefromjpeg(), but dismissing it as not being a valid image


    Thanks for your help
  8. #5
  9. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    This definitely isn't a problem of the code. Either the images themselves are broken (looks like it). Or there's an issue with your server setup.

    Try a bunch of fresh JPEG pictures. Try the faulty pictures on another PC (if possible). Try to recover them with an image processing program. If it's obvious that only a few pictures fail while others work perfectly, I'd assume they're simply defective.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Posts
    113
    Rep Power
    0
    It's strange. I tried one of the JPEG's that failed before. Opened it in an image editor, saved it as a PNG, still fails. Took a screenshot of that same image, saved it as a JPEG and PNG, both failed.

    The error I'm getting for the PNG is:

    Code:
    Warning:  imagesx() expects parameter 1 to be resource, boolean given in /home/bytet231/public_html/myfitfinder.co.uk/includes/imageresize.php on line 45
    
    Warning:  imagesy() expects parameter 1 to be resource, boolean given in 
    /home/bytet231/public_html/myfitfinder.co.uk/includes/imageresize.php on line 46
    Last edited by stevenatherton4; November 18th, 2013 at 03:19 PM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2007
    Posts
    113
    Rep Power
    0
    I've just tried 5 new PNG's and 5 JPEG's from Google Images. all 5 of the PNG's failed, whereas only one JPEG failed.

    I thought it might help if I provide the code I'm using to upload the image and process it:

    PHP Code:
    if($_SERVER['REQUEST_METHOD'] == "POST") {
            
            if(!empty(
    $_FILES['uploadedfile']['name'])) {
            require_once(
    "../includes/imageresize.php");
            
    $allowed_filetypes = array('.jpg','.jpeg','.png','.gif');
            
    $max_filesize 10485760;
            
    $upload_path '/home/bytet231/public_html/myfitfinder.co.uk/images/uploads/';
            
    $filename $_FILES['uploadedfile']['name'];
            
    $randomfilename md5(time().$filename);
            
            
    $ext substr($filenamestrpos($filename,'.'), strlen($filename)-1);

            if(!
    in_array($ext,$allowed_filetypes))
                
    $errors[filetype] = 'The file you attempted to upload is not allowed. Only jpg, jpeg, png and gif are allowed.';

            if(
    filesize($_FILES['uploadedfile']['tmp_name']) > $max_filesize)
                
    $errors[size] = 'The file you attempted to upload is too large.';

            if(!
    is_writable($upload_path))
                
    $errors[error] = 'An error occurred while uploading the photo.';
            

            if(
    move_uploaded_file($_FILES['uploadedfile']['tmp_name'],$upload_path $randomfilename $ext)) {
                
                
    $resize = new ResizeImage($upload_path $randomfilename $ext);
                
    $resize->resizeTo(800800'maxWidth');
                
    $resize->saveImage($upload_path $randomfilename $ext);
                
                
    $resize2 = new ResizeImage($upload_path $randomfilename $ext);
                
    $resize2->resizeTo(150150'maxWidth');
                
    $resize2->saveImage($upload_path 'thumbs/' $randomfilename .'_thumb'$ext);
                
                
    $url 'http://www.myfitfinder.co.uk/'.$upload_path.$randomfilename.$ext;
                
    $thumb 'http://www.myfitfinder.co.uk/'.$upload_path.'thumbs/'.$randomfilename.'_thumb'.$ext;

                
                
    $post nl2br($_POST['new_blog_post']);
                
    $title sanitize($_POST['title']);
                
    $date date("l jS \of F Y h:i:s A"time());
                

                if(
    $errors) {
                    foreach(
    $errors as $error) {
                        echo 
    $error;
                    }
                } else {
                    if(
    $username == 'admin') {
                        
    $author 'MyFitFinder';
                    } else {
                        
    $author $username;
                    }
                    
    $query mysql_query("INSERT INTO news_posts (post, title, author_id, author, publish, date, photo, thumb) VALUES('$post', '$title', '$userid', '$author', '0', '$date', '$url', '$thumb') "); 
                }
                
                
                
    $errors[success] = 'Your post <strong>'.$title.'</strong> was saved successfully.';


            } else {
                
    $errors[error] = 'There was an error creating your post <strong>'.$title.'</strong>';
            }
            } else {
                
    $errors[error] = 'You must choose a photo to upload.';
            }
            } 
    and the form:

    Code:
    <form method="POST" action="blog.php" name="new_blog_form" id="new_blog_form" enctype="multipart/form-data" role="form">
    			  <div class="form-group">
    			    <label>Blog Post Title</label>
    				<input class="form-control" name="title" id="title" value="<? echo $_POST['title']; ?>">
                    <p class="help-block">Make it catchy, but not too long.</p>
    				
    				<label>Post Text</label>
    				<textarea class="form-control" rows="6" name="new_blog_post" id="new_blog_post"><? echo $_POST['new_blog_post']; ?></textarea>
    				
    				<label>Main Image</label>
    				<input type="hidden" name="MAX_FILE_SIZE" value="100000">
    				<input type="file" name="uploadedfile" id="uploadedfile">
    				<p class="help-block">Choose a photo to upload.</p>
    				
    				<button type="submit" class="btn btn-default">Submit Post</button>
    				<button type="reset" class="btn btn-default">Clear</button>
    			  </div>
    
                </form>
    Many thanks

IMN logo majestic logo threadwatch logo seochat tools logo