Skip to content

Instantly share code, notes, and snippets.

@miguelfrmn
Last active May 9, 2023 11:23
Show Gist options
  • Star 62 You must be signed in to star a gist
  • Fork 33 You must be signed in to fork a gist
  • Save miguelfrmn/908143 to your computer and use it in GitHub Desktop.
Save miguelfrmn/908143 to your computer and use it in GitHub Desktop.
SimpleImage PHP Class
<?php
/**
* File: SimpleImage.php
* Author: Simon Jarvis
* Modified by: Miguel Fermín
* Based in: http://www.white-hat-web-design.co.uk/articles/php-image-resizing.php
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
* http://www.gnu.org/licenses/gpl.html
*/
class SimpleImage {
public $image;
public $image_type;
public function __construct($filename = null){
if (!empty($filename)) {
$this->load($filename);
}
}
public function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if ($this->image_type == IMAGETYPE_JPEG) {
$this->image = imagecreatefromjpeg($filename);
} elseif ($this->image_type == IMAGETYPE_GIF) {
$this->image = imagecreatefromgif($filename);
} elseif ($this->image_type == IMAGETYPE_PNG) {
$this->image = imagecreatefrompng($filename);
} else {
throw new Exception("The file you're trying to open is not supported");
}
}
public function save($filename, $image_type = IMAGETYPE_JPEG, $compression = 75, $permissions = null) {
if ($image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image,$filename,$compression);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image,$filename);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image,$filename);
}
if ($permissions != null) {
chmod($filename,$permissions);
}
}
public function output($image_type=IMAGETYPE_JPEG, $quality = 80) {
if ($image_type == IMAGETYPE_JPEG) {
header("Content-type: image/jpeg");
imagejpeg($this->image, null, $quality);
} elseif ($image_type == IMAGETYPE_GIF) {
header("Content-type: image/gif");
imagegif($this->image);
} elseif ($image_type == IMAGETYPE_PNG) {
header("Content-type: image/png");
imagepng($this->image);
}
}
public function getWidth() {
return imagesx($this->image);
}
public function getHeight() {
return imagesy($this->image);
}
public function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = round($this->getWidth() * $ratio);
$this->resize($width,$height);
}
public function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = round($this->getHeight() * $ratio);
$this->resize($width,$height);
}
public function square($size) {
$new_image = imagecreatetruecolor($size, $size);
if ($this->getWidth() > $this->getHeight()) {
$this->resizeToHeight($size);
imagecolortransparent($new_image, imagecolorallocate($new_image, 0, 0, 0));
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
imagecopy($new_image, $this->image, 0, 0, ($this->getWidth() - $size) / 2, 0, $size, $size);
} else {
$this->resizeToWidth($size);
imagecolortransparent($new_image, imagecolorallocate($new_image, 0, 0, 0));
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
imagecopy($new_image, $this->image, 0, 0, 0, ($this->getHeight() - $size) / 2, $size, $size);
}
$this->image = $new_image;
}
public function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getHeight() * $scale/100;
$this->resize($width,$height);
}
public function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagecolortransparent($new_image, imagecolorallocate($new_image, 0, 0, 0));
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
public function cut($x, $y, $width, $height) {
$new_image = imagecreatetruecolor($width, $height);
imagecolortransparent($new_image, imagecolorallocate($new_image, 0, 0, 0));
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
imagecopy($new_image, $this->image, 0, 0, $x, $y, $width, $height);
$this->image = $new_image;
}
public function maxarea($width, $height = null) {
$height = $height ? $height : $width;
if ($this->getWidth() > $width) {
$this->resizeToWidth($width);
}
if ($this->getHeight() > $height) {
$this->resizeToheight($height);
}
}
public function minarea($width, $height = null) {
$height = $height ? $height : $width;
if ($this->getWidth() < $width) {
$this->resizeToWidth($width);
}
if ($this->getHeight() < $height) {
$this->resizeToheight($height);
}
}
public function cutFromCenter($width, $height) {
if ($width < $this->getWidth() && $width > $height) {
$this->resizeToWidth($width);
}
if ($height < $this->getHeight() && $width < $height) {
$this->resizeToHeight($height);
}
$x = ($this->getWidth() / 2) - ($width / 2);
$y = ($this->getHeight() / 2) - ($height / 2);
return $this->cut($x, $y, $width, $height);
}
public function maxareafill($width, $height, $red = 0, $green = 0, $blue = 0) {
$this->maxarea($width, $height);
$new_image = imagecreatetruecolor($width, $height);
$color_fill = imagecolorallocate($new_image, $red, $green, $blue);
imagefill($new_image, 0, 0, $color_fill);
imagecopyresampled( $new_image,
$this->image,
floor(($width - $this->getWidth())/2),
floor(($height-$this->getHeight())/2),
0, 0,
$this->getWidth(),
$this->getHeight(),
$this->getWidth(),
$this->getHeight()
);
$this->image = $new_image;
}
}
// Usage:
// Load the original image
$image = new SimpleImage('lemon.jpg');
// Resize the image to 600px width and the proportional height
$image->resizeToWidth(600);
$image->save('lemon_resized.jpg');
// Create a squared version of the image
$image->square(200);
$image->save('lemon_squared.jpg');
// Scales the image to 75%
$image->scale(75);
$image->save('lemon_scaled.jpg');
// Resize the image to specific width and height
$image->resize(80,60);
$image->save('lemon_resized2.jpg');
// Resize the canvas and fill the empty space with a color of your choice
$image->maxareafill(600,400, 32, 39, 240);
$image->save('lemon_filled.jpg');
// Output the image to the browser:
$image->output();
@fxvizer
Copy link

