/* pcx.c ===== "Euh, pourquoi c,a avance pas ?" "Ben, parce que le momo me prend la tete..." "Ah, je comprends." 2 Octobre 2001: le boutisme va être pris en compte. pour plus de détails, allez voir le module 'basic_io.c'. */ #include #include #include #include /* pour memset() */ #ifdef NEED_ALLOCA_H #include #endif #ifndef DEBUG_LEVEL #define DEBUG_LEVEL 1 #endif #include "tthimage.h" /*::------------------------------------------------------------------::*/ #define LIBPCX_VERSION "0.0.12" typedef struct { /* * Attention, cette structure n'est pas directement * utilsable pour les I/O disques, a cause des problemes * d'aligmement { pas de #pragma pack(1) disponible } */ uint8_t aa; uint8_t version; uint8_t encoding; uint8_t bit_pixel; uint16_t xmin, ymin; uint16_t xmax, ymax; uint16_t hres; uint16_t vres; uint8_t palette[48]; uint8_t reserved; uint8_t col_planes; uint16_t byte_lines; uint16_t palette_type; char filler[58]; } Pcx_file_header; /*::------------------------------------------------------------------::*/ static int Image_PCX_dump_header(Pcx_file_header *ph, int verbose) { if (verbose) printf("pcx header @ %p\n", ph); printf(" aa : %02x\n", ph->aa); printf(" version : %d\n", ph->version); printf(" encoding : %d\n", ph->encoding); printf(" bits/pixels : %d\n", ph->bit_pixel); printf(" xy min : %5d %5d\n", ph->xmin, ph->ymin); printf(" xy max : %5d %5d\n", ph->xmax, ph->ymax); printf(" hv res : %5d %5d\n", ph->hres, ph->vres); printf(" col/plane : %d\n", ph->col_planes); printf(" bytes/line : %d\n", ph->byte_lines); printf(" palette : %d\n", ph->palette_type); return 0; } /*::------------------------------------------------------------------::*/ /* * 9 Oct 2001: ecriture d'un header PCX sur disque sans problemes * de boutisme (en principe :) */ static int write_pcx_header(Pcx_file_header *head, FILE *fp) { #if DEBUG_LEVEL fprintf(stderr, "writing a pcx header (lib v %s)\n", LIBPCX_VERSION); #endif fwrite(&head->aa, 1, 1, fp); fwrite(&head->version, 1, 1, fp); fwrite(&head->encoding, 1, 1, fp); fwrite(&head->bit_pixel, 1, 1, fp); Image_basicIO_write_I_short(fp, head->xmin); Image_basicIO_write_I_short(fp, head->ymin); Image_basicIO_write_I_short(fp, head->xmax); Image_basicIO_write_I_short(fp, head->ymax); Image_basicIO_write_I_short(fp, head->hres); Image_basicIO_write_I_short(fp, head->vres); fwrite(&head->palette, 1, 48, fp); fwrite(&head->reserved, 1, 1, fp); fwrite(&head->col_planes, 1, 1, fp); Image_basicIO_write_I_short(fp, head->byte_lines); Image_basicIO_write_I_short(fp, head->palette_type); fwrite(&head->filler, 1, 58, fp); #if DEBUG_LEVEL Image_PCX_dump_header(head, 1); #endif return 0; } /*::------------------------------------------------------------------::*/ /* new 24 Nov 2001 * read a PCX header */ static int read_pcx_header(Pcx_file_header *head, FILE *fp) { #if DEBUG_LEVEL fprintf(stderr, "reading a pcx header (lib v %s)\n", LIBPCX_VERSION); #endif /* effacement de la zone de données */ memset(head, 0, sizeof(Pcx_file_header)); rewind(fp); /* revenir au début */ fprintf(stderr, "reading...\n"); fread(&head->aa, 1, 1, fp); fread(&head->version, 1, 1, fp); fread(&head->encoding, 1, 1, fp); fread(&head->bit_pixel, 1, 1, fp); Image_basicIO_read_I_short(fp, &head->xmin); Image_basicIO_read_I_short(fp, &head->ymin); Image_basicIO_read_I_short(fp, &head->xmax); Image_basicIO_read_I_short(fp, &head->ymax); Image_basicIO_read_I_short(fp, &head->hres); Image_basicIO_read_I_short(fp, &head->vres); fread(&head->palette, 1, 48, fp); fread(&head->reserved, 1, 1, fp); fread(&head->col_planes, 1, 1, fp); Image_basicIO_read_I_short(fp, &head->byte_lines); return FUNC_NOT_FINISH; } /*::------------------------------------------------------------------::*/ int Image_PCX_fileinfo(char *nom) { Pcx_file_header head; FILE *fp; int foo; fprintf(stderr, "reading '%s'\n", nom); if ( (fp=fopen(nom, "rb")) == NULL ) { fprintf(stderr, "PCX fileinfo: err fopen %d\n", errno); return FILE_NOT_FOUND; } fprintf(stderr, "fp %p\n", fp); read_pcx_header(&head, fp); fclose(fp); printf("PCX infos for file: %s\n", nom); foo = Image_PCX_dump_header(&head, 0); return foo; } /*::------------------------------------------------------------------::*/ /* * Euh, je prends cette fonction direct de Steve Rimmer, et * je chercherais a comprendre quand le Momo me laissera la * cervelle intacte. */ static int pix2byte_mono(int n) { if (n & 0x0007) return((n >> 3) + 1); else return(n >> 3); } static int pix2byte_4cols(int n) { if (n & 0x0001) return((n >> 1) + 1); else return(n >> 1); } /*::------------------------------------------------------------------::*/ /* from "Bit-mapped graphics" page 101 */ static int write_line(unsigned char *p, int bytes, FILE *fp) { unsigned int i=0, j=0, t=0; /* hu ho */ do { i = 0; while((p[t+i]==p[t+i+1]) && ((t+i) 0) { fputc(i | 0xc0, fp); fputc(~p[t], fp); t += i; j += 2; } else { if ( ((~p[t])&0xc0)==0xc0 ) { fputc(0xc1, fp); ++j; } fputc(~p[t++], fp); ++j; } } while (t < bytes); return j; } /*::------------------------------------------------------------------::*/ /* la, j'ai qu'un mot a dire: "ou sont les backups de convpht ?" */ int Image_wrPCX_8colors(char *nom, Image_Desc *im) { Pcx_file_header head; FILE *fp; uint8_t *line, *compline, the_byte; int foo, bytes, x, y; int r, g, b; #if DEBUG_LEVEL fprintf(stderr, "L'ecriture des PCX 8 couleurs est experimentale. YMMV.\n"); #endif /* * populate the header of the file */ memset(&head, ' ', sizeof(head)); head.aa = 0x0a; /* toujours 10 */ head.version = 5; head.encoding = 1; /* toujours 1. */ head.bit_pixel = 4; head.xmin = 0; head.ymin = 0; head.xmax = im->width-1; /* A VERIFIER */ head.ymax = im->height-1; /* A VERIFIER, aussi */ head.hres = 72; head.vres = 72; head.reserved = 0x42; /* what a nice number ! */ head.col_planes = 1; /* ?????????????????? */ head.byte_lines = pix2byte_4cols(im->width); #if DEBUG_LEVEL fprintf(stderr, "width %d -> byte_lines %d\n", im->width, head.byte_lines); #endif head.palette_type = 0; /* we make a 16 color file ? */ for (foo=0; foo<8; foo++) /* create the palette */ { head.palette[foo*3] = (foo & 1) ? 255 : 0; head.palette[foo*3+1] = (foo & 2) ? 255 : 0; head.palette[foo*3+2] = (foo & 4) ? 255 : 0; } /* warning, the filler is NOT an asciiz string */ strncpy(head.filler, "[ PCX writ'd by the libimage (dwtfywl) tontonTh ]", 58); /* * allocate the buffer for the raw bit-map-line, this one * before the compression... */ bytes = pix2byte_4cols(im->width); #if DEBUG_LEVEL fprintf(stderr, "PCX: en largeur, %d pixels, donc une ligne de %d octets\n", im->width, bytes); #endif line = (uint8_t *)alloca(bytes * sizeof(uint8_t)); compline = (uint8_t *)alloca(bytes * 3 * sizeof(uint8_t)); /* * open the file and write the header */ if ( (fp = fopen(nom, "w")) == NULL ) { fprintf(stderr, "wr pcx 8 colors: err fopen %d\n", errno); return FILE_CREATE_ERR; } (void)write_pcx_header(&head, fp); /* new 9 oct 2001 */ /* * and now, the great show: blast all the picture lines to * the marvelous PCX compression scheme. */ for (y=0; yheight; y++) { #if DEBUG_LEVEL fprintf(stderr, "Wr pcx8: line %d\r", y); #endif memset(line, 0, bytes); for (x=0; xwidth; x++) { /* * read the pixels... */ Image_getRGB(im, x, y, &r, &g, &b); r = (r >> 8) & 1; g = (g >> 8) & 1; b = (b >> 8) & 1; the_byte = (r<<4) | (r<<3) | (r<<2); /* * build the line */ if (x & 1) { line[x/2] |= the_byte; } else { line[x/2] |= (the_byte<<4); } } foo = write_line(line, bytes, fp); #if DEBUG_LEVEL fprintf(stderr, " %d bytes written\n", foo); #endif } #if DEBUG_LEVEL fputs("................ pcx .....\n", stderr); #endif fclose(fp); return FULL_NUCKED; /* 24 mars 2002: toujours nucked */ } /*::------------------------------------------------------------------::*/ /* * Raaahaha p'taing il faudrait le finir un de ces jours ! * 16 Feb 2001: j'y travaille, j'y travaille... * 09 Oct 2001: ...et ce sera sans problèmes de boutisme :) * 22 Jan 2003: ça avance, faut pas s'affoler. * 17 Oct 2009: c'est encore au point mort. */ /*::------------------------------------------------------------------::*/ /* 19 mars 2010 : arrivee des bitplanes */ int Image_bp2pcx(A_BitPlane *bp, char *fname, int flags) { #if DEBUG_LEVEL fprintf(stderr, "%s ( %p '%s' %d )\n", __func__, bp, fname, flags); #endif return FULL_NUCKED; } /*::------------------------------------------------------------------::*/