Petit délire illustrant l'usage de constexpr
et de la biliothèsque frozen.
Première étape : faire un dessin en pixel art, par exemple:
constexpr unsigned char bytes[] = " ### ### "
" ##### ########## ##### "
" ####### ####### "
" #### #### "
" ### ### "
" # # "
" # # "
" # ### ### # "
" # ##### ##### # "
" # #### # # #### # "
" # #### # # #### # "
" # ##### ##### # "
" # ### ## ### # "
" # ## # "
" #### RRR RRR #### "
" ######RRRRR RRRRR###### "
" ######RRRRRRRRRRRR###### "
" ######RRRRRRRRRRRR###### "
" ######RRRRRRRRRRRR###### "
" #######RRRRRRRRRR####### "
" ##### RRRRRRRR #### "
" ### RRRRRR ## "
" RRRR ";
On remarquera l'énorme code de couleur espace → blanc, #
→ noir et R
→ rouge.
Ensuite on encode cette colormap dans une petite table de hash (oui dans ce cas un tableau de char suffirait) :
#include <frozen/map.h>
constexpr frozen::map<char, std::array<char, 3>, 5> Tans{
{'R', {(char)0xFF, (char)0x00, (char)0x00}},
{'G', {(char)0x00, (char)0xFF, (char)0x00}},
{'B', {(char)0x00, (char)0x00, (char)0xFF}},
{'#', {(char)0x00, (char)0x00, (char)0x00}},
{' ', {(char)0xFF, (char)0xFF, (char)0xFF}},
};
Et comme on est tout foufou, on demande au compilateur C++ de traduire cette image pixel art en image au format PPM, à compile time
constexpr unsigned itoa(unsigned char * start, unsigned i) {
constexpr unsigned step = sizeof(unsigned) * 3;
for(unsigned k = 0; k < step; ++k)
*start++ = ' ';
do {
*--start = '0' + i % 10;
i /= 10;
} while(i);
return step;
}
template <unsigned H, unsigned W> struct ppm {
unsigned char bytes[9 /* fixed header*/ + sizeof(unsigned) * 3 * 2 /* to hold sizes */ + 3 * H * W];
constexpr ppm(unsigned char const *data) : bytes{0} {
unsigned j = 0;
bytes[j++] = 'P';
bytes[j++] = '6';
bytes[j++] = ' ';
j += itoa(bytes + j, H);
bytes[j++] = ' ';
j += itoa(bytes + j, W);
bytes[j++] = ' ';
bytes[j++] = '2';
bytes[j++] = '5';
bytes[j++] = '5';
bytes[j++] = '\n';
for (unsigned i = 0; i < H * W; ++i) {
auto const code = Tans.find(data[i])->second;
bytes[j + 3 * i + 0] = code[0];
bytes[j + 3 * i + 1] = code[1];
bytes[j + 3 * i + 2] = code[2];
}
}
void save(char const path[]) const {
std::ofstream out{path, std::ios::binary};
out.write((char *)bytes, sizeof bytes);
}
};
On vient donc de créer une image dans un format binaire, en embarquant les sources de cette binaire dans les sources. À quand un encodeur jpeg constexpr
?
PS: sources complètes par ici
# XPM
Posté par binoyte . Évalué à 6.
Ça me fait penser au format d'image XPM !
[^] # Re: XPM
Posté par serge_sans_paille (site web personnel) . Évalué à 2.
Mais mais… tu as raison, très amusant ce petit format :-)
[^] # Re: XPM
Posté par SChauveau . Évalué à 6.
Il y a aussi pbm pour les image monochromes (bitmap) et pgm pour les niveaux de gris (grayscale)
L'avantage de tout ces petits formats est qu'il sont triviaux à lire et a écrire dans quasiment tout les langages. Le paquet netpbm fournit de nombreux utilitaires de conversions tels que pnmtojpeg ou ppnmtopng. Combiné avec popen, cela permet de générer des images JPEG ou PNG à partir de données brutes en seulement quelques lignes de C ou C++
[^] # Re: XPM
Posté par Xavier Maillard . Évalué à 1.
Toute ma jeunesse les PGM lorsque je faisais du TNI.
Un bon souvenir.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.