www

ein Webangebot von rotering-net.de

PHP-Skript: Bildgröße ändern

Bilder müssen für das Web häufig in der Größe angepasst werden, sei es um sie in ein bestimmtes Layout einzupassen oder auch nur um kostbare Bandbreite zu sparen, bspw. wenn es um die Erstellung von Vorschaubildern (sog. Thumbnails) geht. Dies lässt entweder vorab am eigenen Computer bewerkstelligen, aber auch direkt auf dem Webserver mittels einer Skriptsprache. Letzteres wird vor allem dann interessant, wenn auch Externe Bilder auf die Website einbringen sollen. In einem automatisierten Prozess könnte dann zu jedem Bild ein Thumbnail für eine Übersichtsseite erstellt werden.

Das nachfolgende Skript zeigt, wie man die Bildgröße mit Hilfe von PHP anpassen kann. Es erzeugt von einem bereits auf dem Server befindlichen Originalbild ein in Breite und Höhe angepasstes Bild, welches wieder auf dem Server gespeichert wird (das Originalbild wird nicht gelöscht). Das Skript taugt für alle im Web allgemein verbreiteten Bildformate, also JPEG, GIF und PNG, und beachtet insbesondere deren Eigenheiten beim Anpassungsprozess.

Syntax

bool createResizedImage (string $filepath_old, string $filepath_new, int $image_dimension [, int $scale_mode])

  • $filepath_old - Der relative oder absolute Dateipfad zum Originalbild.
  • $filepath_new - Der relative oder absolute Dateipfad unter dem das neue Bild gespeichert werden soll. Beachten Sie, dass PHP Schreibrechte in diesem Verzeichnis benötigt.
  • $image_dimension - Die Dimension des neuen Bildes in der Einheit Pixel. Wie die Dimension interpretiert wird, hängt von $scale_mode ab.
  • $scale_mode (optional) - Modus, in dem die vorherige $image_dimension-Angabe zu interpretieren ist. Mögliche Werte sind:
    • -1 - Die Dimension wird stets als neue Breite des Bildes interpretiert. Die Höhe wird so angepasst, dass das Seitenverhältnis des Bildes erhalten bleibt.
    • -2 - Die Dimension wird stets als neue Höhe des Bildes interpretiert. Die Breite wird so angepasst, dass das Seitenverhältnis des Bildes erhalten bleibt.
    • 0 (standard) - Die Dimension wird als längste Seitenkante des Bildes interpretiert. Die jeweils andere Seitenkante wird stets derart verkleinert, dass das Seitenverhältnis des Bildes erhalten bleibt.
    • 1 - Die Dimension wird als kürzeste Seitenkante des Bildes interpretiert. Die jeweils andere Seitenkante wird stets derart vergrößert, dass das Seitenverhältnis des Bildes erhalten bleibt.

Rückgabewerte: Wurde das modifizierte Bild erfolgreich erstellt, wird true zurückgegeben, andernfalls false.

Skript

<?php function createResizedImage ($filepath_old, $filepath_new, $image_dimension, $scale_mode = 0) { if (!(file_exists($filepath_old)) || file_exists($filepath_new)) return false; $image_attributes = getimagesize($filepath_old); $image_width_old = $image_attributes[0]; $image_height_old = $image_attributes[1]; $image_filetype = $image_attributes[2]; if ($image_width_old <= 0 || $image_height_old <= 0) return false; $image_aspectratio = $image_width_old / $image_height_old; if ($scale_mode == 0) { $scale_mode = ($image_aspectratio > 1 ? -1 : -2); } elseif ($scale_mode == 1) { $scale_mode = ($image_aspectratio > 1 ? -2 : -1); } if ($scale_mode == -1) { $image_width_new = $image_dimension; $image_height_new = round($image_dimension / $image_aspectratio); } elseif ($scale_mode == -2) { $image_height_new = $image_dimension; $image_width_new = round($image_dimension * $image_aspectratio); } else { return false; } switch ($image_filetype) { case 1: $image_old = imagecreatefromgif($filepath_old); $image_new = imagecreate($image_width_new, $image_height_new); imagecopyresampled($image_new, $image_old, 0, 0, 0, 0, $image_width_new, $image_height_new, $image_width_old, $image_height_old); imagegif($image_new, $filepath_new); break; case 2: $image_old = imagecreatefromjpeg($filepath_old); $image_new = imagecreatetruecolor($image_width_new, $image_height_new); imagecopyresampled($image_new, $image_old, 0, 0, 0, 0, $image_width_new, $image_height_new, $image_width_old, $image_height_old); imagejpeg($image_new, $filepath_new); break; case 3: $image_old = imagecreatefrompng($filepath_old); $image_colordepth = imagecolorstotal($image_old); if ($image_colordepth == 0 || $image_colordepth > 255) { $image_new = imagecreatetruecolor($image_width_new, $image_height_new); } else { $image_new = imagecreate($image_width_new, $image_height_new); } imagealphablending($image_new, false); imagecopyresampled($image_new, $image_old, 0, 0, 0, 0, $image_width_new, $image_height_new, $image_width_old, $image_height_old); imagesavealpha($image_new, true); imagepng($image_new, $filepath_new); break; default: return false; } imagedestroy($image_old); imagedestroy($image_new); return true; } ?>

