libtthimage/Lib/pcx.c

361 lines
8.7 KiB
C
Raw Normal View History

2022-06-26 20:06:35 +11: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 10:21:05 +11:00
#include "../tthimage.h"
2022-06-26 20:06:35 +11: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;
}
/*::------------------------------------------------------------------::*/