fxvizer commented Jan 21, 2013

function cutFromCenter($width, $height){
if($width < $this->getWidth() && $width > $height){
$this->resizeToWidth($width);
}
if($height > $this->getHeight() && $width < $height){
$this->resizeToHeight($height);
}

Do not know why we need these operations, but these definitely can cause unexpected behaviour like adding black paddings around the cutted image. These lines makes more sence for me:

function cutFromCenter($width, $height){

if($width > $this->getWidth()){

$this->resizeToWidth($width);

}

if($height > $this->getHeight()){

$this->resizeToHeight($height);

}

@claviska
Copy link

I'm just gonna throw this out there, since I found your class after someone got it confused with mine: https://github.com/claviska/SimpleImage

The reason I'm posting it is because mine supports quite a bit more of GD's built-in functionality, as well as method chaining which is handy. We could probably work together to incorporate additional functionality as needed :)

@J4Numbers
Copy link

Found this earlier and started messing with it, you might want to add a round() function around the values for $width and $height in the alternate resizeTo... functions.

@OndrejSmisek
Copy link

I have a small improvement for the resizeToHeight() and resizeToWidth() functions:

function resizeToHeight($height)
{
    if ($height < $this -> getHeight())
    {
        $ratio = $height / $this -> getHeight();
        $width = $this -> getWidth() * $ratio;
        $this -> resize($width, $height);
    }
}
function resizeToWidth($width)
{
    if ($width < $this -> getWidth())
    {
        $ratio = $width / $this -> getWidth();
        $height = $this -> getHeight() * $ratio;
        $this -> resize($width, $height);
    }
}

@miguelfrmn
Copy link
Author

Great suggestion m477h3w1012, I just added a round() around the width and height.

@miguelfrmn
Copy link
Author

OndrejSmisek, there may be times when I want to resize even if the image is smaller than the target size. The image will be pixelated of course.

@jorgechavz
Copy link

I use your library in almost all my projects, I just wanted to leave this comment and say, thank you

@mortenyde
Copy link

Thanks for this great script!

I only got one question - Is it just me, or does resizing break png transparency?
Resizing png turns my images completely black.

@ritchiedalto
Copy link

Shouldn't you close the "" before "// Usage:" ?

@jason-engage
Copy link

Please add a watermarking function!

@gnzandrs
Copy link

Just what i was looking for. thanks dude!

@galenteryan
Copy link

Hi there, here is the watermark function

function watermark ($right, $bottom, $watermark_url = 'watermark.png') {

    $new_image = imagecreatetruecolor($this->getWidth(), $this->getHeight());

    $watermark = imagecreatefrompng($watermark_url);

    $x = imagesx($watermark);
    $y = imagesy($watermark);

    imagecopy ($this->image, $watermark,
                      imagesx($this->image) - $x - $right,
                      imagesy($this->image) - $y - $bottom,
                      0, 0,
                      imagesx($watermark),
                      imagesy($watermark)
    );

}

but we must clear this - imagealphablending($new_image, false);
from function "cut" and it works

@galenteryan
Copy link

And i was added one more function

public function crop($width, $height) {

    $ratio_source = $this->getWidth() / $this->getHeight();
    $ratio_dest = $width / $height;

    if ($ratio_dest < $ratio_source) {
        $this->resizeToHeight($height);
    } else {
        $this->resizeToWidth($width);
    }

    $x = ($this->getWidth() / 2) - ($width / 2);
    $y = ($this->getHeight() / 2) - ($height / 2);

    return $this->cut($x, $y, $width, $height);

}

it crops symmetrically

@galenteryan
Copy link

And remove this - imagealphablending($new_image, false);
from resize function

@hakkatil
Copy link

hakkatil commented May 5, 2015

When I upload png files, it replaces the transparant background with black background. Is there a way to fix this? Thank you

@hakkatil
Copy link

hakkatil commented May 5, 2015

Never mind. I found it.
if ($ext == 'jpg' || $ext == 'jpeg' || $ext == 'JPG' || $ext == 'JPEG'){
$imagetype = 'IMAGETYPE_JPEG';
} else if($ext[1] == gif'){
$imagetype = 'IMAGETYPE_GIF';
} else if ($ext[1] == 'png'){
$imagetype = 'IMAGETYPE_PNG';
} else {
$imagetype = 'IMAGETYPE_JPEG';
}
$image->save($destination,$imagetype);

@AlexanderSk
Copy link

In order to save png and gif with white background you need to make the following changes in the save function:

  if( $image_type == IMAGETYPE_JPEG ) {
     imagejpeg($this->image,$filename,$compression);
  } elseif( $image_type == IMAGETYPE_GIF ) {
    $w = $this->getWidth();
    $h = $this->getHeight();
    $new = imagecreatetruecolor($w, $h );
    imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
            imagealphablending($new, false);
            imagesavealpha($new, true);
    imagecopyresampled($new, $this->image, 0, 0, 0, 0, $w, $h, $w, $h );
    imagegif($new,$filename);
  } elseif( $image_type == IMAGETYPE_PNG ) {
    $w = $this->getWidth();
    $h = $this->getHeight();
    $new = imagecreatetruecolor($w, $h );
    imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
            imagealphablending($new, false);
            imagesavealpha($new, true);
    imagecopyresampled($new, $this->image, 0, 0, 0, 0, $w, $h, $w, $h );
    imagepng($new,$filename);
  }
  if( $permissions != null) {
     chmod($filename,$permissions);
  }

}

