class.Images.php

Last changes on this page: July 19, 2010

The exemplary hot dog.

A PHP class to rotate, crop and resize images. Can be used to create thumbnails etc.
Eine PHP-Klasse zum Rotieren, Beschneiden und Verändern der Grösse von Bildern.

Yes, I know. It is yet another image manipulation class for PHP. But so far I haven’t found the one that really matches my needs. Either they are too complicated or bound to another system. So I simply created my own class with just the functions I need. So it’s the perfect class for me. If you like it, too – even better! To illustrate what the class can do I’ll use this photo of a hot dog. Hope you’re not hungry!

You’re welcome!

Do you like this class? You’re invited to donate a few bucks.
You know, Thank You Economy and all that stuff…
I promise I won’t get high on it.

Installation

  1. Download source code right here, right now!
  2. That’s it. Get going!

Example

Here’s a basic example of what you can do and this is what you’ll get with it.

require_once("class.Images.php");

//Create a new object, send relative or absolut path to your image
$image = new Image("/path/to/hotdog.jpg");

//Optionally you can set a path to where temporary files shall be saved. If you don't set this path, the class will try to save the temp files in the working directory.
$image->setPathToTempFiles("/path/to/tempfolder");

//We can rotate the image
$image->rotate(90);

//and we can resize and crop it to have a nice thumbnail
$image->resize(150,150,"crop");

//lets see what we have!
$image->display();

Save files

Of course you want to save the new files. Of course you can.

//first same stuff as before
require_once("class.Images.php");
$image = new Image("hotdog.jpg");
$image->setPathToTempFiles("/path/to/tempfolder");
$image->rotate(90);

//Now save the file. First give a filename (without file extension, the class will figure it out!)
//Then, optionally, give path to the folder where you want the image to be saved.
$image->save("newFilename", "../directory/of/save");

//and... oh pretty wow! If the path of the image is accessible to the browser
//you can now even display the whole HTML code of the <img alt="" />-Tag
$image->displayHTML();

Fit, fill or crop

The beauty of the class lies within the resize method. Check this out.

require_once("class.Images.php");

//If you resize an image, the standard value is "fit". This means, your image
//will be resized so it fits within the provided width and height without
//losing its aspect ratio. So what you deliver is basically the maximum
//width and height of the new image, but very likely one side of the
//image will turn out smaller.
$image = new Image("hotdog.jpg");
$image->setPathToTempFiles("/path/to/tempfolder");
$image->resize(300,100);
$image->save("file1");
$image->displayHTML();

//If you set the option "fill" the image will fill the whole width and
//height you provided. But it will loose it aspect ratio. So be ready
//to see your image deformed.
$image = new Image("hotdog.jpg");
$image->setPathToTempFiles("/path/to/tempfolder");
$image->resize(300,100, "fill");
$image->save("file2");
$image->displayHTML();

//If you choose to "crop" the image, it won't lose its aspect ratio but
//parts of the image will be cut off.
$image = new Image("hotdog.jpg");
$image->setPathToTempFiles("/path/to/tempfolder");
$image->resize(300, 100, "crop");
$image->save("file3");
$image->displayHTML();

Crop it like it’s hot

Now, there’s more to cropping! You can choose which part of the original image you want to see on the cropped image. Simply set l, r, or c for left, right or center and b, t or c for bottom, top or center. Go play around, not all combinations make sense for every image. It depends whether the image’s format is landscape or portrait. Here are some examples of our hotdog (by the way, still not hungry?).

//Start at left bottom corner
$image->resize(300, 100, "crop", "l", "b");

//Start at left top corner
$image->resize(300, 100, "crop", "l", "t");

//Start at left side of image, center of height
$image->resize(300, 100, "crop", "l", "c");

Do you two match together?

Let’s say you want your user to upload an image which has an exact aspect ratio of 1:2. How do you check that? Nothing easier than that!

$image = new Image("hotdog.jpg");
if($image->checkRatio(1,2)){
print "Yes, you made it!";
}else{
print "Sorry dude, try again.";
}

All you your knowledge are belong to us

There’s so much to know about an image. Go get some information!

$image = new Image("hotdog.jpg");
print "Width: ".$image->getWidth()."
"
;
print "Height: ".$image->getHeight()."
"
;
print "Extension: ".$image->getExtension()."
"
;
print "Mime: ".$image->getMimeType()."
"
;
print "Type: ".$image->getType()."
"
;
print "Filesize in Bytes: ".$image->getFileSizeInBytes()."
"
;
print "Filesize in kBytes: ".$image->getFileSizeInKiloBytes()."
"
;
print "Filesize readable: ".$image->getFileSize()."
"
;
print "Ratio Width:Height: ".$image->getRatioWidthToHeight()."
"
;
print "Ratio Height:Width: ".$image->getRatioHeightToWidth()."
"
;
print "Is it RGB?: ".$image->isRGB();

