Aller au contenu

xkcd: Click and Drag

Le dernier strip d'xkcd est vraiment fun. Un strip dynamique gigantesque, bourré de détails marrant cachés.

Bon, je sais que je me suis déjà fait griller par certains, mais j'ai quand même décidé d'aller au bout de mon petit jeu : je me suis amusé à vous en faire une miniature complète du strip d'xkcd.

xkcd Click and Drage thumbnails
Cliquez pour agrandir un peu (~5200x2400 pixels)

Pour la réaliser, j'ai observé le code de la page, et j'ai constaté, comme azt.tm avant moi, que l'affichage se basait sur des images de carrées de 2048 pixels de côté, et dont les noms sont basés sur un système d'orientation nord-sud (haut-bas de l'image) et ouest-est (gauche-droite).

Le javascript utilisé par Randall Munroe semblait indiquer qu'il y avait des coordonnées allant jusqu'à 14 nord, 48 est, 25 sud et 33 ouest.

J'ai donc réalisé un petit script qui m'a sorti les liens vers toutes les images supposées exister, entre (33 ouest - 14 nord) et (48 est - 25 sud). Soit un total de 81 par 39 images, donc 3159 images de 2048 pixels, soit.... 165888 par 79872 pixels !

Bon, ok, jusqu'ici, on s'en fout un peu.

Ensuite, j'ai utilisé l'addon de Firefox nommé DownThemAll, pour télécharger automatiquement toutes ces images. On constate finalement que certaines n'existent pas, dans les zones où l'auteur n'a rien dessiné. Il n'y a finalement "que" 225 images au total. Les autres redirigent vers une 404, et DownThemAll a été assez intelligent pour ne pas les télécharger. Bon la méthode est assez bourrine, mais je suis sûr que son serveur est dimenssionné pour suporter une telle charge. O:-P

Un petit coup d'imagemagick pour batchresize tout ça en carrés de 64px :

mogrify -resize 3.125% *.png

Il ne reste plus qu'à pondre un petit code pour rassembler le tout en une image. J'ai d'abord pensé à la commande montage d'imagemagick, mais soit elle n'est pas assez puissante, soit je n'ai pas trouvé les fonctionnalités que je cherchais.

Du coup, j'ai fait ça en C++/Qt :

#include <QImage>
#include <QPainter>
#include <QFile>
#include <QDebug>

int main(int argc, char *argv[]) {
    const int TILE_SIZE = 64;
//    const int TILE_SIZE = 2048;
    const int NORTH_SIZE = 14;
    const int EAST_SIZE = 33;
    const int SOUTH_SIZE = 23;
    const int WEST_SIZE = 48;

    QImage *resultImage = new QImage(TILE_SIZE * (EAST_SIZE + WEST_SIZE) ,TILE_SIZE * (NORTH_SIZE + SOUTH_SIZE), QImage::Format_ARGB32);
    resultImage->fill(Qt::gray);
    for(int i=0; i < (EAST_SIZE+WEST_SIZE); i++) {
        for(int j=0; j < (NORTH_SIZE+SOUTH_SIZE); j++) {
            QString filePath = "thumbs/";
//            QString filePath = "images/";
            if(j < NORTH_SIZE) {
                filePath += QString::number(NORTH_SIZE-j) + "n";
            } else {
                filePath += QString::number(j-NORTH_SIZE+1) + "s";
            }
            if(i < EAST_SIZE) {
                filePath += QString::number(EAST_SIZE-i) + "w";
            } else {
                filePath += QString::number(i-EAST_SIZE+1) + "e";
            }
            filePath += ".png";
            QFile imageFile(filePath);
            if(imageFile.exists()) {
                qDebug() << filePath;
                QPainter painter;
                painter.begin(resultImage);
                painter.drawImage(i*TILE_SIZE, j*TILE_SIZE, QImage(filePath));
                painter.end();
            }
        }
    }
    resultImage->save("result.png");
}

Je vous proposerais bien d'exécuter le même code directement sur les images en 2048 pixels, mais je pense que la mémoire pourrait avoir quelques soucis.

PS : et j'allais presque oublier le lien vers le strip !!! Allez jouer avec sur xkcd !

xkcd sample