and for the re size function accordingly:
function resize($width,$height) {
//EDIT
if( $this->image_type == IMAGETYPE_GIF || $this->image_type == IMAGETYPE_PNG) {

    $w = $this->getWidth();
    $h = $this->getHeight();
    $new = imagecreatetruecolor($w, $h );
    imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
            imagealphablending($new, false);
            imagesavealpha($new, true);
    imagecopyresampled($new, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
    $this->image = $new_image;
  }else{ //JPEG //original
        $new_image = imagecreatetruecolor($width, $height);
        imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
        $this->image = $new_image;
  }

}

Tested and worked fine ;)

@mvnp
Copy link

mvnp commented Nov 25, 2015

Hi People ... This not have a crop solution? Very good Work.

@rafikmalek68
Copy link

Hello.
How can i compress gif image without losing animation, i try this code but gif animation lost.
$path = "../../imgs/user/$user_id-$iId.$ext";
if($ext=='gif'){
$tmpImg = new SimpleImage;
$tmpImg->load($path);
$tmpImg->save($path,IMAGETYPE_GIF);
}

How can i compress gif image without losing image animation.

@dmdotin
Copy link

dmdotin commented Jan 15, 2016

I used this function to merge 2 images one by one below.. actually used to add a website name with a small bar below to uploaded picture.. Can we add this code with simpleimage.php ..