Erläuterungen

Zunächst wird mit Hilfe von file_exists() sichergestellt, dass der Dateipfad zum Originalbild tatsächlich existiert und dass unter dem neuen Dateipfad noch keine Datei existiert, die andernfalls überschrieben werden würde. Sollten Sie dagegen beabsichtigen, eine Datei zu ersetzen, sollten Sie diese vorab löschen. Danach werden mit getimagesize() die Attribute des Originalbildes ermittelt. Da wir bislang nur geprüft haben, ob die Originaldatei existiert, aber nicht, ob es sich dabei überhaupt um ein gültiges Bild handelt, fangen wir den Fall von nicht-positiven Werten für die Höhe und Breite des Bildes ab. Andernfalls würden wir bei den nachfolgenden Berechnungen arge Probleme bekommen.

Um die neuen Abmessungen des Bildes zu bestimmen, ermitteln wir zunächst das Seitenverhältnis von Breite zu Höhe. Abhängig davon und vom gewählten $scale_mode wird nun entschieden, ob $image_dimension als Breite oder Höhe interpretiert werden muss. Dafür wird einfach der $scale_mode auf einen der negativen Optionen umgestellt. Anschließend wird die jeweils andere Seite mit Hilfe des Seitenverhältnisses berechnet.

Nun ist die gesamte Vorarbeit geleistet und das Bild kann angepasst werden. Grundsätzlich muss dazu das Originalbild geladen und im Speicher zusätzlich ein neues leeres Bild mit den neuen Maßen erstellt werden. Anschließend wird das alte Bild auf das neue Bild kopiert. Das pure Verkleinern des Bildes kann mit der Funktion imagecopy() erreicht werden. Damit das Bild überhaupt kleiner wird, müssen jedoch Pixel entfallen. Ein reines Streichen einzelner Pixel führt jedoch nicht zu einer echten Verkleinerung, sondern zu einem Entfernen von Bilddetails, was dem menschlichen Betrachter als Artefakte unangenehm auffällt. Wir benutzen daher die Funktion imagecopyresampled() welche zur Reduktion von Pixeln benachbarte farblich verschmilzt und damit für eine angenehme Verkleinerung sorgt. Abschließend wird das neue Bild wird dann gespeichert. Auch wenn diese Vorgehensweise gleich bleibt, erfordern die verschiedenen Bildformate eine unterschiedliche Prozedur, da sie ihre spezifischen Eigenheiten besitzen. Dies wird häufig übersehen und führt bei vielen Skripten dieser Art daher zu ungewollten Bildstörungen.

Am einfachsten lassen sich die verlustbehafteten JPEG-Bildern handhaben. Ihre Kompression beruht auf dem Entfernen von Details, die das menschliche Auge nicht wahrnehmen kann. Durch die Reduktion der Bildgröße reduzieren wir gleichzeitig die Details, sodass das Bild bei gleicher Qualität noch besser komprimiert werden kann. Wir erhalten das, was wir von einem verkleinertem Bild erwarten: ein kleineres Bild - sowohl was die Abmessungen, als auch die Dateigröße anbelangt.

Bei GIF- und PNG-Bilder beruht die Kompression nicht auf dem Entfernen von Details, sondern auf dem Erkennen von sich wiederholenden Mustern und einer sehr eingeschränkten Farbanzahl. GIF unterstützt von Haus aus nur 256 Farben, weshalb wir hier im Gegensatz zu JPEG auch mit imagecreate() ein Palettenfarbenbild erzeugen müssen. PNG kann sowohl Palettenfarbenbild als auch Echtfarbenbild sein, weshalb wir vorher noch mit imagecolorstotal() die Farbtiefe bestimmen müssen. Bei PNG müssen wir außerdem noch den Alphakanal getrennt sichern, sonst würde er aus dem neuen Bild entfernt.

Bei beiden Formaten ist jedoch festzuhalten, dass sie nicht perfekt verkleinert werden können, da die Anzahl der Farben durch unseren Vekleinerungsprozess zwangsläufig ansteigt. Entweder müssen diese Farben in bereits existierende, naheliegende Farben umgewandelt werden, was zu Artefakten führt, oder aber die zusätzlichen Farben müssen zusätzlich gespeichert werden, wodurch die Kompression schlechter arbeitet als zuvor. Es kann also durchaus der Fall auftreten, dass die Dateigröße eines Vorschaubildes größer wird als die des Originalbildes.