Je travaille en C sur une expérience de physique, Expérience d'interférence de Young et j'ai créé un programme qui imprime à file
une énorme bande de pixels:
for (i=0; i < width*width; i++)
{
fwrite(hue(raster_matrix[i]), 1, 3, file);
}
Où hue
, lorsqu'on lui attribue une valeur [0..255], renvoie un char *
avec 3 octets, R, V, B.
Je voudrais mettre un en-tête minimal dans mon fichier image afin de faire de ce fichier brut un fichier image valid.
Plus concis: Passant de:
offset
0000 : height * width : data } my data, 24bit RGB pixels
à
offset
0000 : dword : magic \
: /* ?? */ \
0012 : dword : height } Header <--> common image file
0016 : dword : width /
: /* ?? */ /
0040 : height * width : data } my data, 24bit RGB pixels
Je vous remercie.
Vous voudrez probablement utiliser le format PPM qui correspond à ce que vous recherchez: un en-tête minimal suivi d'un RVB brut.
Le format récemment créé farbfeld est assez minime, bien que peu de logiciels le supportent (du moins jusqu’à présent).
Bytes │ Description
8 │ "farbfeld" magic value
4 │ 32-Bit BE unsigned integer (width)
4 │ 32-Bit BE unsigned integer (height)
(2+2+2+2)*width*height │ 4*16-Bit BE unsigned integers [RGBA] / pixel, row-major
TARGA (extension de nom de fichier .tga
) est peut-être le format de fichier d'image binaire le plus largement pris en charge si vous n'utilisez pas la compression ni aucune de ses extensions. C'est encore plus simple que les fichiers Windows .bmp
et est pris en charge par ImageMagick et de nombreux programmes Paint. C’est mon format préféré lorsque j’ai juste besoin de sortir des pixels d’un programme jetable.
Voici un programme C minimal pour générer une image sur une sortie standard:
#include <stdio.h>
#include <string.h>
enum { width = 550, height = 400 };
int main(void) {
static unsigned char pixels[width * height * 3];
static unsigned char tga[18];
unsigned char *p;
size_t x, y;
p = pixels;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
*p++ = 255 * ((float)y / height);
*p++ = 255 * ((float)x / width);
*p++ = 255 * ((float)y / height);
}
}
tga[2] = 2;
tga[12] = 255 & width;
tga[13] = 255 & (width >> 8);
tga[14] = 255 & height;
tga[15] = 255 & (height >> 8);
tga[16] = 24;
tga[17] = 32;
return !((1 == fwrite(tga, sizeof(tga), 1, stdout)) &&
(1 == fwrite(pixels, sizeof(pixels), 1, stdout)));
}
Voici un exemple minimal qui écrit votre fichier image avec un en-tête minimal PPM:
#include <stdio.h>
#include <stdlib.h>
#include <math.h> // compile with gcc -lm
#define WAVE(x,y) sin(sqrt( (x)*(x)+(y)*(y) ) / 3.0)
int main(){
/* Setup code */
#define width 256
unsigned char raster_matrix[width*width];
unsigned char a[3];
#define hue(c) (a[0] = c, a[1] = 128, a[2] = 255-c, a)
int x, y, i = 0;
for (y = 0; y < width; y++) for (x = 0; x < width; x++)
raster_matrix[i++] = 128 + 64*(WAVE(x,y) + WAVE(x,width-y));
/* Open PPM File */
FILE *file = fopen("young.ppm", "wb"); if (!file) return -1;
/* Write PPM Header */
fprintf(file, "P6 %d %d %d\n", width, width, 255); /* width, height, maxval */
/* Write Image Data */
for (i=0; i < width*width; i++)
fwrite(hue(raster_matrix[i]), 1, 3, file);
/* Close PPM File */
fclose(file);
/* All done */
return 0;
}
J'ai écrit le code d'en-tête basé sur les spécifications à http://netpbm.sourceforge.net/doc/ppm.html .
J'ai piraté du code d'installation pour pouvoir incorporer la boucle for
donnée dans la question. :)