function merge($filename_x, $filename_y, $filename_result) {

 // Get dimensions for specified images

 list($width_x, $height_x, $type_x) = getimagesize($filename_x);
 list($width_y, $height_y, $type_y) = getimagesize($filename_y);

 // Create new image with desired dimensions

 $image = imagecreatetruecolor($width_x , $height_x + $height_y);

 // Load images and then copy to destination image
if( $type_x == IMAGETYPE_JPEG ) {
        $image_x = imagecreatefromjpeg($filename_x);
      } elseif( $type_x == IMAGETYPE_GIF ) {
         $image_x = imagecreatefromgif($filename_x);
      } elseif( $type_x == IMAGETYPE_PNG ) {
         $image_x = imagecreatefrompng($filename_x);
      }

if( $type_y == IMAGETYPE_JPEG ) {
    $image_y = imagecreatefromjpeg($filename_y);
  } elseif( $type_y == IMAGETYPE_GIF ) {
     $image_y = imagecreatefromgif($filename_y);
  } elseif( $type_y == IMAGETYPE_PNG ) {
     $image_y = imagecreatefrompng($filename_y);
  }
 //$image_x = imagecreatefromjpeg($filename_x);
 //$image_y = imagecreatefromgif($filename_y);

 imagecopy($image, $image_x, 0, 0, 0, 0, $width_x, $height_x);
 imagecopy($image, $image_y, $height_x, 0, 0, 0, $width_y, $height_y);

 // Save the resulting image to disk (as JPEG)

 imagejpeg($image, $filename_result);

 // Clean up

 imagedestroy($image);
 imagedestroy($image_x);
 imagedestroy($image_y);

}

Copy link

ghost commented Feb 13, 2016

Fix for cutfromcenter - no bars

public function cutFromCenter($width, $height)
 {
        $w = $this->getWidth();  //960
        $h = $this->getHeight(); //310
        $o = $w/$h;
        if ($w < $h && $w > $width)
        { 
            //(original height / original width) x new width = new height
            $after_resize_h = floor(($h / $w) * $width);
            if ($after_resize_h < $height)
               $this->resizeToHeight($height);
            else
               $this->resizeToWidth($width);
        }
        elseif ($w > $h && $h > $height)
        {

           $after_resize_w = floor(($w / $h) * $height);
           if($after_resize_w < $width)
                $this->resizeToWidth($width);
           else
                $this->resizeToHeight($height);
        }

        $x = ($this->getWidth() / 2) - ($width / 2);
        $y = ($this->getHeight() / 2) - ($height / 2);
        return $this->cut($x, $y, $width, $height);
    }

@matheuseduardo
Copy link

function __destruct() {
    if (is_resource($this->image) && 'gd' == get_resource_type($image)) {
        imagedestroy($this->image);
    }
}

@LAGHMARI
Copy link

LAGHMARI commented Mar 7, 2016

Hello,
Thank you for this script.
Can you help me please, I have this error:

Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /home/mywebsite/www/projectFolder/SimpleImage.php on line 22

Thank you

@LeChatNoir69
Copy link

Hi,

When jpg file has exif information, sometimes, orientation is revert while resizing using this class.
In the load function, I've fixed it like this :

