⬅ Zurück zur Übersicht

Einfaches Imageresize + Caching

david am Donnerstag, 26.07.2018 - 21:23:52
⬅ Zurück zur Übersicht

Ab und an kommt es vor, dass ein bereits existierendes Bild in einer anderen Größe benötigt wird. Dann kann man entweder mit Photoshop für jede Version des Bildes eine individuell zugeschnittene Version erstellen und diese in die Webseite einbinden (hier bietet sich eventuell Autopush – Einfach geänderte Dateien hochladen an), aber man kann das ganze auch on-the-fly mit einem PHP Skript machen.

Und um die Performance nicht zu sehr leiden zu lassen kann man das ganze auch noch Cachen und somit nur dann das Originalbild zuschneiden, wenn es nicht bereits vorher auf die gewünschte Größe zugeschnitten wurde.

Das alles geht zwar ein bisschen zu Lasten des Speicherplatzes, aber mit der manuellen Version (zuschneiden via Photoshop) wäre das ja nicht anders 😉

Wir benötigen dazu als erstes eine .htaccess Datei, welche unsere .png, .jpg und .jpeg Requests erstmal an ein PHP Skript sendet welches dann die weitere Arbeit macht.
In die .htaccess – Datei kommt folgendes, damit wir bei jeder Bilddatei auch automatisch das PHP Skript durchlaufen:

1
RewriteRule ^(.*)\.(jpg|jpeg|png)/?([0-9]*)?/([0-9]*)?/?([0-1]{1})?$ parse_image.php?i=$1&e=$2&w=$3&h=$4&r=$5 [L,QSA]

Der Pfad zur parse_image.php muss natürlich angepasst werden 😉

Diese HTACCESS – Regel macht nichts anderes, als alle Dateien mit der Endung jpg, jpeg oder png abzufangen und an die parse_image.php weiterzuleiten.
Weiterhin können noch 3 Parameter im Pfad – Stil angegeben werden, welche dann vom PHP Skript verarbeitet werden (siehe unten).
Wenn keine Parameter übergeben werden, wird das „Hauptbild“ aufgerufen ohne weitere Veränderungen.

Die weiteren Parameter sind

Aufrufen können wir das ganze dann also folgendermaßen:

1
<img src="images/040.jpg/100/200/1" />

images/040.jpg ist der Pfad zum Bild, der erste Wert (100) ist die Breite des Ausgabebildes, der zweite (200) die Höhe, der Dritte Wert gibt an ob das Bild proportional skaliert werden soll oder ob einfach die gewünschte Stelle „ausgeschnitten“ wird. Hier ‚1‘ – also wird die Ausgabe proportional skaliert.

Das Skript zum Cachen bzw. zur Ausgabe sieht dann so aus:
Die Konstante „CACHEFOLDER“ muss angepasst werden, und zwar auf einen Ordner auf den PHP Lese- und Schreibzugriff hat (sonst könnten wir das neue Bild ja nicht speichern).

Die Konstante ALLOWED_TYPES gibt als kleines Extraschmankerl‘ noch an, welche Mime – Types zugelassen sind und welche nicht.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Der Ordner, in dem wir die Bilder cachen
define("CACHEFOLDER", "cache/images/");
# Zugelassene Typen - hier jpeg, jpg und png
define("ALLOWED_TYPES", ['image/jpeg', 'image/jpg', 'image/png']);
# Wir beziehen die GET - Variable r (ratio) und speichern je nach dem ein true oder false in unserer $keep_ratio
$keep_ratio = ($_GET['r'] == '1') ? true : false;
# Es werden die GET - Parameter geholt und in Variablen geschrieben. Muss man natürlich nicht machen, macht den ganzen Vorgang aber übersichtlicher
list($file, $ext, $dimensions['w'], $dimensions['h']) = [$_GET['i'], $_GET['e'], isset($_GET['w']) ? $_GET['w'] : 0, isset($_GET['h']) ? $_GET['h'] : 0];
# Es wird ein MD5 - Hash erstellt bestehend aus Dateiname, Zielbreite und Zielhöhe und der Information, ob die Dimensionen erhalten bleiben sollen oder nicht.
$hash = CACHEFOLDER . md5($file.$ext.$dimensions['w'].$dimensions['h'].(($keep_ratio) ? '1' : '0'));
# $file_src enthält den kompletten Pfad zur Originaldatei
$file_src = $file . '.' . $ext;
# Wenn die Originaldatei nicht von einem der o.g. ALLOWED_TYPES ist, brechen wir die Verarbeitung ab (es ist kein png, jpg oder jpeg Bild und höchstwahrscheinlich wurde das Skript direkt aufgerufen)
if (!in_array(mime_content_type($file_src), ALLOWED_TYPES)) die();
# Wenn keine Datei existiert, welche unserem Hash entspricht, dann gibt es keine gecachte Version unseres Bildes und wir erstellen eine.
# Hierzu erstellen wir erst ein jpeg Bild von unserem Originalbild, beziehen die Größe des Bildes und skalieren dann das Bild abhängig von den angegebenen PArametern
if (!file_exists($hash)){
$res['src'] = imagecreatefromjpeg($file_src);
$filedata = getimagesize($file_src);
if ($dimensions['w'] == 0||$dimensions['h'] == 0) list($dimensions['w'], $dimensions['h']) = [$filedata[0], $filedata[1]];
$res['dst'] = imagecreatetruecolor($dimensions['w'], $dimensions['h']);
if ($keep_ratio === false){
imagecopyresized($res['dst'], $res['src'], 0, 0, 0, 0, $dimensions['w'], $dimensions['h'], $filedata[0], $filedata[1]);
}else{
if($filedata[0] &amp;&amp; $filedata[1]) {
$dst['h'] = $dimensions['h'];
$dst['w'] = floor($filedata[0] * ($dimensions['h'] / $filedata[1]));
$crop['x'] = ceil(($filedata[0] - $filedata[1]) / 2);
$crop['y'] = 0; }else{ $dst['w'] = $dimensions['w'];
$dst['h'] = floor($filedata[1] * ($dimensions['w'] / $filedata[0]));
$crop['x'] = 0;
$crop['y'] = ceil(($filedata[1] - $filedata[0]) / 2);
}
imagecopyresampled($res['dst'], $res['src'], 0, 0, $crop['x'], $crop['y'], $dst['w'], $dst['h'], $filedata[0], $filedata[1]);
}
# Schlussendlich geben wir unsere Datei aus.
imagejpeg($res['dst'], $hash); }
header('Content-Type: ' . mime_content_type($hash));
header('Content-Length: ' . filesize($hash));
readfile($hash);
Kommentar schreiben

Kommentare