2022-06-26 11:06:35 +02:00
|
|
|
|
/*
|
|
|
|
|
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 <EFBFBD>tre pris en compte. pour plus
|
|
|
|
|
de d<EFBFBD>tails, allez voir le module 'basic_io.c'.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h> /* pour memset() */
|
|
|
|
|
|
|
|
|
|
#ifdef NEED_ALLOCA_H
|
|
|
|
|
#include <alloca.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef DEBUG_LEVEL
|
|
|
|
|
#define DEBUG_LEVEL 1
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-01-31 00:21:05 +01:00
|
|
|
|
#include "../tthimage.h"
|
2022-06-26 11:06:35 +02:00
|
|
|
|
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
#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<6E>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)<bytes) && (i<63)) ++i;
|
|
|
|
|
if (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; y<im->height; y++)
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "Wr pcx8: line %d\r", y);
|
|
|
|
|
#endif
|
|
|
|
|
memset(line, 0, bytes);
|
|
|
|
|
for (x=0; x<im->width; 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<EFBFBD>mes de boutisme :)
|
|
|
|
|
* 22 Jan 2003: <EFBFBD>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;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|