Ich hab gerade mal wieder richtig Lust auf einen Nuklearschlag gegen das Microsoft-Hauptquartier. Vor vier Stunden wollte ich noch mal eben schnell ein kleines CSS-Experiment wagen und dann Feierabend machen. Dem IE habe ich es zu verdanken, dass ich erst jetzt darüber schreiben darf und die letzten Stunden ganz schön am basteln war. Aber der Reihe nach.

Das Ziel: Automatisch bessere Qualität bei Client-side Image Resizing

Gestern bin ich via Nico über Client-side Image Resizing gestolpert. Darin geht es darum, wie man durch Browser verkleinerte Bilder (also per height und width-Attribut oder CSS) im IE mit etwas besserer Bildqualität ausstattet. Normale Browser liefern standardmäßig eine anständige Qualität, beim Internet Explorer 6 und 7 muss man da etwas proprietäres CSS auffahren. Andernfalls sehen verkleinerte Bilder so aus:

Normal verkleinerte Bilder

Um das im IE7 zu verbessern, muss man dem Bild die CSS-Eigenschaft -ms-interpolation-mode:bicubic; verpassen und im IE6 das Bild mit dem vom PNG-Fix bekannten AlphaImageLoader laden. Macht man das, kommt das hier dabei heraus:

Sieht doch schon besser aus

Es lohnt sich also. Nur ist es etwas uncool, solchen MS-eigenen Krempel fest einzubauen, also wollte ich die Qualitätsverbesserung mitttels Javascript automatisieren.

Der Code

Dieser Mootools-Code prüft, ob ein Bild verkleinert, vergrößert oder verzerrt ist und wendet dann einen der beiden IE-Fixes an, je nachdem, welcher Browser verwendet wird.

var transparent = 'transparent.gif';
window.addEvent('domready', function(){
	if (Browser.Engine.trident) {
		var version = Browser.Engine.version;
		if (version < 6) {
			var img = $$('#hack img');
			img.each(function(el){
				var tmp = new Element('img', { src: el.get('src') })
				if (el.width != tmp.width || el.height != tmp.height) {
					if (version == 5) {
						el.style.msInterpolationMode = 'bicubic';
					}
					else if (version == 4) {
						el.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + el.get('src') + "',sizingMethod='scale')";
						el.set('src', transparent);
					}
				}
				tmp.destroy();
			});
		}
	}
});

Zur Erläuterung:

  1. Es wird geprüft, ob die IE-Engine Trident verwendet wird (Browser.Engine.trident) und ob wir es mit IE6 oder IE7 zu tun haben (if (version < 6))
  2. Ist das der Fall, werden alle Bilder ausgewählt, die geprüft und ggf. bearbeitet werden sollen (var img = $$('#hack img');)
  3. Von jedem dieser Bilder nehmen wir die Bildadresse und erzeugen damit ein neues <img> ohne festgelegte Maße. Die Größe dieser Kopie wird mit dem Original verglichen; weicht sie ab, werden je nach Trident-Version die proprietären CSS-Attribute in das Original eingefügt. Im Falle des Filters beim IE6 muss außerdem das src des Bildes durch ein komplett transparentes GIF ersetzt werden. Am Ende wird die Kopie wieder zerstört.

Der Code ist auf dieser Demoseite in Aktion zu sehen. Die Bilder in der rechten Spalte wurden vom Script optimiert, die linken sind im Originalzustand.

Und warum der Nuklearschlag?

Es scheint so zu sein, dass der IE7-Fix, das MS-eigene -ms-interpolation-mode, nicht bei jeder Form von Bilddatei funktioniert. Getestet werden kann das auf dieser Seite. Ich bin noch nicht dahinter gekommen was die beiden pngs, die nicht geglättet dargestellt werden, vom Rest unterscheidet. In der Dokumentation steht nichts hilfreiches. Ich weiß nur, dass das erste Bild, mit dem ich experimentiert habe, natürlich eines von denen war, die nicht funktioniert haben. Ohne diese Macke hätte das hier sicher nicht vier Stunden Entstehungszeit in Anspruch genommen.

Falls irgendwer eine Idee hat, was mit den Bildern los sein könnte, nur raus damit!