//The output:
# Width: 500
# Height: 298
# Extension: jpg
# Mime: image/jpeg
# Type: jpeg
# Filesize in Bytes: 89166
# Filesize in kBytes: 87.076171875
# Filesize readable: 87 KB
# Ratio Width:Height: 1.67785234899
# Ratio Height:Width: 0.596
# Is it RGB?: true

Add watermarks

Added July 19, 2010
Want to protect your image from greedy thieves? Add a watermark to it!

//add the watermark file
$Watermark = $image->addWatermark("anotherImage.png");

//do crazy stuff with it!
//Beware: This may turn out buggy with images with transparency
$Watermark->rotate(45);
$Watermark->resize(50,50,"crop");

//write it in the main image
$image->writeWatermark();

There are several options you can set when writing the watermark, like opacity and position. Have a look at the source code of the class to find out what you can do as I’m being lazy right now :)

Feedback?

That’s it. With this class you can propably cover most of the things you need to do with images. Of course there is much more possible. Go ahead and extend the class. I’ll be more than happy to implement it into the downloads here.

Get in touch: @sprain on Twitter or email me.



Kommentare

  1. christian am 05. Mai 2010 um 15:24 Uhr

    Uh, fremder Code zum Kritisieren. Was gibt’s schöneres?

    Zeile 44: Kennst du tempnam()? :-)

    Zeile 74: Die Funktion könnte doch auch gleich den Array $this->imageInfo zurückgeben.

    Zeile 103: Mit realpath() könntest du auch noch gleich die Existenz des temporären Verzeichnisses testen und den Pfad säubern. Plus dann weisst du, dass das Trailing Slash sicher fehlt, welches du dann mit DIRECTORY_SEPARATOR einfach anhängen kannst.

    Zeile 337: Funktioniert nicht, wenn ein Windows-Pfad mit \ ankommt. Darum eben lieber realpath() benutzen und die Konstante DIRECTORY_SEPARATOR.

    Ab Zeile 281: functions haben keinen private/public-Modifikator mehr.

    Zeile 593: Das ?> schreibt man am Schluss nicht mehr.

    Das Dauerproblem mit den blöden Image-Funktionen (imageCreateFroJPEG()…) hast du elegant gelöst. :-)

    Was für ein Editor macht dir dir ganzen //if und so?

  2. sprain am 05. Mai 2010 um 15:51 Uhr

    @Christian
    Oh cool, danke! Habs gleich angepasst.

    Zeile 44:
    tempnam() kannte ich echt nicht. Ist jetzt eingebaut.

    Zeile 74:
    Dafür nimmst du getImageInfo()

    Zeile 103/337:
    realpath und DIRECTORY_SEPARATOR eingebaut. Du siehst, im Filesystem codiere ich selten :)

    Ab Zeile 281:
    Gingen vergessen, jetzt ergänzt. Danke

    Zeile 593:
    Aber mir gefällt das ?>. Ist für mich auch ein EOF-Zeichen, das File ist komplett, ich hab nix aus Versehen abgeschnitten.

  3. sprain am 05. Mai 2010 um 15:52 Uhr

    @Christan
    Ach ja, der Editor der die //function hinten an die geschweiften Klammern macht heisst sprain :) Hab ich mir einfach angewöhnt.

  4. christian am 05. Mai 2010 um 16:07 Uhr

    Bitte…

    Das mit dem ?> kann dir einfach hässliche Fehler generieren, wenn du hinten noch ein Leerzeichen hast.

    Fürs Ende hättest du ja dein }//class. :-)

    Mal sehen, vielleicht kann ich deine Klass demnächst gut gebrauchen und werde Änderungen zurückmelden.

  5. @dworni am 08. Mai 2010 um 20:25 Uhr

    cool, gut zu wissen, dass es hier ne anständige Bilddingsbums-Klasse gibt. Danke fürs sharen. Und hopp auf Delicious damit… :)

  6. nik am 18. September 2010 um 17:25 Uhr

    Seh ich das richtig, oder lädt displayHTML die Bilder vom absouluten Pfad des Servers ‘/var/htdocs/……/fotos/bild.jpg’?

  7. sprain am 19. September 2010 um 09:55 Uhr

    @nik
    Eigentlich nicht, aber ich schliesse nicht aus, dass da irgend ein Bug besteht. Hast du ein Codebeispiel, wie dies bei dir geschieht?

  8. sprain am 10. November 2010 um 00:07 Uhr

    Heute mit Update! Unter anderem ist das Problem von @nik in vielen Fällen behoben.

  9. nik am 07. Januar 2011 um 02:55 Uhr

    Hallo sprain,
    leider hatte ich die url verloren und auch deine Klasse hab ich nicht mehr gefunden, weil ich in vielen Projekten unterschiedlichste eingesetzt hatte.
    Aber -das ist jetzt keine übertriebene Lobhuddelei- deine Klasse gefällt mir 100mal besser als alles was da draußen so rumläuft und so hab ich meine ganze Festplatte und mehrere files durchsucht, um sie endlich wiederzufinden!
    Umso peinlicher ist es mir, dass ich meinen Kommentar nicht weiterverfolgt habe und dir kein Beispiel geliefert hatte :-( Schande…
    Werd mir gleich mal die aktuelle Version ziehen.
    Liebe Grüße und vielen Dank für deine Mühe!

  10. sprain am 07. Januar 2011 um 12:49 Uhr

    @nik
    Na, dann vielen Dank und willkommen zurück! Ich hoffe, dass es jetzt klappen wird bei dir.

  11. nik am 11. Januar 2011 um 23:58 Uhr

    Hat schon davor geklappt, hatte ein bisschen drin rumgepfuscht…
    Werds mal bei Gelegenheit testen, dann gibts Feedback :-)

  12. Orlando am 17. Januar 2011 um 18:06 Uhr

    Mir ist gerade einen Qualitätsunterschied zwischen einer älteren Version (2010/05/06) und der Aktuellen aufgefallen.

    Wenn ich ein Bild mit der Version vom 2010/05/06 verkleinere ist die Bildqualität gut und sieht so aus http://gabaglio.com/images/2011/schnappschuss_0117173107.jpg , wenn ich das Bild aber mit der aktuellen Version verkleinern hat das Bild Streifen (Sichtbar im Himmel). http://gabaglio.com/images/2011/schnappschuss_0117172718.jpg

    Dies ist wohl nicht beabsichtigt :-)

  13. sprain am 17. Januar 2011 um 18:48 Uhr

    @Orlando
    Kannst du mir das Originalbild und deinen Code zukommen lassen?

  14. Orlando am 17. Januar 2011 um 20:29 Uhr

    @sprain
    Sind per Mail gesendet.

  15. sprain am 24. Januar 2011 um 21:11 Uhr

    @all
    Das “Problem” bei Orli war, dass er mit der Qualitätseinstellung der JPEG-Speicherung gespielt hat, diese im Skript veränderte und sich nicht mehr daran erinnern konnte :) Problem gelöst!

  16. Markus am 28. September 2011 um 09:31 Uhr

    Muss mich zunächst einigen Vorrednern anschließen: Sehr gute Arbeit! Bin begeistert.

    Allerdings habe ich eben ein Problem festgestellt: In der resize-Methode werden im Zweig zu “crop” für den Parameter $cropAreaBottomTop nur die Werte “b” und “c” abgefragt, nicht aber “t”, wie es im Hotdog Beispiel 3 verwendet wird.
    Analog für Parameter $cropAreaLeftRight.

    Oder habe ich was übersehen? Bei mir funktioniert “crop” mit “t” nämlich leider nicht…

  17. Markus am 28. September 2011 um 10:53 Uhr

    Kopf -> Tischplatte.
    Mein Problem war kein Fehler in der Klasse. Die Werte zum Zuschneiden bei “crop” mit “t” bzw. “r” werden ja mit 0 initialisiert, sodass eine extra Abfrage dieser Fälle nicht nötig ist.

    Mein Fehler lag viel mehr am Skript das die Klasse genutzt hat (dort waren die Parameter für resize() falsch gesetzt).

    Unterstreicht nur nochmal meine Meinung aus dem vorherigen Kommentar: große Klasse diese Klasse :)

  18. sprain am 28. September 2011 um 10:55 Uhr

    @Markus
    Schön, wenn sich Probleme von selbst lösen. Also für mich… ;)

  19. Matthias am 17. Januar 2012 um 17:04 Uhr

    Werde mich demnächst mal in den Code ein wenig einlesen.
    Meine Frage vorab: Wie handelt die Klasse Fehler?
    Ist etwas möglich wie:

    if (!$image->resize(300, 100, “crop”)) {

    // if there was an error, let’s see what the error is about
    switch ($image->error) {

    case 1:
    echo ‘Source file could not be found!’;
    break;
    case 2:
    echo ‘Source file is not readable!’;
    break;
    case 3:
    echo ‘Could not write target file!’;
    break;
    case 4:
    echo ‘Unsupported source file format!’;
    break;
    case 5:
    echo ‘Unsupported target file format!’;
    break;
    case 6:
    echo ‘GD library version does not support target file format!’;
    break;
    case 7:
    echo ‘GD library is not installed!’;
    break;

    }

  20. sprain am 17. Januar 2012 um 17:05 Uhr

    @Matthias
    Du darfst soetwas gerne einbauen :)

  21. Matthias am 17. Januar 2012 um 17:07 Uhr

    Na dann schau ich mal, ob ich das demnächst mal hinbekomme ;-)
    Wir suchen aktuell eine gute Image-Klasse für Lepton CMS und diese hier gefällt mir persönlich recht gut…
    Lediglich das Errorhandling muss ich mir eben mal ansehen ;-)

  22. WebBird am 27. Januar 2012 um 12:04 Uhr

    Die Klasse hat die Abstimmung gewonnen und wird nun für LEPTON CMS eingebunden. Gratuliere! Du hast harte Konkurrenz ausgestochen!

    Ich habe eben ein kleines Problem mit readImageInfo() bei einem PNG festgestellt. Dort war der Array-Index “channel” nicht belegt. Korrektur:

    $this->imageInfo["channels"] = ( isset($data["channels"]) ? $data["channels"] : NULL );

    Ich forke das mal bei GitHub und schicke Dir einen Pull Request. Error handling werden wir sicherlich auch noch einbauen.

    Hast Du evtl. auch eine Lösung für das Watermark-Problem bei transparenten Bildern? (Idee im Kopf, aber aus Zeitgründen nicht eingebaut oder so?)

  23. sprain am 30. Januar 2012 um 09:02 Uhr

    @WebBird
    Cool, freut mich!

    Euren Bugfix hab ich gemerged.

    Was das Watermark-Problem angeht hab ich im Moment leider keinen Lösungsansatz auf Lager. Hab mich aber auch schon lange nicht mehr darum gekümmert…

  24. Vibolrith am 19. März 2012 um 16:00 Uhr

    Danke für die gute Arbeit!

  25. WebBird am 27. März 2012 um 14:17 Uhr

    Ich habe bei GitHub einige Änderungen bezüglich der Watermark-Geschichte eingestellt. Kannst Du Dir ja mal angucken.

  26. Shapur am 20. Mai 2012 um 01:28 Uhr

    Very nice and handy class.
    Well done, mate.
    Thanks for sharing the great work.

  27. macwinnie am 30. Mai 2012 um 00:30 Uhr

    Danke für die tolle Klasse, ich verwende sie in verschiedensten meiner Web-Projekte.

    Heute habe ich ein Problem mit transparenten PNGs entdeckt – nach dem Bearbeiten mit deiner Klasse hatten die Bilder alle einen schwarzen Hintergrund. Wahrscheinlich ist das zwar nicht der perfekte Bugfix, aber durch den folgenden Block in Zeile 248 (im “//Let’s get it on, create image!” Block nach der ersten Zeile eingefügt) wird das Problem gelöst:

    if ($image_save_func == “ImagePNG”) {
    imagesavealpha($imageC, true);
    $trans_colour = imagecolorallocatealpha($imageC, 0, 0, 0, 127);
    imagefill($imageC, 0, 0, $trans_colour);
    }

  28. sprain am 30. Mai 2012 um 10:22 Uhr

    @macwinnie
    Danke für den Hinweis. Ich werde dies bei Gelegenheit mal noch näher prüfen.

  29. Jan am 31. Dezember 2012 um 18:37 Uhr

    Hallo,

    vielen Dank für deine Arbeit, prima Sache.

    Ich beiss mir gerade die Zähne an einer bestimmt simplen Sache aus:

    Das Bild soll unter gleichem Namen gespeichert werden.

    Egal was ich mache, immer entsteht
    bild.jpg.jpg

    Habe es auch hiermit versucht:
    $image->save($bild,”$dirname/thumbs/”,”");
    Damit müsste die Klasse doch die Extension “übergehen”?

    (Gut, ich kann ja auch vorher die .jpg wegmachen, aber das ist nicht schön …)

    So, feiert erstmal ins neue Jahr. Die Sache hier hat noch bis morgen Zeit ;-)

    Danke

  30. sprain am 01. Januar 2013 um 19:35 Uhr

    @Jan
    Die Klasse ist darauf ausgelegt, die Extension selbst zu setzen. So wird vermieden, dass eine falschen Extension geschrieben wird.
    Am Besten entfernst du die Extension einfach aus dem Filenamen vor dem Aufrufen der save-Methode.

Kommentar abgeben




Trackbacks