jQuery: Bilder zuschneiden direkt im Browser

jQuery: Bilder zuschneiden direkt im Browser
Von Lars Ebert am 11.04.11, 19:35
Kategorien: JavaScript, jQuery, PHP, Programmieren and Tutorials

Für die meisten Bildergalerien hat es bisher ausgereicht, wenn ein zufälliger Bildausschnitt als Vorschaubild ausgeschnitten wird. Deshalb war es bisher nicht nötig, dem Nutzer die Möglichkeit zu geben, direkt im Browser einen Bildausschnitt zu wählen. Doch vor kurzem stand ich vor der Aufgabe, für eine junge Fotografin aus Iserlohn eine Bildergalerie zu programmieren. Da die Bilder auf der Internetseite im Vordergrund stehen sollten, mussten sie besser in Szene gesetzt werden.

In diesem Artikel soll es darum gehen, wie man eine Nutzeroberfläche zum Zuschneiden von Bildern realisieren kann. Mit dem JavaScript-Framework jQuery und ein wenig PHP ist dies tatsächlich nicht schwer.

Schritt 1: Die Nutzeroberfläche

An dieser Stelle gehen wir einmal davon aus, dass der Nutzer bereits ein Bild hochgeladen hat. Nun soll ihm eine Oberfläche zum Zuschneiden des Bildes angezeigt werden. Dafür benötigen wir als erstes das jQuery-Plugin jCrop. Dieses Plugin bietet viele Methoden, um eine solche Oberfläche zu erstellen.

Nachdem das Plugin eingebunden wurde, zeigen wir nun das Bild an, dass der Nutzer gerade hochgeladen hat. Da wir nicht wissen, wie groß das Bild ist, skalieren wir das Bild automatisch mit PHP.


<img alt="Bild" src="/slir/w500/bild1.jpg" id="cropimage" />

Noch einmal zur Erläuterung: Hier wird also das Bild »bild1.jpg« angezeigt, allerdings mit einer maximalen Breite von 500 Pixeln. Wichtig ist, dass wir hier dem Bild eine eindeutige ID geben, in diesem Fall »cropimage«.

Damit der Nutzer das zugeschnittene Bild auch speichern kann, fügen wir jetzt noch ein Formular hinzu.


<form action="index.php" method="post">
	<img alt="Bild" src="/slir/w500/bild1.jpg" id="cropimage" />
	<input type="hidden" id="cropimagefield" name="cropimage" />
	<input type="submit" value="Speichern" />
</form>

Das versteckte Feld benutzen wir gleich, um die Koordinaten des Bildausschnittes zu übermitteln. Aber bis jetzt haben wir nichts weiter als ein Bild und einen Submit-Button. Was noch fehlt, ist die Funktionalität, den Bildausschnitt zu wählen. Deshalb fügen wir jetzt ein bisschen JavaScript hinzu.


$(document).ready(function()
{
	$('#cropimage').Jcrop(
	{
		onSelect: function(coords)
		{
			$('#cropimagefield').val(coords.x + ':' + coords.y + ':' + coords.w + ':' + coords.h);
		}
	});
});

Das ist der gesamte JavaScript-Code, den wir brauchen. Die erste Zeile sorgt dafür, dass die Zuschneide-Funktionen erst aktiviert werden, wenn das Bild geladen ist. Mit Jcrop() machen wir das Bild zu einer Auswahl-Oberfläche. Und mit dem onSelect-Event speichern wir beim Ändern der Auswahl die Koordinaten in das versteckte Formularfeld.

Die Auswahl-Oberfläche
Dank JavaScript kann jetzt direkt aus dem Bild ein Ausschnitt gewählt werden.

Nach dem Absenden können die Koordinaten wahlweise gespeichert werden oder an ein Script übergeben werden, welches direkt eine Bilddatei erzeugt. Ich habe mich, um flexibel zu bleiben, für die erste Variante entschieden und speichere die Koordinaten einfach in einer Datenbank.

Schritt 2: Verarbeiten der Auswahl

Was wir jetzt haben sind nichts weiter als eine Hand voll Zahlen. Der nächste Schritt muss sein, aus diesen Koordinaten ein Bild zu erstellen.

Dazu legen wir ein neues Script an, welches wir später einfach im scr-Attribut eines image-Tags verwenden können. Dort können wir per Parameter die Koordinaten der Auswahl übergeben und es wird das zugeschnittene Bild zurückgegeben.

Zur Verdeutlichung hier einmal, wie der Code aussehen könnte, der die Bilddatei ausgibt:


$coords = '74:46:350:233';

