Geekeries Javascript

Regardez bien cette image PNG de 29Ko :

prototype png

Outre le fait que ce soit une image en niveaux de gris, la première chose qui saute aux yeux c’est l’aspect aléatoire de la répartition des pixel car cette image contient des données. Ou plus précisément elle a été générée à partir d’un fichier ASCII où chaque caractère est simplement codé/stocké sous forme d’un pixel. Voici le script PHP en question:

$filename = 'prototype-1.6.0.2.packed.js';
 
if(file_exists($filename)) {
  $iFileSize = filesize($filename);
  $iWidth = ceil(sqrt($iFileSize / 1));
  $iHeight = $iWidth;
  $im = imagecreate($iWidth, $iHeight);
  $fs = fopen($filename, 'r');
  $data = fread($fs, $iFileSize);
  fclose($fs);
 
  $i = 0;
  $colors = array();
 
  for($y=0;$y<$iHeight;++$y) {
    for($x=0;$x<$iWidth;++$x) {
      $ord = ord($data[$i]);
 
      if(!$colors[$ord]) {
        $colors[$ord] = imagecolorallocate($im,$ord,$ord,$ord);
      }
 
      $color = $colors[$ord];
 
      imagesetpixel($im, $x, $y, imagecolorallocate($im, $color));
 
      ++$i;
    }
  }
 
  header('Content-Type: image/png');
  imagepng($im);
  imagedestroy($im);
}

Ce qui est fun, c’est que l’auteur arrive à passer un Javascript de 124Ko dans cette image de 29Ko! Inversement, voici le script Javascript qui permet de transcoder la valeur d’un pixel en caractère ASCII

function loadPNGData(strFilename, fncCallback) {
	// test for canvas and getImageData
	var bCanvas = false;
	var oCanvas = document.createElement("canvas");
	if (oCanvas.getContext) {
		var oCtx = oCanvas.getContext("2d");
		if (oCtx.getImageData) {
			bCanvas = true;
		}
	}
	if (bCanvas) {
		var oImg = new Image();
		oImg.style.position = "absolute";
		oImg.style.left = "-10000px";
		document.body.appendChild(oImg);
		oImg.onload = function() {
			var iWidth = this.offsetWidth;
			var iHeight = this.offsetHeight;
			oCanvas.width = iWidth;
			oCanvas.height = iHeight;
			oCanvas.style.width = iWidth+"px";
			oCanvas.style.height = iHeight+"px";
			var oText = document.getElementById("output");
			oCtx.drawImage(this,0,0);
			var oData = oCtx.getImageData(0,0,iWidth,iHeight).data;
			var a = [];
			var len = oData.length;
			var p = -1;
			for (var i=0;i<len;i+=4) {
				if (oData[i] > 0)
					a[++p] = String.fromCharCode(oData[i]);
			};
			var strData = a.join("");
			if (fncCallback) {
				fncCallback(strData);
			}
			document.body.removeChild(oImg);
		}
		oImg.src = strFilename;
		return true;
	} else {
		return false;
	}
}

L’image ci-dessus contient en réalité l’intégralité du script “Prototype” en version 1.6.0.2 dont voici un court extrait des 4221 lignes:

/*  Prototype JavaScript framework, version 1.6.0.2
 *  (c) 2005-2008 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
 *--------------------------------------------------------------------------*/
 
var Prototype = {
  Version: '1.6.0.2',
 
(...)
 
Element.addMethods();

L’article original est dispo sur nihilogic.dk avec les exemples et comparaisons entres scripts pré-compressés et formats d’image, le script PHP pour générer le PNG et la librairie Javascript pour décompresser le PNG à la volée.

Pendant que vous y êtes, ne ratez surtout pas LE délire de ce fou furieux du code : un niveau de Mario dans un unique fichier javascript de 8Ko, sans aucune autre ressource (aucune image)!

Plus loin sur la toile et tout aussi fou, un doom-like avec 4Ko de javascript… moi je change de métier :)

Tags:  javascript

Articles relatifs