Image uploading and manipulation - GD PART II

A rather common use of GD in webapplications is the use of image resizing. Whenever a website allows you to store some sort of "profile" it usually comes with a image you can upload. Some sites would put restrictions on the dimensions and filesize of your image, others wouldn't be so picky - they'd process the image after upload to ensure it suits the site.

There are mainly two concerns with user uploaded images - we'll address both of them here.
  • Image size
    As this usually is crucial for page design
  • Image proportions
    Whenever resizing an image, proportions gotta match
To start off, a basic upload script (for any file) would look like

<form enctype="multipart/form-data" action="image_upload.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
File: <input name="userfile" type="file" />
<input type="submit" value="Upload" />
</form>
The above form looks like this:
File:


[IMAGE GOES HERE WHEN UPLOADED!]

That'd be all we need for the sending part, on the receiving end however - is where the magic happens. For that we need is a block of code that:
  • Looks for uploaded files
  • Verifies the upload (MIME/size/etc)
  • Reads in the uploaded image
  • Does necessary processing such as resizing
  • Makes use of the result, stores, outputs or something similar.


So I'll begin with the code and I'll follow up with comments on it, i'll use a lot of in-line commenting as well.

TOP OF THE PAGE CONTAINS :
<?
$image_is_aight 
false//yet...
if(isset($_FILES['userfile'])){ //is a file posted and match criterias set?
    
if($_FILES['userfile']['type'] == "image/jpeg" || $_FILES['userfile']['type'] == "image/pjpeg"){
        
$targetdir '/xxx/yyy/zzz/httpd.www/port80/upload/'//upload dir
        
$targetfile $targetdir basename($_FILES['userfile']['name']); //full path

        
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $targetfile)) {
            
//seems valid, lets go on
            
$baseim imagecreatefromjpeg($targetfile);

            
//Sort some work values
            
$orgx imagesx($baseim);
            
$orgy imagesy($baseim);
            
$newx 250;
            
$newy 250;
            
            
//Calculate measuring from biggest value
            //Basic math, I'm crap at it so there's probably better ways..
            
if(imagesx($baseim) > 250 && imagesy($baseim) <= imagesx($baseim)){
                
//cut by width
                
$newy $orgy * ($newx $orgx);
                
$newim imagecreatetruecolor($newx$newy);
                
imagecopyresized($newim$baseim0000$newx$newy$orgx$orgy);
                
imagejpeg($newim,
                    
"/customers/bollibompa.com/bollibompa.com/httpd.www/port80/upload/tmpjpeg.jpg");
                
unlink($targetfile);
            }else if(
imagesy($baseim) > 250){
                
//cut by height
                
$newx $orgx * ($newy $orgy);
                
$newim imagecreatetruecolor($newx$newy);
                
imagecopyresized($newim$baseim0000$newx$newy$orgx$orgy);
                
imagejpeg($newim,
                    
"/customers/bollibompa.com/bollibompa.com/httpd.www/port80/upload/tmpjpeg.jpg");
                
unlink($targetfile);
            }else{
                
//no resizing needed
                
rename($targetfile$targetdir "tmpjpeg.jpg");
            }
            
//finally, flag image is aight ^^
            
$image_is_aight true;
        } else {
            
//invalid, possible attack
        
}
    }
}
?>

MIDDLE OF PAGE CONTAINS :
<?
if($image_is_aight){
?>
    <img src="upload/tmpjpeg.jpg" style="border: 1px solid black" />
<?
}else{
?>
    [IMAGE GOES HERE WHEN UPLOADED!]
<?
}
?>

The code above isn't anything fancy, I know - it's just what can be done with some basic php knowledge and the proper use of a manual. What's fun with it is that - and I've said this earlier - it's so fast and easy to get a fancy result out of things like this.

I'll sure do a part III soon, combining this upload with SAJAX, making image editable and showing instant no-reload results. That'll be fun ^^

EDIT 2007-08-08
Changed <? imagecreate([width], [height]); ?> to <? imagecreatetruecolor([width], [height]); ?> . This was done to make a proper call to GD2 truecolor library to ensures image quality through processing.