list($x, $y, $w, $h) = explode(':', $coords);

echo '<img src="crop.php?image=flower.jpg&amp;x=' . $x . '&amp;y=' . $y . '&amp;w=' . $w . '&amp;h=' . $h . '&amp;tw=200&amp;th=300" alt="Blume" />';

Diesen Aufruf an die Datei crop.php müssen wir jetzt natürlich verarbeiten. Dort wird nun endlich das Bild zugeschnitten und zurückgegeben.


//Gewünschte Größe des Resultats
$targ_w = $_GET['tw'];
$targ_h = $_GET['th'];

//Bildqualität
$jpeg_quality = 90;

//Wo liegt das Bild?
$src = 'pfad/zum/bild/' . $_GET['image'];

//Der Bildausschnitt
$x = $_GET['x'];
$y = $_GET['y'];
$w = $_GET['w'];
$h = $_GET['h'];

//Das Ausgangs- und das Zielbild werden erzeugt
$ausgangsbild = imagecreatefromjpeg($src);
$zielbild = ImageCreateTrueColor($targ_w, $targ_h);

//Nun wird der gewünschte Bildausschnitt aus dem Ausgangsbild ins Zielbild kopiert und dabei auf die richtige Größe skaliert
imagecopyresampled($zielbild, $ausgangsbild, 0, 0, $x, $y, $targ_w, $targ_h, $w, $h);

//Schließlich wird noch das fertige Bild ausgegeben
header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);

exit;

Dieses Script ist im Grunde jetzt schon fertig, allerdings hat es noch einen Schönheitsfehler, der alles durcheinander bringt. Wir blicken noch einmal zurück zur Oberfläche für den Nutzer:


<img alt="Bild" src="/slir/w500/bild1.jpg" id="cropimage" />

Hier wird das Bild, falls es breiter als 500 Pixel ist, auf eine Breite von 500 Pixeln verkleinert. Dadurch beziehen sich in diesem Fall aber auch die Auswahl-Koordinaten auf die verkleinerte Version des Bildes. Also müssen wir diesen Sonderfall noch betrachten, da sonst der Bildausschnitt falsch gewählt wird. Glücklicherweise müssen wir nicht viel an unserem Script ändern:


//Gewünschte Größe des Resultats
$targ_w = $_GET['tw'];
$targ_h = $_GET['th'];

//Bildqualität
$jpeg_quality = 90;

//Wo liegt das Bild?
$src = 'pfad/zum/bild/' . $_GET['image'];

//Wenn das Bild breiter als 500 Pixel ist, müssen wir die Koordinaten korrigieren
if(imagesx($img_r) > 500)
{
	//Um diesen Faktor wurde das Bild skaliert, also müssen die Koordinaten wieder auf die volle Größe zurückgerechnet werden!
	$factor = imagesx($img_r) / 500;
	$x = $_GET['x'] * $factor;
	$y = $_GET['y'] * $factor;
	$w = $_GET['w'] * $factor;
	$h = $_GET['h'] * $factor;
}
else
{
	$x = $_GET['x'];
	$y = $_GET['y'];
	$w = $_GET['w'];
	$h = $_GET['h'];
}

//Das Ausgangs- und das Zielbild werden erzeugt
$ausgangsbild = imagecreatefromjpeg($src);
$zielbild = ImageCreateTrueColor($targ_w, $targ_h);

//Nun wird der gewünschte Bildausschnitt aus dem Ausgangsbild ins Zielbild kopiert und dabei auf die richtige Größe skaliert
imagecopyresampled($zielbild, $ausgangsbild, 0, 0, $x, $y, $targ_w, $targ_h, $w, $h);

//Schließlich wird noch das fertige Bild ausgegeben
header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);

exit;

Und in der Tat wird jetzt der richtige Bildausschnitt angezeigt.

Es wird nur der Ausschnitt gezeigt
Das PHP-Script sorgt dafür, dass aus dem Originalbild der richtige Bildausschnitt gezeigt wird.

Fazit

Wie man sieht, ist es gar nicht so kompliziert, Nutzer beliebige Bildausschnitte aus einem Bild auswählen zu lassen und diese hinterher mit PHP zuzuschneiden. Dank jQuery und seinen unzähligen Plugins ist auch diese Aufgabe zu bewältigen.

Was sagt ihr?

Hättet ihr gedacht, dass es so einfach ist, so eine vermeintlich komplizierte Funktion umzusetzen? Was würdet ihr anders machen? Habt ihr Erfahrung mit dieser oder ähnlichen Techniken? Eure Meinung interessiert mich brennend, also hinterlasst mir doch einen Kommentar!