Automatische Bild-Kompression bei Handys

30.12.2010, 00:04

Nicht zuletzt wegen meinem Desire beschäftige ich mich auch mit dem Optimieren von Websites für mobile Endgeräte. Öfters ärgere ich mich über Seiten, die mit grossen Bildern beladen sind und entsprechend lange brauchen, bis sie über das nicht immer schnelle Mobilfunknetz geladen wurden.

Ich suchte also nach einer einfachen Möglichkeit, Bilder ohne viel Aufwand für zu komprimieren, wenn diese über Smartphones und Konsorten abgerufen werden, und den Datentraffic dadurch erheblich zu reduzieren.

Ergeben hat sich folgendes Script: Per .htaccess werden Anfragen von mobilen Endgeräten auf Bilddateien abgefangen und auf ein PHP-Script umgeleitet. Dieses liest die Bilddatei aus und komprimiert sie spürbar, genauer gesagt wird eine JPEG-Grafik mit Qualitätsstufe 35 ausgegeben, gerade genug, um den Inhalt des Bildes zu erkennen. Um bei wiederholtem Zugriff Rechenleistung zu sparen, werden die komprimierten Bilder in einem Cache gespeichert.

Was man dazu braucht, sind das Cache-Verzeichnis img-compress-cache, die .htaccess-Datei und das PHP-Script img-compress.php, alle im Root-Verzeichnis der Domain.

In die .htaccess muss man folgenden Code einfügen:
# image-compress
RewriteCond %{HTTP_USER_AGENT} (iphone|ipod|android|opera\ mini|opera\ mobi|windows\ phone|windows\ ce|palm|blackberry|symbian|series60|samsung|nokia|fennec|/MIDP) [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^[^\?]+\.(png|jpg|jpeg|gif)$ img-compress.php?file=%{REQUEST_URI}

Und das PHP-Script img-compress.php sieht wie folgt aus:
<?php

// Hintergrundfarbe für Transparenz-Ersatz
$bgc = array('r'=>255'g'=>255'b'=>255);
// Cache aktivieren?
$cache_enabled true;

// Pfad einlesen
if(empty($_GET['file']))
    die(
'Fehler: kein Bild angegeben');

$file trim($_GET['file']);

// Root-Slash entfernen
$file preg_replace('#^/+#'''$file);

// "../" unterbinden
$file preg_replace('#\.{2,}/#s'''$file);

// Bild auf Existenz prüfen
if(!file_exists($file)){
    
$file preg_replace('#^[^/]+/#'''$file);
    if(!
file_exists($file)) // 1 VZ tiefer
        
die('Fehler: die Datei existiert nicht');
}

// Cache-Header senden (2592000s = 1 Monat)
header('Expires: '.gmdate('D, d M Y H:i:s'time()+2592000).' GMT');
header('Cache-Control: maxage=2592000');

// Cache prüfen
$cached_file 'img-compress-cache/'.md5($file).'.jpg';
if(
$cache_enabled && file_exists($cached_file)){
    
// jpeg-Header setzen
    
header('Content-Type: image/jpeg');
    
// Datei ausgeben
    
readfile($cached_file);
    
// Script beenden
    
exit;
}

// Endung auslesen
$ext strtolower(strrchr($file'.'));

// Dateigrösse in Bytes
$size filesize($file);

// Grafik einlesen
if($ext==='.png'){
    
// PNG einlesen
    
if($size<2048){
        
// kleine PNG-Grafik nicht jpeggen
        
header('Content-Type: image/png');
        
readfile($file);
        exit;
    }
    
$img = @imagecreatefrompng($file);
}
elseif(
$ext==='.jpg' || $ext==='.jpeg'){
    
// JPG einlesen
    
$img = @imagecreatefromjpeg($file);
}
elseif(
$ext==='.gif'){
    
// GIF einlesen
    
if($size<1024){
        
// kleine GIF-Grafik nicht jpeggen
        
header('Content-Type: image/gif');
        
readfile($file);
        exit;
    }
    
$img = @imagecreatefromgif($file);
}
else{
    die(
'Fehler: Ungültiger Bild-Typ');
}

// Fehler beim Öffnen
if(!$img){
    die(
'Fehler: das Bild ist fehlerhaft');
}


if(
$ext==='.jpg' || $ext==='.jpeg'){
    
// Transparenz-Prozedere ersparen bei jpeg
    
$res $img;
}
else{
    
// Ziel-Grafik mit weissem Hintergrund erstellen (wegen Transparenz)
    
$w imagesx($img);
    
$h imagesy($img);
    
$res imagecreatetruecolor($w$h);
    
$bg imagecolorallocate($res$bgc['r'], $bgc['g'], $bgc['b']);
    
imagefill($res00$bg);
    
// Originalbild kopieren
    
imagecopy($res$img0000$w$h);
    
imagedestroy($img);
}

// jpeg-Header setzen
header('Content-Type: image/jpeg');

// komprimierte jpeg-Grafik ausgeben
imagejpeg($resnull35);

if(
$cache_enabled){
    
// Grafik im Cache speichern
    
imagejpeg($res$cached_file35);
}

?>
 


Andere Einträge