function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
$exif = exif_read_data($filename);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$this->image = imagerotate($this->image,90,0);
break;
case 3:
$this->image = imagerotate($this->image,180,0);
break;
case 6:
$this->image = imagerotate($this->image,-90,0);
break;
}
}
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
} elseif( $this->image_type == IMAGETYPE_BMP ) {
$this->image = imagecreatefrombmp($filename);
}

}

@xavianaxw
Copy link

Hi guys.

I was using simpleimage to do some image formatting on my project. Currently I have a setup using resize() which I intend to resize all image to 700x600 pixels. I have manage to setup everything and the project is LIVE'd already but during production, there was a case where the image would resize to 699x600 while the others are all 700x600 thus breaking the layout.

Was wondering if anyone faced this before?

Thanks

@Kurariahunter
Copy link

Kurariahunter commented Dec 15, 2016

I offer a to screen output rather then using headers. Post kepts eating my img tags =( lol

    public function output($image_type = IMAGETYPE_JPEG, $quality = 80)
    {
        if ($image_type == IMAGETYPE_JPEG) {
            //header("Content-type: image/jpeg");
            // start buffering
            ob_start();
            // output jpeg (or any other chosen) format & quality
            imagejpeg($this->image, NULL, 85);
            // capture output to string
            $contents = ob_get_contents();
            // end capture
            ob_end_clean();
            // be tidy; free up memory
            imagedestroy($this->image);
            $data = base64_encode($contents);
            echo '<img src="data:image/jpg;base64,'. $data .'" />';
        } elseif ($image_type == IMAGETYPE_GIF) {
            //header("Content-type: image/gif");
            // start buffering
            ob_start();
            // output gif (or any other chosen) format & quality
            imagegif($this->image);
            // capture output to string
            $contents = ob_get_contents();
            // end capture
            ob_end_clean();
            // be tidy; free up memory
            imagedestroy($this->image);
            $data = base64_encode($contents);
            echo '<img src="data:image/gif;base64,'. $data .'" />';
        } elseif ($image_type == IMAGETYPE_PNG) {
            //header("Content-type: image/png");
            // start buffering
            ob_start();
            // output png (or any other chosen) format & quality
            imagepng($this->image);
            // capture output to string
            $contents = ob_get_contents();
            // end capture
            ob_end_clean();
            // be tidy; free up memory
            imagedestroy($this->image);
            $data = base64_encode($contents);
            echo '<img src="data:image/png;base64,'. $data .'" />';
        }
    }

@crisdany6
Copy link

Hello

I wanted to use this function for my image by downloading the images with file_get_contents

My code does not work
$url=ImageCreateFromString(file_get_contents('http://www.bicivendita.it/WebRoot/registerit3/Shops/990241304/509A/9674/BCB8/5136/52FE/C0A8/8007/4E62/BICICLETTE_DA_CITTA_LEGGERE_DA_UOMO_FUORISERIE.jpg'));
$image = new SimpleImage($url);
It's possible?
Regards

@zaherkh
Copy link

zaherkh commented Jun 12, 2020

Great code. Thanks

@webmavie
Copy link

Hi i added new function text watermark
`function watermark_text($waterMarkText, $font=4, $r=158, $g=158, $b=158) {
$width = imagefontwidth($font) * strlen($waterMarkText) ;

   $height = imagefontheight($font) ;
    
   $image=$this->image;
    
   $x = $this->getWidth() - $width - 10;
    
   $y = $this->getHeight() - $height - 10;
    
   $backgroundColor = imagecolorallocate ($image, 255,255,255);
    
   $textColor = imagecolorallocate ($image, $r,$g,$b);
    
   imagestring ($image, $font, $x, $y, $waterMarkText, $textColor);

   $this->image = $image;

}`

Use:
$img->watermark_text('For Example.com', 8, 215, 13, 213)

@miguel-estevez
Copy link

Miguel, gracias por la librería. Considera incluir la aportación de LeChatNoir69
LeChatNoir69
Perfect fix.
Tks!!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment