|
Packit |
78deda |
/* ilbmtoppm.c - read an IFF ILBM file and produce a PPM
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Copyright (C) 1989 by Jef Poskanzer.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
78deda |
** documentation for any purpose and without fee is hereby granted, provided
|
|
Packit |
78deda |
** that the above copyright notice appear in all copies and that both that
|
|
Packit |
78deda |
** copyright notice and this permission notice appear in supporting
|
|
Packit |
78deda |
** documentation. This software is provided "as is" without express or
|
|
Packit |
78deda |
** implied warranty.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Modified by Mark Thompson on 10/4/90 to accommodate 24-bit IFF files
|
|
Packit |
78deda |
** as used by ASDG, NewTek, etc.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Modified by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
Packit |
78deda |
** 20/Jun/93:
|
|
Packit |
78deda |
** - row-by-row operation
|
|
Packit |
78deda |
** - better de-interleave algorithm
|
|
Packit |
78deda |
** - colormap files
|
|
Packit |
78deda |
** - direct color
|
|
Packit |
78deda |
** 04/Oct/93:
|
|
Packit |
78deda |
** - multipalette capability (PCHG chunk)
|
|
Packit |
78deda |
** - options -ignore, -isham, -isehb and -adjustcolors
|
|
Packit |
78deda |
** 22/May/94:
|
|
Packit |
78deda |
** - minor change: check first for 24 planes, then for HAM
|
|
Packit |
78deda |
** 21/Sep/94:
|
|
Packit |
78deda |
** - write mask plane to a file if -maskfile option used
|
|
Packit |
78deda |
** - write colormap file
|
|
Packit |
78deda |
** - added sliced HAM/dynamic HAM/dynamic Hires multipalette formats (SHAM, CTBL chunk)
|
|
Packit |
78deda |
** - added color lookup tables (CLUT chunk)
|
|
Packit |
78deda |
** - major rework of colormap/multipalette handling
|
|
Packit |
78deda |
** - now uses numeric IFF IDs
|
|
Packit |
78deda |
** 24/Oct/94:
|
|
Packit |
78deda |
** - transparentColor capability
|
|
Packit |
78deda |
** - added RGBN/RGB8 image types
|
|
Packit |
78deda |
** - 24-bit & direct color modified to n-bit deep ILBM
|
|
Packit |
78deda |
** 22/Feb/95:
|
|
Packit |
78deda |
** - direct color (DCOL) reimplemented
|
|
Packit |
78deda |
** 29/Mar/95
|
|
Packit |
78deda |
** - added IFF-PBM format
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <string.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
#include "intcode.h"
|
|
Packit |
78deda |
#include "ilbm.h"
|
|
Packit |
78deda |
#include "ppm.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
typedef struct {
|
|
Packit |
78deda |
int reg; /* color register to change */
|
|
Packit |
78deda |
pixval r, g, b; /* new colors for register */
|
|
Packit |
78deda |
} PaletteChange;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
typedef struct {
|
|
Packit |
78deda |
pixel *color;
|
|
Packit |
78deda |
int ncolors;
|
|
Packit |
78deda |
/* lookup tables */
|
|
Packit |
78deda |
unsigned char *redlut;
|
|
Packit |
78deda |
unsigned char *greenlut;
|
|
Packit |
78deda |
unsigned char *bluelut;
|
|
Packit |
78deda |
unsigned char *monolut;
|
|
Packit |
78deda |
/* multipalette stuff */
|
|
Packit |
78deda |
PaletteChange *mp_init;
|
|
Packit |
78deda |
PaletteChange **mp_change;
|
|
Packit |
78deda |
int mp_rows; /* # of rows in change array */
|
|
Packit |
78deda |
int mp_type; /* see below, higher types preferred */
|
|
Packit |
78deda |
int mp_flags;
|
|
Packit |
78deda |
IFF_ID mp_id;
|
|
Packit |
78deda |
} ColorMap;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define HAS_COLORMAP(cmap) ((cmap) && (cmap)->color)
|
|
Packit |
78deda |
#define HAS_COLORLUT(cmap) ((cmap) && ((cmap)->redlut || (cmap)->greenlut || (cmap)->bluelut))
|
|
Packit |
78deda |
#define HAS_MONOLUT(cmap) ((cmap) && (cmap)->monolut)
|
|
Packit |
78deda |
#define HAS_MULTIPALETTE(cmap) (HAS_COLORMAP(cmap) && (cmap)->mp_type)
|
|
Packit |
78deda |
#define MP_TYPE_SHAM 1
|
|
Packit |
78deda |
#define MP_TYPE_CTBL 2
|
|
Packit |
78deda |
#define MP_TYPE_PCHG 3
|
|
Packit |
78deda |
#define MP_REG_IGNORE -1
|
|
Packit |
78deda |
#define MP_REG_END -2
|
|
Packit |
78deda |
#define MP_FLAGS_SKIPLACED (1<<0)
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define FACTOR_4BIT 17 /* scale factor maxval 15 -> maxval 255 */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static short verbose = 0;
|
|
Packit |
78deda |
static short adjustcolors = 0;
|
|
Packit |
78deda |
static unsigned char *ilbmrow;
|
|
Packit |
78deda |
static pixel *pixelrow;
|
|
Packit |
78deda |
static FILE *maskfile = NULL;
|
|
Packit |
78deda |
static bit *maskrow = NULL;
|
|
Packit |
78deda |
static bool wrotemask;
|
|
Packit |
78deda |
static IFF_ID typeid; /* ID_ILBM, ID_RGBN, ID_RGB8 */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static char *transpName = NULL; /* -transparent option value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static bool debug = FALSE;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static char *
|
|
Packit |
78deda |
ID2string(id)
|
|
Packit |
78deda |
IFF_ID id;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
static char str[] = "abcd";
|
|
Packit |
78deda |
|
|
Packit |
78deda |
str[0] = (char)(id >> 24 & 0xff);
|
|
Packit |
78deda |
str[1] = (char)(id >> 16 & 0xff);
|
|
Packit |
78deda |
str[2] = (char)(id >> 8 & 0xff);
|
|
Packit |
78deda |
str[3] = (char)(id >> 0 & 0xff);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return str;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Memory allocation
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
static ColorMap *
|
|
Packit |
78deda |
alloc_cmap(void) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ColorMap * cmap;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(cmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmap->color = NULL;
|
|
Packit |
78deda |
cmap->ncolors = 0;
|
|
Packit |
78deda |
cmap->monolut = NULL;
|
|
Packit |
78deda |
cmap->redlut = NULL;
|
|
Packit |
78deda |
cmap->greenlut = NULL;
|
|
Packit |
78deda |
cmap->bluelut = NULL;
|
|
Packit |
78deda |
cmap->mp_init = NULL;
|
|
Packit |
78deda |
cmap->mp_change = NULL;
|
|
Packit |
78deda |
cmap->mp_rows = 0;
|
|
Packit |
78deda |
cmap->mp_type = 0;
|
|
Packit |
78deda |
cmap->mp_flags = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return cmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static rawtype *
|
|
Packit |
78deda |
alloc_rawrow(cols)
|
|
Packit |
78deda |
int cols;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
rawtype *r;
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(r, cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( i = 0; i < cols; i++ )
|
|
Packit |
78deda |
r[i] = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return r;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Basic I/O functions
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
readerr(f, iffid)
|
|
Packit |
78deda |
FILE *f;
|
|
Packit |
78deda |
IFF_ID iffid;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( ferror(f) )
|
|
Packit |
78deda |
pm_error("read error");
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_error("premature EOF in %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_bytes(FILE * const ifP,
|
|
Packit |
78deda |
int const bytes,
|
|
Packit |
78deda |
unsigned char * const buffer,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long * const counterP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (counterP) {
|
|
Packit |
78deda |
if (*counterP < bytes)
|
|
Packit |
78deda |
pm_error("insufficient data in %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
*counterP -= bytes;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (fread(buffer, 1, bytes, ifP) != bytes)
|
|
Packit |
78deda |
readerr(ifP, iffid);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned char
|
|
Packit |
78deda |
get_byte(ifP, iffid, counter)
|
|
Packit |
78deda |
FILE* ifP;
|
|
Packit |
78deda |
IFF_ID iffid;
|
|
Packit |
78deda |
long *counter;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( counter ) {
|
|
Packit |
78deda |
if( *counter == 0 )
|
|
Packit |
78deda |
pm_error("insufficient data in %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
--(*counter);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
i = getc(ifP);
|
|
Packit |
78deda |
if( i == EOF )
|
|
Packit |
78deda |
readerr(ifP, iffid);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return (unsigned char) i;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static long
|
|
Packit |
78deda |
get_big_long(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long * const counterP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
long l;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (counterP) {
|
|
Packit |
78deda |
if (*counterP < 4)
|
|
Packit |
78deda |
pm_error("insufficient data in %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
*counterP -= 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (pm_readbiglong(ifP, &l) == -1)
|
|
Packit |
78deda |
readerr(ifP, iffid);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return l;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static short
|
|
Packit |
78deda |
get_big_short(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long * const counterP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
short s;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (counterP) {
|
|
Packit |
78deda |
if (*counterP < 2)
|
|
Packit |
78deda |
pm_error("insufficient data in %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
*counterP -= 2;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (pm_readbigshort(ifP, &s) == -1)
|
|
Packit |
78deda |
readerr(ifP, iffid);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return s;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Chunk reader
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
chunk_end(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long const chunksize) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (chunksize > 0) {
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pm_message("warning - %ld extraneous byte%s in %s chunk",
|
|
Packit |
78deda |
chunksize, (chunksize == 1 ? "" : "s"), ID2string(iffid));
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
while (remainingChunksize > 0)
|
|
Packit |
78deda |
get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
skip_chunk(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long const chunksize) {
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
while (remainingChunksize > 0)
|
|
Packit |
78deda |
get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
display_chunk(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long const chunksize) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int byte;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("contents of %s chunk:", ID2string(iffid));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
byte = '\0';
|
|
Packit |
78deda |
|
|
Packit |
78deda |
while (remainingChunksize > 0) {
|
|
Packit |
78deda |
byte = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
if (fputc(byte, stderr) == EOF)
|
|
Packit |
78deda |
pm_error("write error");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (byte != '\n')
|
|
Packit |
78deda |
if (fputc('\n', stderr) == EOF)
|
|
Packit |
78deda |
pm_error("write error");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_cmap(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
long colors;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
colors = chunksize / 3;
|
|
Packit |
78deda |
if( colors == 0 ) {
|
|
Packit |
78deda |
pm_error("warning - empty %s colormap", ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
if( cmap->color ) /* prefer CMAP-chunk over CMYK-chunk */
|
|
Packit |
78deda |
ppm_freerow(cmap->color);
|
|
Packit |
78deda |
cmap->color = ppm_allocrow(colors);
|
|
Packit |
78deda |
cmap->ncolors = colors;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( i = 0; i < colors; ++i ) {
|
|
Packit |
78deda |
int r, g, b;
|
|
Packit |
78deda |
r = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
g = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
b = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
PPM_ASSIGN(cmap->color[i], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, iffid, chunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_cmyk(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_COLORMAP(cmap) ) { /* prefer RGB color map */
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
long const colors = chunksize/4;
|
|
Packit |
78deda |
if( colors == 0 ) {
|
|
Packit |
78deda |
pm_error("warning - empty %s colormap", ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
cmap->color = ppm_allocrow(colors);
|
|
Packit |
78deda |
cmap->ncolors = colors;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( i = 0; i < colors; ++i ) {
|
|
Packit |
78deda |
int c, m, y, k;
|
|
Packit |
78deda |
c = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
m = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
y = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
k = get_byte(ifP, iffid, &chunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
pixval const red =
|
|
Packit |
78deda |
MAXCOLVAL - MIN(MAXCOLVAL,
|
|
Packit |
78deda |
c*(MAXCOLVAL-k)/MAXCOLVAL+k);
|
|
Packit |
78deda |
pixval const green =
|
|
Packit |
78deda |
MAXCOLVAL - MIN(MAXCOLVAL,
|
|
Packit |
78deda |
m*(MAXCOLVAL-k)/MAXCOLVAL+k);
|
|
Packit |
78deda |
pixval const blue =
|
|
Packit |
78deda |
MAXCOLVAL - MIN(MAXCOLVAL,
|
|
Packit |
78deda |
y*(MAXCOLVAL-k)/MAXCOLVAL+k);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
PPM_ASSIGN(cmap->color[i], red, green, blue);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, iffid, chunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_clut(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long const chunksize,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (chunksize != CLUTSize) {
|
|
Packit |
78deda |
pm_message("invalid size for %s chunk - skipping it",
|
|
Packit |
78deda |
ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
long type;
|
|
Packit |
78deda |
unsigned char * lut;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
type = get_big_long(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
get_big_long(ifP, iffid, &remainingChunksize); /* skip reserved fld */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(lut, 256);
|
|
Packit |
78deda |
for( i = 0; i < 256; ++i )
|
|
Packit |
78deda |
lut[i] = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch( type ) {
|
|
Packit |
78deda |
case CLUT_MONO:
|
|
Packit |
78deda |
cmap->monolut = lut;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case CLUT_RED:
|
|
Packit |
78deda |
cmap->redlut = lut;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case CLUT_GREEN:
|
|
Packit |
78deda |
cmap->greenlut = lut;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case CLUT_BLUE:
|
|
Packit |
78deda |
cmap->bluelut = lut;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_message("warning - %s type %ld not recognized",
|
|
Packit |
78deda |
ID2string(iffid), type);
|
|
Packit |
78deda |
free(lut);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
warnNonsquarePixels(uint8_t const xAspect,
|
|
Packit |
78deda |
uint8_t const yAspect) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (xAspect != yAspect) {
|
|
Packit |
78deda |
const char * const baseMsg = "warning - non-square pixels";
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (pm_have_float_format())
|
|
Packit |
78deda |
pm_message("%s; to fix do a 'pamscale -%cscale %g'",
|
|
Packit |
78deda |
baseMsg,
|
|
Packit |
78deda |
xAspect > yAspect ? 'x' : 'y',
|
|
Packit |
78deda |
xAspect > yAspect ?
|
|
Packit |
78deda |
(float)xAspect/yAspect :
|
|
Packit |
78deda |
(float)yAspect/xAspect);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_message("%s", baseMsg);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static BitMapHeader *
|
|
Packit |
78deda |
read_bmhd(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
unsigned long const chunksize) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
BitMapHeader * bmhdP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (chunksize != BitMapHeaderSize) {
|
|
Packit |
78deda |
pm_message("invalid size for %s chunk - skipping it",
|
|
Packit |
78deda |
ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
bmhdP = NULL;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(bmhdP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bmhdP->w = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->h = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->x = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->y = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->nPlanes = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->masking = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->compression = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->flags = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->transparentColor =
|
|
Packit |
78deda |
get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->xAspect = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->yAspect = get_byte(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->pageWidth = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
bmhdP->pageHeight = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (verbose) {
|
|
Packit |
78deda |
if (typeid == ID_ILBM)
|
|
Packit |
78deda |
pm_message("dimensions: %dx%d, %d planes",
|
|
Packit |
78deda |
bmhdP->w, bmhdP->h, bmhdP->nPlanes);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_message("dimensions: %dx%d", bmhdP->w, bmhdP->h);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (typeid == ID_ILBM || typeid == ID_PBM) {
|
|
Packit |
78deda |
pm_message("compression: %s",
|
|
Packit |
78deda |
bmhdP->compression <= cmpMAXKNOWN ?
|
|
Packit |
78deda |
cmpNAME[bmhdP->compression] : "unknown");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch(bmhdP->masking) {
|
|
Packit |
78deda |
case mskNone:
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case mskHasMask:
|
|
Packit |
78deda |
case mskHasTransparentColor:
|
|
Packit |
78deda |
if (!maskfile)
|
|
Packit |
78deda |
pm_message("use '-maskfile <filename>' "
|
|
Packit |
78deda |
"to generate a PBM mask file from %s",
|
|
Packit |
78deda |
mskNAME[bmhdP->masking]);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case mskLasso:
|
|
Packit |
78deda |
pm_message("warning - masking type '%s' not recognized",
|
|
Packit |
78deda |
mskNAME[bmhdP->masking]);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("unknown masking type %d", bmhdP->masking);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else /* RGBN/RGB8 */
|
|
Packit |
78deda |
if (!maskfile)
|
|
Packit |
78deda |
pm_message("use '-maskfile <filename>' "
|
|
Packit |
78deda |
"to generate a PBM mask file "
|
|
Packit |
78deda |
"from genlock bits");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* fix aspect ratio */
|
|
Packit |
78deda |
if (bmhdP->xAspect == 0 || bmhdP->yAspect == 0) {
|
|
Packit |
78deda |
pm_message("warning - illegal aspect ratio %d:%d, using 1:1",
|
|
Packit |
78deda |
bmhdP->xAspect, bmhdP->yAspect);
|
|
Packit |
78deda |
bmhdP->xAspect = bmhdP->yAspect = 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
warnNonsquarePixels(bmhdP->xAspect, bmhdP->yAspect);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return bmhdP;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
ILBM functions
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_ilbm_plane(FILE * const ifP,
|
|
Packit |
78deda |
unsigned long * const remainingChunksizeP,
|
|
Packit |
78deda |
int const bytes,
|
|
Packit |
78deda |
int const compression) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned char *ubp;
|
|
Packit |
78deda |
int j, byte;
|
|
Packit |
78deda |
int bytesRemaining;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesRemaining = bytes; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch(compression) {
|
|
Packit |
78deda |
case cmpNone:
|
|
Packit |
78deda |
read_bytes(ifP, bytesRemaining, ilbmrow,
|
|
Packit |
78deda |
ID_BODY, remainingChunksizeP);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case cmpByteRun1:
|
|
Packit |
78deda |
ubp = ilbmrow;
|
|
Packit |
78deda |
do {
|
|
Packit |
78deda |
byte = (int)get_byte(ifP, ID_BODY, remainingChunksizeP);
|
|
Packit |
78deda |
if( byte <= 127 ) {
|
|
Packit |
78deda |
j = byte;
|
|
Packit |
78deda |
bytesRemaining -= (j+1);
|
|
Packit |
78deda |
if( bytesRemaining < 0 )
|
|
Packit |
78deda |
pm_error("error doing ByteRun1 decompression");
|
|
Packit |
78deda |
for( ; j >= 0; j-- )
|
|
Packit |
78deda |
*ubp++ = get_byte(ifP, ID_BODY, remainingChunksizeP);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
if ( byte != 128 ) {
|
|
Packit |
78deda |
j = 256 - byte;
|
|
Packit |
78deda |
bytesRemaining -= (j+1);
|
|
Packit |
78deda |
if( bytesRemaining < 0 )
|
|
Packit |
78deda |
pm_error("error doing ByteRun1 decompression");
|
|
Packit |
78deda |
byte = (int)get_byte(ifP, ID_BODY, remainingChunksizeP);
|
|
Packit |
78deda |
for( ; j >= 0; j-- )
|
|
Packit |
78deda |
*ubp++ = (unsigned char)byte;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/* 128 is a NOP */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
while( bytesRemaining > 0 );
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("unknown compression type %d", compression);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static const unsigned char bit_mask[] = {1, 2, 4, 8, 16, 32, 64, 128};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
decode_row(FILE * const ifP,
|
|
Packit |
78deda |
unsigned long * const remainingChunksizeP,
|
|
Packit |
78deda |
rawtype * const chunkyrow,
|
|
Packit |
78deda |
int const nPlanes,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int plane, col, cols, cbit, bytes;
|
|
Packit |
78deda |
unsigned char *ilp;
|
|
Packit |
78deda |
rawtype *chp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cols = bmhdP->w;
|
|
Packit Service |
ad4525 |
overflow_add(cols, 15);
|
|
Packit |
78deda |
bytes = RowBytes(cols);
|
|
Packit |
78deda |
for( plane = 0; plane < nPlanes; plane++ ) {
|
|
Packit |
78deda |
int mask;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
mask = 1 << plane;
|
|
Packit |
78deda |
read_ilbm_plane(ifP, remainingChunksizeP, bytes, bmhdP->compression);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ilp = ilbmrow;
|
|
Packit |
78deda |
chp = chunkyrow;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cbit = 7;
|
|
Packit |
78deda |
for( col = 0; col < cols; col++, cbit--, chp++ ) {
|
|
Packit |
78deda |
if( cbit < 0 ) {
|
|
Packit |
78deda |
cbit = 7;
|
|
Packit |
78deda |
ilp++;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( *ilp & bit_mask[cbit] )
|
|
Packit |
78deda |
*chp |= mask;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
*chp &= ~mask;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
decode_mask(FILE * const ifP,
|
|
Packit |
78deda |
unsigned long * const remainingChunksizeP,
|
|
Packit |
78deda |
rawtype * const chunkyrow,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int col, cols, cbit;
|
|
Packit |
78deda |
unsigned char *ilp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cols = bmhdP->w;
|
|
Packit |
78deda |
switch (bmhdP->masking) {
|
|
Packit |
78deda |
case mskNone:
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case mskHasMask: /* mask plane */
|
|
Packit |
78deda |
read_ilbm_plane(ifP, remainingChunksizeP, RowBytes(cols),
|
|
Packit |
78deda |
bmhdP->compression);
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
ilp = ilbmrow;
|
|
Packit |
78deda |
cbit = 7;
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col, --cbit) {
|
|
Packit |
78deda |
if (cbit < 0) {
|
|
Packit |
78deda |
cbit = 7;
|
|
Packit |
78deda |
++ilp;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (*ilp & bit_mask[cbit])
|
|
Packit |
78deda |
maskrow[col] = PBM_BLACK;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
maskrow[col] = PBM_WHITE;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pbm_writepbmrow(maskfile, maskrow, cols, 0);
|
|
Packit |
78deda |
wrotemask = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case mskHasTransparentColor:
|
|
Packit |
78deda |
if (!chunkyrow)
|
|
Packit |
78deda |
pm_error("decode_mask(): chunkyrow == NULL - can't happen");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col) {
|
|
Packit |
78deda |
if (chunkyrow[col] == bmhdP->transparentColor)
|
|
Packit |
78deda |
maskrow[col] = PBM_WHITE;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
maskrow[col] = PBM_BLACK;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pbm_writepbmrow(maskfile, maskrow, cols, 0);
|
|
Packit |
78deda |
wrotemask = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case mskLasso:
|
|
Packit |
78deda |
pm_error("This program does not know how to process Lasso masking");
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("decode_mask(): unknown masking type %d - can't happen",
|
|
Packit |
78deda |
bmhdP->masking);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Multipalette handling
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit Service |
ad4525 |
static void *
|
|
Packit Service |
ad4525 |
xmalloc2(x, y)
|
|
Packit Service |
ad4525 |
int x;
|
|
Packit Service |
ad4525 |
int y;
|
|
Packit Service |
ad4525 |
{
|
|
Packit Service |
ad4525 |
void *mem;
|
|
Packit Service |
ad4525 |
|
|
Packit Service |
ad4525 |
overflow2(x,y);
|
|
Packit Service |
ad4525 |
if( x * y == 0 )
|
|
Packit Service |
ad4525 |
return NULL;
|
|
Packit Service |
ad4525 |
|
|
Packit Service |
ad4525 |
mem = malloc2(x,y);
|
|
Packit Service |
ad4525 |
if( mem == NULL )
|
|
Packit Service |
ad4525 |
pm_error("out of memory allocating %d bytes", x * y);
|
|
Packit Service |
ad4525 |
return mem;
|
|
Packit Service |
ad4525 |
}
|
|
Packit Service |
ad4525 |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
multi_adjust(cmap, row, palchange)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int row;
|
|
Packit |
78deda |
PaletteChange *palchange;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i, reg;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( i = 0; palchange[i].reg != MP_REG_END; i++ ) {
|
|
Packit |
78deda |
reg = palchange[i].reg;
|
|
Packit |
78deda |
if( reg >= cmap->ncolors ) {
|
|
Packit |
78deda |
pm_message("warning - palette change register out of range");
|
|
Packit |
78deda |
pm_message(" row %d change structure %d reg=%d (max %d)",
|
|
Packit |
78deda |
row, i, reg, cmap->ncolors-1);
|
|
Packit |
78deda |
pm_message(" ignoring it... "
|
|
Packit |
78deda |
"colors might get messed up from here");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
if( reg != MP_REG_IGNORE ) {
|
|
Packit |
78deda |
PPM_ASSIGN(cmap->color[reg],
|
|
Packit |
78deda |
palchange[i].r, palchange[i].g, palchange[i].b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
multi_init(cmap, viewportmodes)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
long viewportmodes;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap->mp_init )
|
|
Packit |
78deda |
multi_adjust(cmap, -1, cmap->mp_init);
|
|
Packit |
78deda |
if( !(viewportmodes & vmLACE) )
|
|
Packit |
78deda |
cmap->mp_flags &= ~(MP_FLAGS_SKIPLACED);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
multi_update(cmap, row)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int row;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap->mp_flags & MP_FLAGS_SKIPLACED ) {
|
|
Packit |
78deda |
if( ODD(row) )
|
|
Packit |
78deda |
return;
|
|
Packit |
78deda |
if( row/2 < cmap->mp_rows && cmap->mp_change[row/2] )
|
|
Packit |
78deda |
multi_adjust(cmap, row, cmap->mp_change[row/2]);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
if( row < cmap->mp_rows && cmap->mp_change[row] )
|
|
Packit |
78deda |
multi_adjust(cmap, row, cmap->mp_change[row]);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
multi_free(cmap)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( cmap->mp_init ) {
|
|
Packit |
78deda |
free(cmap->mp_init);
|
|
Packit |
78deda |
cmap->mp_init = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( cmap->mp_change ) {
|
|
Packit |
78deda |
for( i = 0; i < cmap->mp_rows; i++ ) {
|
|
Packit |
78deda |
if( cmap->mp_change[i] )
|
|
Packit |
78deda |
free(cmap->mp_change[i]);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
free(cmap->mp_change);
|
|
Packit |
78deda |
cmap->mp_change = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
cmap->mp_rows = 0;
|
|
Packit |
78deda |
cmap->mp_type = 0;
|
|
Packit |
78deda |
cmap->mp_flags = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Colormap handling
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
analyzeCmapSamples(const ColorMap * const cmapP,
|
|
Packit |
78deda |
pixval * const maxSampleP,
|
|
Packit |
78deda |
bool * const shiftedP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixval maxSample;
|
|
Packit |
78deda |
bool shifted;
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0, maxSample = 0, shifted = true; i < cmapP->ncolors; ++i) {
|
|
Packit |
78deda |
pixval const r = PPM_GETR(cmapP->color[i]);
|
|
Packit |
78deda |
pixval const g = PPM_GETG(cmapP->color[i]);
|
|
Packit |
78deda |
pixval const b = PPM_GETB(cmapP->color[i]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
maxSample = MAX(maxSample, MAX(r, MAX(g, b)));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (r & 0x0f || g & 0x0f || b & 0x0f)
|
|
Packit |
78deda |
shifted = false;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*shiftedP = shifted;
|
|
Packit |
78deda |
*maxSampleP = maxSample;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
transformCmap(ColorMap * const cmapP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixval maxSample;
|
|
Packit |
78deda |
/* The maximum sample value in *cmapP input */
|
|
Packit |
78deda |
bool shifted;
|
|
Packit |
78deda |
/* Samples in the *cmapP input appear to be 4 bit (maxval 15) original
|
|
Packit |
78deda |
values shifted left 4 places to make 8 bit (maxval 255) samples.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
analyzeCmapSamples(cmapP, &maxSample, &shifted);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (maxSample == 0)
|
|
Packit |
78deda |
pm_message("warning - black colormap");
|
|
Packit |
78deda |
else if (shifted || maxSample <= 15) {
|
|
Packit |
78deda |
if (!adjustcolors) {
|
|
Packit |
78deda |
pm_message("warning - probably %s4-bit colormap",
|
|
Packit |
78deda |
shifted ? "shifted " : "");
|
|
Packit |
78deda |
pm_message("Use '-adjustcolors' to scale colormap to 8 bits");
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
pm_message("scaling colormap to 8 bits");
|
|
Packit |
78deda |
for (i = 0; i < cmapP->ncolors; ++i) {
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
r = PPM_GETR(cmapP->color[i]);
|
|
Packit |
78deda |
g = PPM_GETG(cmapP->color[i]);
|
|
Packit |
78deda |
b = PPM_GETB(cmapP->color[i]);
|
|
Packit |
78deda |
if (shifted) {
|
|
Packit |
78deda |
r >>= 4;
|
|
Packit |
78deda |
g >>= 4;
|
|
Packit |
78deda |
b >>= 4;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
r *= FACTOR_4BIT;
|
|
Packit |
78deda |
g *= FACTOR_4BIT;
|
|
Packit |
78deda |
b *= FACTOR_4BIT;
|
|
Packit |
78deda |
PPM_ASSIGN(cmapP->color[i], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixel *
|
|
Packit |
78deda |
transpColor(const BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmapP,
|
|
Packit |
78deda |
const char * const transpName,
|
|
Packit |
78deda |
pixval const maxval) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bmhdP) {
|
|
Packit |
78deda |
if (bmhdP->masking == mskHasTransparentColor ||
|
|
Packit |
78deda |
bmhdP->masking == mskLasso) {
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(transpColorP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (transpName)
|
|
Packit |
78deda |
*transpColorP = ppm_parsecolor(transpName, maxval);
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
unsigned short const transpIdx = bmhdP->transparentColor;
|
|
Packit |
78deda |
if (HAS_COLORMAP(cmapP)) {
|
|
Packit |
78deda |
if (transpIdx >= cmapP->ncolors) {
|
|
Packit |
78deda |
pm_message("using default transparent color (black)");
|
|
Packit |
78deda |
PPM_ASSIGN(*transpColorP, 0, 0, 0);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
*transpColorP = cmapP->color[transpIdx];
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
/* The color index is just a direct gray level */
|
|
Packit |
78deda |
PPM_ASSIGN(*transpColorP, transpIdx, transpIdx, transpIdx);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
transpColorP = NULL;
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
transpColorP = NULL;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return transpColorP;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
prepareCmap(const BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmapP) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
This is a really ugly subroutine that 1) analyzes a colormap and its
|
|
Packit |
78deda |
context (returning the analysis in global variables); and 2) modifies that
|
|
Packit |
78deda |
color map, because it's really one type of data structure as input and
|
|
Packit |
78deda |
another as output.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
bool bmhdCmapOk;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bmhdP)
|
|
Packit |
78deda |
bmhdCmapOk = (bmhdP->flags & BMHD_FLAGS_CMAPOK);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
bmhdCmapOk = false;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (HAS_COLORMAP(cmapP) && !bmhdCmapOk)
|
|
Packit |
78deda |
transformCmap(cmapP);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixval
|
|
Packit |
78deda |
lookup_red(cmap, oldval)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int oldval;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap && cmap->redlut && oldval < 256 )
|
|
Packit |
78deda |
return cmap->redlut[oldval];
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
return oldval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixval
|
|
Packit |
78deda |
lookup_green(cmap, oldval)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int oldval;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap && cmap->greenlut && oldval < 256 )
|
|
Packit |
78deda |
return cmap->greenlut[oldval];
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
return oldval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixval
|
|
Packit |
78deda |
lookup_blue(cmap, oldval)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int oldval;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap && cmap->bluelut && oldval < 256 )
|
|
Packit |
78deda |
return cmap->bluelut[oldval];
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
return oldval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixval
|
|
Packit |
78deda |
lookup_mono(cmap, oldval)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int oldval;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( cmap && cmap->monolut && oldval < 256 )
|
|
Packit |
78deda |
return cmap->monolut[oldval];
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
return oldval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static ColorMap *
|
|
Packit |
78deda |
ehbcmap(cmap)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
pixel *tempcolor = NULL;
|
|
Packit |
78deda |
int i, col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
col = cmap->ncolors;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
tempcolor = ppm_allocrow(col * 2);
|
|
Packit |
78deda |
for( i = 0; i < col; i++ ) {
|
|
Packit |
78deda |
tempcolor[i] = cmap->color[i];
|
|
Packit |
78deda |
PPM_ASSIGN(tempcolor[col + i], PPM_GETR(cmap->color[i]) / 2,
|
|
Packit |
78deda |
PPM_GETG(cmap->color[i]) / 2,
|
|
Packit |
78deda |
PPM_GETB(cmap->color[i]) / 2 );
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_freerow(cmap->color);
|
|
Packit |
78deda |
cmap->color = tempcolor;
|
|
Packit |
78deda |
cmap->ncolors *= 2;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return cmap;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static pixval
|
|
Packit |
78deda |
lut_maxval(ColorMap * const cmap,
|
|
Packit |
78deda |
pixval const maxval) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixval retval;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (maxval >= 255)
|
|
Packit |
78deda |
retval = maxval;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
if (!HAS_COLORLUT(cmap))
|
|
Packit |
78deda |
retval = maxval;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
unsigned char maxlut;
|
|
Packit |
78deda |
maxlut = maxval;
|
|
Packit |
78deda |
for( i = 0; i < maxval; i++ ) {
|
|
Packit |
78deda |
if( cmap->redlut && cmap->redlut[i] > maxlut )
|
|
Packit |
78deda |
maxlut = cmap->redlut[i];
|
|
Packit |
78deda |
if( cmap->greenlut && cmap->greenlut[i] > maxlut )
|
|
Packit |
78deda |
maxlut = cmap->greenlut[i];
|
|
Packit |
78deda |
if( cmap->bluelut && cmap->bluelut[i] > maxlut )
|
|
Packit |
78deda |
maxlut = cmap->bluelut[i];
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pm_message("warning - "
|
|
Packit |
78deda |
"%d-bit index into 8-bit color lookup table, "
|
|
Packit |
78deda |
"table maxval=%d",
|
|
Packit |
78deda |
pm_maxvaltobits(maxval), maxlut);
|
|
Packit |
78deda |
if( maxlut != maxval )
|
|
Packit |
78deda |
retval = 255;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
retval = maxval;
|
|
Packit |
78deda |
pm_message(" assuming image maxval=%d", retval);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return retval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
get_color(cmap, idx, red, green, blue)
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
int idx;
|
|
Packit |
78deda |
pixval *red, *green, *blue;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if( HAS_COLORMAP(cmap) ) {
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( idx >= cmap->ncolors )
|
|
Packit |
78deda |
pm_error("color index out of range: %d (max %d)",
|
|
Packit |
78deda |
idx, cmap->ncolors);
|
|
Packit |
78deda |
r = PPM_GETR(cmap->color[idx]);
|
|
Packit |
78deda |
g = PPM_GETG(cmap->color[idx]);
|
|
Packit |
78deda |
b = PPM_GETB(cmap->color[idx]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*red = lookup_red(cmap, r);
|
|
Packit |
78deda |
*green = lookup_green(cmap, g);
|
|
Packit |
78deda |
*blue = lookup_blue(cmap, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
*red = *green = *blue = lookup_mono(cmap, idx);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Conversion functions
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
std_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
long const viewportmodes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
ham_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
long const viewportmodes) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int cols, rows, hambits, hammask, hamshift, hammask2, col, row;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
rawtype *rawrow;
|
|
Packit |
78deda |
unsigned char hamlut[256];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cols = bmhdP->w;
|
|
Packit |
78deda |
rows = bmhdP->h;
|
|
Packit |
78deda |
hambits = bmhdP->nPlanes - 2;
|
|
Packit |
78deda |
hammask = (1 << hambits) - 1;
|
|
Packit |
78deda |
hamshift = 8 - hambits;
|
|
Packit |
78deda |
hammask2 = (1 << hamshift) - 1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( hambits > 8 || hambits < 1 ) {
|
|
Packit |
78deda |
int const assumed_viewportmodes = viewportmodes & ~(vmHAM);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("%d-plane HAM?? - interpreting image as a normal ILBM",
|
|
Packit |
78deda |
bmhdP->nPlanes);
|
|
Packit |
78deda |
std_to_ppm(ifP, chunksize, bmhdP, cmap, assumed_viewportmodes);
|
|
Packit |
78deda |
return;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a %sHAM%d file",
|
|
Packit |
78deda |
HAS_MULTIPALETTE(cmap) ? "multipalette " : "",
|
|
Packit |
78deda |
bmhdP->nPlanes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_COLORLUT(cmap) || HAS_MONOLUT(cmap) ) {
|
|
Packit |
78deda |
pm_message("warning - color lookup tables ignored in HAM");
|
|
Packit |
78deda |
if( cmap->redlut ) free(cmap->redlut);
|
|
Packit |
78deda |
if( cmap->greenlut ) free(cmap->greenlut);
|
|
Packit |
78deda |
if( cmap->bluelut ) free(cmap->bluelut);
|
|
Packit |
78deda |
if( cmap->monolut ) free(cmap->monolut);
|
|
Packit |
78deda |
cmap->redlut = cmap->greenlut = cmap->bluelut =
|
|
Packit |
78deda |
cmap->monolut = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( !HAS_COLORMAP(cmap) ) {
|
|
Packit |
78deda |
pm_message("no colormap - interpreting values as grayscale");
|
|
Packit |
78deda |
maxval = pm_bitstomaxval(hambits);
|
|
Packit |
78deda |
for( col = 0; col <= maxval; col++ )
|
|
Packit |
78deda |
hamlut[col] = col * MAXCOLVAL / maxval;
|
|
Packit |
78deda |
cmap->monolut = hamlut;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, MAXCOLVAL);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_init(cmap, viewportmodes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
rawrow = alloc_rawrow(cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(stdout, cols, rows, MAXCOLVAL, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_update(cmap, row);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP);
|
|
Packit |
78deda |
decode_mask(ifP, &remainingChunksize, rawrow, bmhdP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
r = g = b = 0;
|
|
Packit |
78deda |
for( col = 0; col < cols; col++ ) {
|
|
Packit |
78deda |
int idx = rawrow[col] & hammask;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
switch((rawrow[col] >> hambits) & 0x03) {
|
|
Packit |
78deda |
case HAMCODE_CMAP:
|
|
Packit |
78deda |
get_color(cmap, idx, &r, &g, &b);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case HAMCODE_BLUE:
|
|
Packit |
78deda |
b = ((b & hammask2) | (idx << hamshift));
|
|
Packit |
78deda |
/*b = hamlut[idx];*/
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case HAMCODE_RED:
|
|
Packit |
78deda |
r = ((r & hammask2) | (idx << hamshift));
|
|
Packit |
78deda |
/*r = hamlut[idx];*/
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case HAMCODE_GREEN:
|
|
Packit |
78deda |
g = ((g & hammask2) | (idx << hamshift));
|
|
Packit |
78deda |
/*g = hamlut[idx];*/
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("ham_to_ppm(): "
|
|
Packit |
78deda |
"impossible HAM code - can't happen");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
PPM_ASSIGN(pixelrow[col], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, MAXCOLVAL, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
std_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
long const viewportmodes) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (viewportmodes & vmHAM) {
|
|
Packit |
78deda |
ham_to_ppm(ifP, chunksize, bmhdP, cmap, viewportmodes);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int const cols = bmhdP->w;
|
|
Packit |
78deda |
unsigned int const rows = bmhdP->h;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
rawtype *rawrow;
|
|
Packit |
78deda |
unsigned int row, col;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a %d-plane %s%sILBM", bmhdP->nPlanes,
|
|
Packit |
78deda |
HAS_MULTIPALETTE(cmap) ? "multipalette " : "",
|
|
Packit |
78deda |
viewportmodes & vmEXTRA_HALFBRITE ? "EHB " : ""
|
|
Packit |
78deda |
);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->nPlanes > MAXPLANES )
|
|
Packit |
78deda |
pm_error("too many planes (max %d)", MAXPLANES);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_COLORMAP(cmap) ) {
|
|
Packit |
78deda |
if( viewportmodes & vmEXTRA_HALFBRITE )
|
|
Packit |
78deda |
ehbcmap(cmap); /* Modifies *cmap */
|
|
Packit |
78deda |
maxval = MAXCOLVAL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
pm_message("no colormap - interpreting values as grayscale");
|
|
Packit |
78deda |
maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes));
|
|
Packit |
78deda |
if( maxval > PPM_OVERALLMAXVAL )
|
|
Packit |
78deda |
pm_error("nPlanes is too large");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
rawrow = alloc_rawrow(cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_init(cmap, viewportmodes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit( stdout, cols, rows, maxval, 0 );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_update(cmap, row);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP);
|
|
Packit |
78deda |
decode_mask(ifP, &remainingChunksize, rawrow, bmhdP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( col = 0; col < cols; col++ ) {
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
get_color(cmap, rawrow[col], &r, &g, &b);
|
|
Packit |
78deda |
PPM_ASSIGN(pixelrow[col], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
deep_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const cols = bmhdP->w;
|
|
Packit |
78deda |
unsigned int const rows = bmhdP->h;
|
|
Packit |
78deda |
unsigned int const planespercolor = bmhdP->nPlanes / 3;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int col, row;
|
|
Packit |
78deda |
rawtype *Rrow, *Grow, *Brow;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a deep (%d-bit) ILBM", bmhdP->nPlanes);
|
|
Packit |
78deda |
if( planespercolor > MAXPLANES )
|
|
Packit |
78deda |
pm_error("too many planes (max %d)", MAXPLANES * 3);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->masking == mskHasTransparentColor ||
|
|
Packit |
78deda |
bmhdP->masking == mskLasso ) {
|
|
Packit |
78deda |
pm_message("masking type '%s' in a deep ILBM?? - ignoring it",
|
|
Packit |
78deda |
mskNAME[bmhdP->masking]);
|
|
Packit |
78deda |
bmhdP->masking = mskNone;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
maxval = lut_maxval(cmap, pm_bitstomaxval(planespercolor));
|
|
Packit |
78deda |
if( maxval > PPM_OVERALLMAXVAL )
|
|
Packit |
78deda |
pm_error("nPlanes is too large");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Rrow = alloc_rawrow(cols);
|
|
Packit |
78deda |
Grow = alloc_rawrow(cols);
|
|
Packit |
78deda |
Brow = alloc_rawrow(cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(stdout, cols, rows, maxval, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( row = 0; row < rows; row++ ) {
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Rrow, planespercolor, bmhdP);
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Grow, planespercolor, bmhdP);
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Brow, planespercolor, bmhdP);
|
|
Packit |
78deda |
decode_mask(ifP, &remainingChunksize, NULL, bmhdP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( col = 0; col < cols; col++ ) {
|
|
Packit |
78deda |
if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
PPM_ASSIGN(pixelrow[col], lookup_red(cmap, Rrow[col]),
|
|
Packit |
78deda |
lookup_green(cmap, Grow[col]),
|
|
Packit |
78deda |
lookup_blue(cmap, Brow[col]) );
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
dcol_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
DirectColor * const dcol) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const cols = bmhdP->w;
|
|
Packit |
78deda |
unsigned int const rows = bmhdP->h;
|
|
Packit |
78deda |
unsigned int const redplanes = dcol->r;
|
|
Packit |
78deda |
unsigned int const greenplanes = dcol->g;
|
|
Packit |
78deda |
unsigned int const blueplanes = dcol->b;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int col, row;
|
|
Packit |
78deda |
rawtype *Rrow, *Grow, *Brow;
|
|
Packit |
78deda |
pixval maxval, redmaxval, greenmaxval, bluemaxval;
|
|
Packit |
78deda |
pixval *redtable, *greentable, *bluetable;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a %d:%d:%d direct color ILBM",
|
|
Packit |
78deda |
redplanes, greenplanes, blueplanes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( redplanes > MAXPLANES ||
|
|
Packit |
78deda |
blueplanes > MAXPLANES ||
|
|
Packit |
78deda |
greenplanes > MAXPLANES )
|
|
Packit |
78deda |
pm_error("too many planes (max %d per color component)", MAXPLANES);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->nPlanes != (redplanes + greenplanes + blueplanes) )
|
|
Packit |
78deda |
pm_error("%s/%s plane number mismatch",
|
|
Packit |
78deda |
ID2string(ID_BMHD), ID2string(ID_DCOL));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->masking == mskHasTransparentColor ||
|
|
Packit |
78deda |
bmhdP->masking == mskLasso ) {
|
|
Packit |
78deda |
pm_message("masking type '%s' in a direct color ILBM?? - ignoring it",
|
|
Packit |
78deda |
mskNAME[bmhdP->masking]);
|
|
Packit |
78deda |
bmhdP->masking = mskNone;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_COLORLUT(cmap) ) {
|
|
Packit |
78deda |
pm_error("This program does not know how to process a %s chunk "
|
|
Packit |
78deda |
"in direct color", ID2string(ID_CLUT));
|
|
Packit |
78deda |
cmap->redlut = cmap->greenlut = cmap->bluelut = NULL;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
redmaxval = pm_bitstomaxval(redplanes);
|
|
Packit |
78deda |
greenmaxval = pm_bitstomaxval(greenplanes);
|
|
Packit |
78deda |
bluemaxval = pm_bitstomaxval(blueplanes);
|
|
Packit |
78deda |
maxval = MAX(redmaxval, MAX(greenmaxval, bluemaxval));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( maxval > PPM_OVERALLMAXVAL )
|
|
Packit |
78deda |
pm_error("too many planes");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( redmaxval != maxval || greenmaxval != maxval || bluemaxval != maxval )
|
|
Packit |
78deda |
pm_message("scaling colors to %d bits", pm_maxvaltobits(maxval));
|
|
Packit |
78deda |
|
|
Packit Service |
ad4525 |
overflow_add(redmaxval, 1);
|
|
Packit Service |
ad4525 |
overflow_add(greenmaxval, 1);
|
|
Packit Service |
ad4525 |
overflow_add(bluemaxval, 1);
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(redtable, redmaxval +1);
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(greentable, greenmaxval +1);
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(bluetable, bluemaxval +1);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
for (i = 0; i <= redmaxval; ++i)
|
|
Packit |
78deda |
redtable[i] = ROUNDDIV(i * maxval, redmaxval);
|
|
Packit |
78deda |
for (i = 0; i <= greenmaxval; ++i)
|
|
Packit |
78deda |
greentable[i] = ROUNDDIV(i * maxval, greenmaxval);
|
|
Packit |
78deda |
for (i = 0; i <= bluemaxval; ++i)
|
|
Packit |
78deda |
bluetable[i] = ROUNDDIV(i * maxval, bluemaxval);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Rrow = alloc_rawrow(cols);
|
|
Packit |
78deda |
Grow = alloc_rawrow(cols);
|
|
Packit |
78deda |
Brow = alloc_rawrow(cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(stdout, cols, rows, maxval, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( row = 0; row < rows; row++ ) {
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Rrow, redplanes, bmhdP);
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Grow, greenplanes, bmhdP);
|
|
Packit |
78deda |
decode_row(ifP, &remainingChunksize, Brow, blueplanes, bmhdP);
|
|
Packit |
78deda |
decode_mask(ifP, &remainingChunksize, NULL, bmhdP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( col = 0; col < cols; col++ ) {
|
|
Packit |
78deda |
if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
PPM_ASSIGN( pixelrow[col], redtable[Rrow[col]],
|
|
Packit |
78deda |
greentable[Grow[col]],
|
|
Packit |
78deda |
bluetable[Brow[col]] );
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
cmapToPpm(FILE * const ofP,
|
|
Packit |
78deda |
ColorMap * const cmapP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_colorrowtomapfile(ofP, cmapP->color, cmapP->ncolors, MAXCOLVAL);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
ipbm_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
long const viewportmodes) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const cols = bmhdP->w;
|
|
Packit |
78deda |
unsigned int const rows = bmhdP->h;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int col, row;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a %sPBM ",
|
|
Packit |
78deda |
HAS_MULTIPALETTE(cmap) ? "multipalette " : "");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->nPlanes != 8 )
|
|
Packit |
78deda |
pm_error("invalid number of planes for IFF-PBM: %d (must be 8)",
|
|
Packit |
78deda |
bmhdP->nPlanes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( bmhdP->masking == mskHasMask )
|
|
Packit |
78deda |
pm_error("Image has a maskplane, which is invalid in IFF-PBM");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_COLORMAP(cmap) )
|
|
Packit |
78deda |
maxval = MAXCOLVAL;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
pm_message("no colormap - interpreting values as grayscale");
|
|
Packit |
78deda |
maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_init(cmap, viewportmodes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(ilbmrow, cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(stdout, cols, rows, maxval, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( row = 0; row < rows; row++ ) {
|
|
Packit |
78deda |
if( HAS_MULTIPALETTE(cmap) )
|
|
Packit |
78deda |
multi_update(cmap, row);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
read_ilbm_plane(ifP, &remainingChunksize, cols, bmhdP->compression);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( col = 0; col < cols; col++ ) {
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
get_color(cmap, ilbmrow[col], &r, &g, &b);
|
|
Packit |
78deda |
PPM_ASSIGN(pixelrow[col], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
rgbn_to_ppm(FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap /* for CLUTs */
|
|
Packit |
78deda |
) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const rows = bmhdP->h;
|
|
Packit |
78deda |
unsigned int const cols = bmhdP->w;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
unsigned int count;
|
|
Packit |
78deda |
pixval maxval;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
pixel * transpColorP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_message("input is a %d-bit RGB image", (typeid == ID_RGB8 ? 8 : 4));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bmhdP->compression != 4)
|
|
Packit |
78deda |
pm_error("invalid compression mode for %s: %d (must be 4)",
|
|
Packit |
78deda |
ID2string(typeid), bmhdP->compression);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (typeid) {
|
|
Packit |
78deda |
case ID_RGBN:
|
|
Packit |
78deda |
if (bmhdP->nPlanes != 13)
|
|
Packit |
78deda |
pm_error("invalid number of planes for %s: %d (must be 13)",
|
|
Packit |
78deda |
ID2string(typeid), bmhdP->nPlanes);
|
|
Packit |
78deda |
maxval = lut_maxval(cmap, 15);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_RGB8:
|
|
Packit |
78deda |
if (bmhdP->nPlanes != 25)
|
|
Packit |
78deda |
pm_error("invalid number of planes for %s: %d (must be 25)",
|
|
Packit |
78deda |
ID2string(typeid), bmhdP->nPlanes);
|
|
Packit |
78deda |
maxval = 255;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen",
|
|
Packit |
78deda |
ID2string(typeid));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(stdout, cols, rows, maxval, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0, count = 0, remainingChunksize = chunksize;
|
|
Packit |
78deda |
row < rows;
|
|
Packit |
78deda |
++row) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col) {
|
|
Packit |
78deda |
unsigned int tries;
|
|
Packit |
78deda |
unsigned int genlock;
|
|
Packit |
78deda |
pixval r, g, b;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
tries = 0;
|
|
Packit |
78deda |
while (count == 0) {
|
|
Packit |
78deda |
if (typeid == ID_RGB8) {
|
|
Packit |
78deda |
r = lookup_red(cmap, get_byte(ifP, ID_BODY,
|
|
Packit |
78deda |
&remainingChunksize));
|
|
Packit |
78deda |
g = lookup_green(cmap, get_byte(ifP, ID_BODY,
|
|
Packit |
78deda |
&remainingChunksize));
|
|
Packit |
78deda |
b = lookup_blue(cmap, get_byte(ifP, ID_BODY,
|
|
Packit |
78deda |
&remainingChunksize));
|
|
Packit |
78deda |
count = get_byte(ifP, ID_BODY, &remainingChunksize);
|
|
Packit |
78deda |
genlock = count & 0x80;
|
|
Packit |
78deda |
count &= 0x7f;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
unsigned int const word =
|
|
Packit |
78deda |
get_big_short(ifP, ID_BODY, &remainingChunksize);
|
|
Packit |
78deda |
r = lookup_red(cmap, (word & 0xf000) >> 12);
|
|
Packit |
78deda |
g = lookup_green(cmap, (word & 0x0f00) >> 8);
|
|
Packit |
78deda |
b = lookup_blue(cmap, (word & 0x00f0) >> 4);
|
|
Packit |
78deda |
genlock = word & 0x0008;
|
|
Packit |
78deda |
count = word & 0x0007;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (!count) {
|
|
Packit |
78deda |
count = get_byte(ifP, ID_BODY, &remainingChunksize);
|
|
Packit |
78deda |
if (count == 0)
|
|
Packit |
78deda |
count =
|
|
Packit |
78deda |
get_big_short(ifP, ID_BODY, &remainingChunksize);
|
|
Packit |
78deda |
if (count == 0)
|
|
Packit |
78deda |
++tries;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (tries > 0) {
|
|
Packit |
78deda |
pm_message("warning - repeat count 0 at col %u row %u: "
|
|
Packit |
78deda |
"skipped %u RGB entr%s",
|
|
Packit |
78deda |
col, row, tries, (tries == 1 ? "y" : "ies"));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
/* genlock bit set -> transparent */
|
|
Packit |
78deda |
if (genlock)
|
|
Packit |
78deda |
maskrow[col] = PBM_WHITE;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
maskrow[col] = PBM_BLACK;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (transpColorP && maskrow && maskrow[col] == PBM_WHITE)
|
|
Packit |
78deda |
pixelrow[col] = *transpColorP;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
PPM_ASSIGN(pixelrow[col], r, g, b);
|
|
Packit |
78deda |
--count;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
pbm_writepbmrow(maskfile, maskrow, cols, 0);
|
|
Packit |
78deda |
wrotemask = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, ID_BODY, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/****************************************************************************
|
|
Packit |
78deda |
Multipalette chunk reader
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Currently there are three multipalette formats:
|
|
Packit |
78deda |
SHAM - sliced HAM (obselete)
|
|
Packit |
78deda |
CTBL - dynamic HAM/Hires (obselete)
|
|
Packit |
78deda |
PCHG - palette change
|
|
Packit |
78deda |
There is no official documentation available for SHAM and CTBL, so
|
|
Packit |
78deda |
this is mostly guesswork from other sources and hexdumps of pictures...
|
|
Packit |
78deda |
|
|
Packit |
78deda |
CTBL format (dynamic HAM/Hires):
|
|
Packit |
78deda |
16 bigendian words per row (16 bit: 0000rrrrggggbbbb)
|
|
Packit |
78deda |
This is simply an entire 4-bit colormap per row.
|
|
Packit |
78deda |
I have no idea what the DYCP chunk is for.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
SHAM format (sliced HAM):
|
|
Packit |
78deda |
1 word - version info (?) - always 0
|
|
Packit |
78deda |
16 bigendian words per row (16 bit: 0000rrrrggggbbbb)
|
|
Packit |
78deda |
If the picture is laced, then there are only rows/2 changes, don't change
|
|
Packit |
78deda |
palette on odd lines.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
PCHG format: A detailed description of this format is available
|
|
Packit |
78deda |
from AmiNet as PCHGLib12.lha.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Turn big-endian 4-byte long and 2-byte short stored at x (unsigned char *)
|
|
Packit |
78deda |
* into the native format of the CPU
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
#define BIG_LONG(x) ( ((unsigned long)((x)[0]) << 24) + \
|
|
Packit |
78deda |
((unsigned long)((x)[1]) << 16) + \
|
|
Packit |
78deda |
((unsigned long)((x)[2]) << 8) + \
|
|
Packit |
78deda |
((unsigned long)((x)[3]) << 0) )
|
|
Packit |
78deda |
#define BIG_WORD(x) ( ((unsigned short)((x)[0]) << 8) + \
|
|
Packit |
78deda |
((unsigned short)((x)[1]) << 0) )
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_4bit_mp(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int row, rows, i, type;
|
|
Packit |
78deda |
short data;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
type = (iffid == ID_SHAM ? MP_TYPE_SHAM : MP_TYPE_CTBL);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( cmap->mp_type >= type ) {
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
if( cmap->mp_type )
|
|
Packit |
78deda |
multi_free(cmap);
|
|
Packit |
78deda |
cmap->mp_type = type;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( type == MP_TYPE_SHAM ) {
|
|
Packit |
78deda |
cmap->mp_flags = MP_FLAGS_SKIPLACED;
|
|
Packit |
78deda |
get_big_short(ifP, iffid, &remainingChunksize); /* skip first wd */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmap->mp_rows = rows = remainingChunksize/32; /* sizeof(word) * 16 */
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_change, rows);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( row = 0; row < rows; row++ ) {
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_change[row], 17); /* 16 + sentinel */
|
|
Packit |
78deda |
for( i = 0; i < 16; i++ ) {
|
|
Packit |
78deda |
data = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
cmap->mp_change[row][i].reg = i;
|
|
Packit |
78deda |
cmap->mp_change[row][i].r =
|
|
Packit |
78deda |
((data & 0x0f00) >> 8) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_change[row][i].g =
|
|
Packit |
78deda |
((data & 0x00f0) >> 4) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_change[row][i].b =
|
|
Packit |
78deda |
((data & 0x000f) >> 0) * FACTOR_4BIT;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
cmap->mp_change[row][16].reg = MP_REG_END; /* sentinel */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
chunk_end(ifP, iffid, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PCHG_DecompHuff(src, dest, tree, origsize)
|
|
Packit |
78deda |
unsigned char *src, *dest;
|
|
Packit |
78deda |
short *tree;
|
|
Packit |
78deda |
unsigned long origsize;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned long i = 0, bits = 0;
|
|
Packit |
78deda |
unsigned char thisbyte;
|
|
Packit |
78deda |
short *p;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
p = tree;
|
|
Packit |
78deda |
while( i < origsize ) {
|
|
Packit |
78deda |
if( bits == 0 ) {
|
|
Packit |
78deda |
thisbyte = *src++;
|
|
Packit |
78deda |
bits = 8;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( thisbyte & (1 << 7) ) {
|
|
Packit |
78deda |
if( *p >= 0 ) {
|
|
Packit |
78deda |
*dest++ = (unsigned char)*p;
|
|
Packit |
78deda |
i++;
|
|
Packit |
78deda |
p = tree;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
p += (*p / 2);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
p--;
|
|
Packit |
78deda |
if( *p > 0 && (*p & 0x100) ) {
|
|
Packit |
78deda |
*dest++ = (unsigned char )*p;
|
|
Packit |
78deda |
i++;
|
|
Packit |
78deda |
p = tree;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
thisbyte <<= 1;
|
|
Packit |
78deda |
bits--;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PCHG_Decompress(PCHGHeader * const PCHG,
|
|
Packit |
78deda |
PCHGCompHeader * const CompHdr,
|
|
Packit |
78deda |
unsigned char * const compdata,
|
|
Packit |
78deda |
unsigned long const compsize,
|
|
Packit |
78deda |
unsigned char * const comptree,
|
|
Packit |
78deda |
unsigned char * const data) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch(PCHG->Compression) {
|
|
Packit |
78deda |
case PCHG_COMP_HUFFMAN: {
|
|
Packit |
78deda |
unsigned long const treesize = CompHdr->CompInfoSize;
|
|
Packit |
78deda |
unsigned long const huffsize = treesize / 2;
|
|
Packit |
78deda |
const bigend16 * const bigendComptree = (const void *)comptree;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
short * hufftree;
|
|
Packit |
78deda |
unsigned long i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Convert big-endian 2-byte shorts to C shorts */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY(hufftree, huffsize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!hufftree)
|
|
Packit |
78deda |
pm_error("Couldn't get memory for %lu-byte Huffman tree",
|
|
Packit |
78deda |
huffsize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < huffsize; ++i)
|
|
Packit |
78deda |
hufftree[i] = pm_uintFromBigend16(bigendComptree[i]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* decompress the change structure data */
|
|
Packit |
78deda |
PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1],
|
|
Packit |
78deda |
CompHdr->OriginalDataSize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(hufftree);
|
|
Packit |
78deda |
} break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_error("unknown PCHG compression type %d", PCHG->Compression);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PCHG_ConvertSmall(PCHG, cmap, mask, datasize)
|
|
Packit |
78deda |
PCHGHeader *PCHG;
|
|
Packit |
78deda |
ColorMap *cmap;
|
|
Packit |
78deda |
unsigned char *mask;
|
|
Packit |
78deda |
unsigned long datasize;
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned char *data;
|
|
Packit |
78deda |
unsigned char thismask;
|
|
Packit |
78deda |
int bits, row, i, changes, masklen, reg;
|
|
Packit |
78deda |
unsigned char ChangeCount16, ChangeCount32;
|
|
Packit |
78deda |
unsigned short SmallChange;
|
|
Packit |
78deda |
unsigned long totalchanges = 0;
|
|
Packit |
78deda |
int changedlines = PCHG->ChangedLines;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
masklen = 4 * MaskLongWords(PCHG->LineCount);
|
|
Packit |
78deda |
data = mask + masklen; datasize -= masklen;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bits = 0;
|
|
Packit |
78deda |
for( row = PCHG->StartLine; changedlines && row < 0; row++ ) {
|
|
Packit |
78deda |
if( bits == 0 ) {
|
|
Packit |
78deda |
if( masklen == 0 ) goto fail2;
|
|
Packit |
78deda |
thismask = *mask++;
|
|
Packit |
78deda |
--masklen;
|
|
Packit |
78deda |
bits = 8;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( thismask & (1<<7) ) {
|
|
Packit |
78deda |
if( datasize < 2 ) goto fail;
|
|
Packit |
78deda |
ChangeCount16 = *data++;
|
|
Packit |
78deda |
ChangeCount32 = *data++;
|
|
Packit |
78deda |
datasize -= 2;
|
|
Packit |
78deda |
|
|
Packit Service |
ad4525 |
overflow_add(ChangeCount16, ChangeCount32);
|
|
Packit |
78deda |
changes = ChangeCount16 + ChangeCount32;
|
|
Packit Service |
ad4525 |
overflow_add(changes, 1);
|
|
Packit |
78deda |
for( i = 0; i < changes; i++ ) {
|
|
Packit |
78deda |
if( totalchanges >= PCHG->TotalChanges ) goto fail;
|
|
Packit |
78deda |
if( datasize < 2 ) goto fail;
|
|
Packit |
78deda |
SmallChange = BIG_WORD(data); data += 2; datasize -= 2;
|
|
Packit |
78deda |
reg = ((SmallChange & 0xf000) >> 12) +
|
|
Packit |
78deda |
(i >= ChangeCount16 ? 16 : 0);
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].reg = reg;
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].r =
|
|
Packit |
78deda |
((SmallChange & 0x0f00) >> 8) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].g =
|
|
Packit |
78deda |
((SmallChange & 0x00f0) >> 4) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].b =
|
|
Packit |
78deda |
((SmallChange & 0x000f) >> 0) * FACTOR_4BIT;
|
|
Packit |
78deda |
++totalchanges;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
--changedlines;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
thismask <<= 1;
|
|
Packit |
78deda |
bits--;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for( row = PCHG->StartLine; changedlines && row < cmap->mp_rows; row++ ) {
|
|
Packit |
78deda |
if( bits == 0 ) {
|
|
Packit |
78deda |
if( masklen == 0 ) goto fail2;
|
|
Packit |
78deda |
thismask = *mask++;
|
|
Packit |
78deda |
--masklen;
|
|
Packit |
78deda |
bits = 8;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( thismask & (1<<7) ) {
|
|
Packit |
78deda |
if( datasize < 2 ) goto fail;
|
|
Packit |
78deda |
ChangeCount16 = *data++;
|
|
Packit |
78deda |
ChangeCount32 = *data++;
|
|
Packit |
78deda |
datasize -= 2;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
changes = ChangeCount16 + ChangeCount32;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
|
|
Packit |
78deda |
for( i = 0; i < changes; i++ ) {
|
|
Packit |
78deda |
if( totalchanges >= PCHG->TotalChanges ) goto fail;
|
|
Packit |
78deda |
if( datasize < 2 ) goto fail;
|
|
Packit |
78deda |
SmallChange = BIG_WORD(data); data += 2; datasize -= 2;
|
|
Packit |
78deda |
reg = ((SmallChange & 0xf000) >> 12) +
|
|
Packit |
78deda |
(i >= ChangeCount16 ? 16 : 0);
|
|
Packit |
78deda |
cmap->mp_change[row][i].reg = reg;
|
|
Packit |
78deda |
cmap->mp_change[row][i].r =
|
|
Packit |
78deda |
((SmallChange & 0x0f00) >> 8) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_change[row][i].g =
|
|
Packit |
78deda |
((SmallChange & 0x00f0) >> 4) * FACTOR_4BIT;
|
|
Packit |
78deda |
cmap->mp_change[row][i].b =
|
|
Packit |
78deda |
((SmallChange & 0x000f) >> 0) * FACTOR_4BIT;
|
|
Packit |
78deda |
++totalchanges;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
cmap->mp_change[row][changes].reg = MP_REG_END;
|
|
Packit |
78deda |
--changedlines;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
thismask <<= 1;
|
|
Packit |
78deda |
bits--;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if( totalchanges != PCHG->TotalChanges )
|
|
Packit |
78deda |
pm_message("warning - got %ld change structures, "
|
|
Packit |
78deda |
"chunk header reports %ld",
|
|
Packit |
78deda |
totalchanges, PCHG->TotalChanges);
|
|
Packit |
78deda |
return;
|
|
Packit |
78deda |
fail:
|
|
Packit |
78deda |
pm_error("insufficient data in SmallLineChanges structures");
|
|
Packit |
78deda |
fail2:
|
|
Packit |
78deda |
pm_error("insufficient data in line mask");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
PCHG_ConvertBig(PCHGHeader * const PCHG,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
unsigned char * const maskStart,
|
|
Packit |
78deda |
unsigned long const datasize) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned char * data;
|
|
Packit |
78deda |
unsigned char thismask;
|
|
Packit |
78deda |
int bits;
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
int changes;
|
|
Packit |
78deda |
int masklen;
|
|
Packit |
78deda |
int reg;
|
|
Packit |
78deda |
unsigned long totalchanges;
|
|
Packit |
78deda |
int changedlines;
|
|
Packit |
78deda |
unsigned long dataRemaining;
|
|
Packit |
78deda |
unsigned char * mask;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
mask = maskStart; /* initial value */
|
|
Packit |
78deda |
dataRemaining = datasize; /* initial value */
|
|
Packit |
78deda |
changedlines = PCHG->ChangedLines; /* initial value */
|
|
Packit |
78deda |
totalchanges = 0; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
masklen = 4 * MaskLongWords(PCHG->LineCount);
|
|
Packit |
78deda |
data = mask + masklen; dataRemaining -= masklen;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = PCHG->StartLine, bits = 0; changedlines && row < 0; ++row) {
|
|
Packit |
78deda |
if (bits == 0) {
|
|
Packit |
78deda |
if (masklen == 0)
|
|
Packit |
78deda |
pm_error("insufficient data in line mask");
|
|
Packit |
78deda |
thismask = *mask++;
|
|
Packit |
78deda |
--masklen;
|
|
Packit |
78deda |
bits = 8;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (thismask & (1<<7)) {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (dataRemaining < 2)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < changes; ++i) {
|
|
Packit |
78deda |
if (totalchanges >= PCHG->TotalChanges)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (dataRemaining < 6)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
reg = BIG_WORD(data); data += 2;
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].reg = reg;
|
|
Packit |
78deda |
++data; /* skip alpha */
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].r = *data++;
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].b = *data++; /* yes, RBG */
|
|
Packit |
78deda |
cmap->mp_init[reg - PCHG->MinReg].g = *data++;
|
|
Packit |
78deda |
dataRemaining -= 6;
|
|
Packit |
78deda |
++totalchanges;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
--changedlines;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
thismask <<= 1;
|
|
Packit |
78deda |
--bits;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = PCHG->StartLine; changedlines && row < cmap->mp_rows; ++row) {
|
|
Packit |
78deda |
if (bits == 0) {
|
|
Packit |
78deda |
if (masklen == 0)
|
|
Packit |
78deda |
pm_error("insufficient data in line mask");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
thismask = *mask++;
|
|
Packit |
78deda |
--masklen;
|
|
Packit |
78deda |
bits = 8;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (thismask & (1<<7)) {
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (dataRemaining < 2)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
|
|
Packit |
78deda |
for (i = 0; i < changes; ++i) {
|
|
Packit |
78deda |
if (totalchanges >= PCHG->TotalChanges)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (dataRemaining < 6)
|
|
Packit |
78deda |
pm_error("insufficient data in BigLineChanges structures");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
reg = BIG_WORD(data); data += 2;
|
|
Packit |
78deda |
cmap->mp_change[row][i].reg = reg;
|
|
Packit |
78deda |
++data; /* skip alpha */
|
|
Packit |
78deda |
cmap->mp_change[row][i].r = *data++;
|
|
Packit |
78deda |
cmap->mp_change[row][i].b = *data++; /* yes, RBG */
|
|
Packit |
78deda |
cmap->mp_change[row][i].g = *data++;
|
|
Packit |
78deda |
dataRemaining -= 6;
|
|
Packit |
78deda |
++totalchanges;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
cmap->mp_change[row][changes].reg = MP_REG_END;
|
|
Packit |
78deda |
--changedlines;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
thismask <<= 1;
|
|
Packit |
78deda |
--bits;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (totalchanges != PCHG->TotalChanges)
|
|
Packit |
78deda |
pm_message("warning - got %ld change structures, "
|
|
Packit |
78deda |
"chunk header reports %ld",
|
|
Packit |
78deda |
totalchanges, PCHG->TotalChanges);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_pchg(FILE * const ifP,
|
|
Packit |
78deda |
IFF_ID const iffid,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
ColorMap * const cmap) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( cmap->mp_type >= MP_TYPE_PCHG ) {
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
PCHGHeader PCHG;
|
|
Packit |
78deda |
unsigned char *data;
|
|
Packit |
78deda |
unsigned long datasize;
|
|
Packit |
78deda |
unsigned long remainingChunksize;
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( cmap->mp_type )
|
|
Packit |
78deda |
multi_free(cmap);
|
|
Packit |
78deda |
cmap->mp_type = MP_TYPE_PCHG;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
remainingChunksize = chunksize; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
PCHG.Compression = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.Flags = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.StartLine = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.LineCount = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.ChangedLines= get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.MinReg = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.MaxReg = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.MaxChanges = get_big_short(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
PCHG.TotalChanges= get_big_long(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#ifdef DEBUG
|
|
Packit |
78deda |
pm_message("PCHG StartLine : %d", PCHG.StartLine);
|
|
Packit |
78deda |
pm_message("PCHG LineCount : %d", PCHG.LineCount);
|
|
Packit |
78deda |
pm_message("PCHG ChangedLines: %d", PCHG.ChangedLines);
|
|
Packit |
78deda |
pm_message("PCHG TotalChanges: %d", PCHG.TotalChanges);
|
|
Packit |
78deda |
#endif
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( PCHG.Compression != PCHG_COMP_NONE ) {
|
|
Packit |
78deda |
PCHGCompHeader CompHdr;
|
|
Packit |
78deda |
unsigned char *compdata, *comptree;
|
|
Packit |
78deda |
long treesize, compsize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
CompHdr.CompInfoSize =
|
|
Packit |
78deda |
get_big_long(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
CompHdr.OriginalDataSize =
|
|
Packit |
78deda |
get_big_long(ifP, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
treesize = CompHdr.CompInfoSize;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(comptree, treesize);
|
|
Packit |
78deda |
read_bytes(ifP, treesize, comptree, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
compsize = remainingChunksize;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(compdata, compsize);
|
|
Packit |
78deda |
read_bytes(ifP, compsize, compdata, iffid, &remainingChunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
datasize = CompHdr.OriginalDataSize;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(data, datasize);
|
|
Packit |
78deda |
PCHG_Decompress(&PCHG, &CompHdr, compdata,
|
|
Packit |
78deda |
compsize, comptree, data);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(comptree);
|
|
Packit |
78deda |
free(compdata);
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
#ifdef DEBUG
|
|
Packit |
78deda |
pm_message("uncompressed PCHG");
|
|
Packit |
78deda |
#endif
|
|
Packit |
78deda |
datasize = remainingChunksize;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(data, datasize);
|
|
Packit |
78deda |
read_bytes(ifP, datasize, data, iffid, &remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( PCHG.Flags & PCHGF_USE_ALPHA )
|
|
Packit |
78deda |
pm_message("warning - ignoring PCHG alpha channel because "
|
|
Packit |
78deda |
"this program doesn't know what to do with it");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmap->mp_rows = PCHG.StartLine + PCHG.LineCount;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_change, cmap->mp_rows);
|
|
Packit |
78deda |
for( i = 0; i < cmap->mp_rows; i++ )
|
|
Packit |
78deda |
cmap->mp_change[i] = NULL;
|
|
Packit |
78deda |
if( PCHG.StartLine < 0 ) {
|
|
Packit |
78deda |
int nch;
|
|
Packit Service |
ad4525 |
if(PCHG.MaxReg < PCHG.MinReg)
|
|
Packit Service |
ad4525 |
pm_error("assert: MinReg > MaxReg");
|
|
Packit Service |
ad4525 |
overflow_add(PCHG.MaxReg-PCHG.MinReg, 2);
|
|
Packit |
78deda |
nch = PCHG.MaxReg - PCHG.MinReg +1;
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(cmap->mp_init, nch + 1);
|
|
Packit |
78deda |
for( i = 0; i < nch; i++ )
|
|
Packit |
78deda |
cmap->mp_init[i].reg = MP_REG_IGNORE;
|
|
Packit |
78deda |
cmap->mp_init[nch].reg = MP_REG_END;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( PCHG.Flags & PCHGF_12BIT ) {
|
|
Packit |
78deda |
#ifdef DEBUG
|
|
Packit |
78deda |
pm_message("SmallLineChanges");
|
|
Packit |
78deda |
#endif
|
|
Packit |
78deda |
PCHG_ConvertSmall(&PCHG, cmap, data, datasize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
if( PCHG.Flags & PCHGF_32BIT ) {
|
|
Packit |
78deda |
#ifdef DEBUG
|
|
Packit |
78deda |
pm_message("BigLineChanges");
|
|
Packit |
78deda |
#endif
|
|
Packit |
78deda |
PCHG_ConvertBig(&PCHG, cmap, data, datasize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_error("unknown palette changes structure "
|
|
Packit |
78deda |
"format in %s chunk",
|
|
Packit |
78deda |
ID2string(iffid));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
free(data);
|
|
Packit |
78deda |
chunk_end(ifP, iffid, remainingChunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static bool
|
|
Packit |
78deda |
ignored_iffid(IFF_ID const iffid,
|
|
Packit |
78deda |
IFF_ID const ignorelist[],
|
|
Packit |
78deda |
unsigned int const ignorecount) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bool ignore;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
ignore = FALSE; /* initial assumption */
|
|
Packit |
78deda |
for( i = 0; i < ignorecount && !ignore; i++ ) {
|
|
Packit |
78deda |
if( iffid == ignorelist[i] )
|
|
Packit |
78deda |
ignore = TRUE;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return ignore;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
process_body( FILE * const ifP,
|
|
Packit |
78deda |
long const chunksize,
|
|
Packit |
78deda |
BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
FILE * const maskfile,
|
|
Packit |
78deda |
int const fakeviewport,
|
|
Packit |
78deda |
int const isdeepopt,
|
|
Packit |
78deda |
DirectColor * const dcol,
|
|
Packit |
78deda |
int * const viewportmodesP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bmhdP == NULL)
|
|
Packit |
78deda |
pm_error("%s chunk without %s chunk",
|
|
Packit |
78deda |
ID2string(ID_BODY), ID2string(ID_BMHD));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
prepareCmap(bmhdP, cmap);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pixelrow = ppm_allocrow(bmhdP->w);
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
maskrow = pbm_allocrow(bmhdP->w);
|
|
Packit |
78deda |
pbm_writepbminit(maskfile, bmhdP->w, bmhdP->h, 0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (typeid == ID_ILBM) {
|
|
Packit |
78deda |
int isdeep;
|
|
Packit |
78deda |
|
|
Packit Service |
ad4525 |
overflow_add(bmhdP->w, 15);
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(ilbmrow, RowBytes(bmhdP->w));
|
|
Packit |
78deda |
*viewportmodesP |= fakeviewport; /* -isham/-isehb */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( isdeepopt > 0 && (bmhdP->nPlanes % 3 != 0) ) {
|
|
Packit |
78deda |
pm_message("cannot interpret %d-plane image as 'deep' "
|
|
Packit |
78deda |
"(# of planes must be divisible by 3)",
|
|
Packit |
78deda |
bmhdP->nPlanes);
|
|
Packit |
78deda |
isdeep = 0;
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
isdeep = isdeepopt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (isdeep > 0)
|
|
Packit |
78deda |
deep_to_ppm(ifP, chunksize, bmhdP, cmap);
|
|
Packit |
78deda |
else if (dcol)
|
|
Packit |
78deda |
dcol_to_ppm(ifP, chunksize, bmhdP, cmap, dcol);
|
|
Packit |
78deda |
else if (bmhdP->nPlanes > 8) {
|
|
Packit |
78deda |
if (bmhdP->nPlanes <= 16 && HAS_COLORMAP(cmap))
|
|
Packit |
78deda |
std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
|
|
Packit |
78deda |
else if (isdeep >= 0 && (bmhdP->nPlanes % 3 == 0))
|
|
Packit |
78deda |
deep_to_ppm(ifP, chunksize, bmhdP, cmap);
|
|
Packit |
78deda |
else if (bmhdP->nPlanes <= 16)
|
|
Packit |
78deda |
/* will be interpreted as grayscale */
|
|
Packit |
78deda |
std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_error("don't know how to interpret %d-plane image",
|
|
Packit |
78deda |
bmhdP->nPlanes);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
|
|
Packit |
78deda |
} else if( typeid == ID_PBM )
|
|
Packit |
78deda |
ipbm_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
|
|
Packit |
78deda |
else /* RGBN or RGB8 */
|
|
Packit |
78deda |
rgbn_to_ppm(ifP, chunksize, bmhdP, cmap);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
processChunk(FILE * const ifP,
|
|
Packit |
78deda |
long const formsize,
|
|
Packit |
78deda |
IFF_ID const ignorelist[],
|
|
Packit |
78deda |
unsigned int const ignorecount,
|
|
Packit |
78deda |
int const fakeviewport,
|
|
Packit |
78deda |
int const viewportmask,
|
|
Packit |
78deda |
int const isdeepopt,
|
|
Packit |
78deda |
bool const cmaponly,
|
|
Packit |
78deda |
bool * const bodyChunkProcessedP,
|
|
Packit |
78deda |
bool * const endchunkP,
|
|
Packit |
78deda |
BitMapHeader ** const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmap,
|
|
Packit |
78deda |
DirectColor ** const dcolP,
|
|
Packit |
78deda |
int * const viewportmodesP,
|
|
Packit |
78deda |
long * const bytesReadP
|
|
Packit |
78deda |
) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
IFF_ID iffid;
|
|
Packit |
78deda |
long chunksize;
|
|
Packit |
78deda |
long bytesread;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesread = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
iffid = get_big_long(ifP, ID_FORM, NULL);
|
|
Packit |
78deda |
chunksize = get_big_long(ifP, iffid, NULL);
|
|
Packit |
78deda |
bytesread += 8;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (debug)
|
|
Packit |
78deda |
pm_message("reading %s chunk: %ld bytes", ID2string(iffid), chunksize);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (ignored_iffid(iffid, ignorelist, ignorecount)) {
|
|
Packit |
78deda |
pm_message("ignoring %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else if (iffid == ID_END) {
|
|
Packit |
78deda |
/* END chunks are not officially valid in IFF, but
|
|
Packit |
78deda |
suggested as a future expansion for stream-writing,
|
|
Packit |
78deda |
see Amiga RKM Devices, 3rd Ed, page 376
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (chunksize != 0 ) {
|
|
Packit |
78deda |
pm_message("warning - non-0 %s chunk", ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
if (formsize != 0xffffffff)
|
|
Packit |
78deda |
pm_message("warning - %s chunk with FORM size 0x%08lx "
|
|
Packit |
78deda |
"(should be 0x%08x)",
|
|
Packit |
78deda |
ID2string(iffid), formsize, 0xffffffff);
|
|
Packit |
78deda |
*endchunkP = 1;
|
|
Packit |
78deda |
} else if (*bodyChunkProcessedP) {
|
|
Packit |
78deda |
pm_message("%s chunk found after %s chunk - skipping",
|
|
Packit |
78deda |
ID2string(iffid), ID2string(ID_BODY));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
switch (iffid) {
|
|
Packit |
78deda |
case ID_BMHD:
|
|
Packit |
78deda |
*bmhdP = read_bmhd(ifP, iffid, chunksize);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_CMAP:
|
|
Packit |
78deda |
read_cmap(ifP, iffid, chunksize, cmap);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_CMYK:
|
|
Packit |
78deda |
read_cmyk(ifP, iffid, chunksize, cmap);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_CLUT:
|
|
Packit |
78deda |
read_clut(ifP, iffid, chunksize, cmap);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_CAMG:
|
|
Packit |
78deda |
if (chunksize != CAMGChunkSize)
|
|
Packit |
78deda |
pm_error("%s chunk size mismatch", ID2string(iffid));
|
|
Packit |
78deda |
*viewportmodesP = get_big_long(ifP, ID_CAMG, NULL);
|
|
Packit |
78deda |
*viewportmodesP &= viewportmask; /* -isnotham/-isnotehb */
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_PCHG:
|
|
Packit |
78deda |
read_pchg(ifP, iffid, chunksize, cmap);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_CTBL:
|
|
Packit |
78deda |
case ID_SHAM:
|
|
Packit |
78deda |
read_4bit_mp(ifP, iffid, chunksize, cmap);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_DCOL:
|
|
Packit |
78deda |
if (chunksize != DirectColorSize)
|
|
Packit |
78deda |
pm_error("%s chunk size mismatch", ID2string(iffid));
|
|
Packit |
78deda |
MALLOCVAR_NOFAIL(*dcolP);
|
|
Packit |
78deda |
(*dcolP)->r = get_byte(ifP, iffid, NULL);
|
|
Packit |
78deda |
(*dcolP)->g = get_byte(ifP, iffid, NULL);
|
|
Packit |
78deda |
(*dcolP)->b = get_byte(ifP, iffid, NULL);
|
|
Packit |
78deda |
get_byte(ifP, iffid, NULL); /* skip pad byte */
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_BODY:
|
|
Packit |
78deda |
if (cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0))
|
|
Packit |
78deda |
skip_chunk(ifP, ID_BODY, chunksize);
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
process_body(ifP, chunksize, *bmhdP, cmap,
|
|
Packit |
78deda |
maskfile, fakeviewport, isdeepopt, *dcolP,
|
|
Packit |
78deda |
viewportmodesP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*bodyChunkProcessedP = TRUE;
|
|
Packit |
78deda |
} break;
|
|
Packit |
78deda |
case ID_GRAB: case ID_DEST: case ID_SPRT: case ID_CRNG:
|
|
Packit |
78deda |
case ID_CCRT: case ID_DYCP: case ID_DPPV: case ID_DRNG:
|
|
Packit |
78deda |
case ID_EPSF: case ID_JUNK: case ID_CNAM: case ID_PRVW:
|
|
Packit |
78deda |
case ID_TINY: case ID_DPPS:
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_copy: case ID_AUTH: case ID_NAME: case ID_ANNO:
|
|
Packit |
78deda |
case ID_TEXT: case ID_FVER:
|
|
Packit |
78deda |
if (verbose)
|
|
Packit |
78deda |
display_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ID_DPI: {
|
|
Packit |
78deda |
int x, y;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
x = get_big_short(ifP, ID_DPI, NULL);
|
|
Packit |
78deda |
y = get_big_short(ifP, ID_DPI, NULL);
|
|
Packit |
78deda |
if (verbose)
|
|
Packit |
78deda |
pm_message("%s chunk: dpi_x = %d dpi_y = %d",
|
|
Packit |
78deda |
ID2string(ID_DPI), x, y);
|
|
Packit |
78deda |
} break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
pm_message("unknown chunk type %s - skipping",
|
|
Packit |
78deda |
ID2string(iffid));
|
|
Packit |
78deda |
skip_chunk(ifP, iffid, chunksize);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesread += chunksize;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (ODD(chunksize)) {
|
|
Packit |
78deda |
get_byte(ifP, iffid, NULL);
|
|
Packit |
78deda |
bytesread += 1;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*bytesReadP = bytesread;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
maybeWriteColorMap(FILE * const ofP,
|
|
Packit |
78deda |
const BitMapHeader * const bmhdP,
|
|
Packit |
78deda |
ColorMap * const cmapP,
|
|
Packit |
78deda |
bool const bodyChunkProcessed,
|
|
Packit |
78deda |
bool const cmaponly) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Write to file *ofP the color map *cmapP as a PPM, if appropriate.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The logic (not just here -- in the program as a whole) for deciding whether
|
|
Packit |
78deda |
to write the image or the colormap is quite twisted. If I thought anyone
|
|
Packit |
78deda |
was actually using this program, I would take the time to straighten it
|
|
Packit |
78deda |
out.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
What's really sick about this subroutine is that in choosing to write
|
|
Packit |
78deda |
a color map, it has to know that Caller hasn't already written
|
|
Packit |
78deda |
the image. Huge modularity violation.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
if (cmaponly) {
|
|
Packit |
78deda |
if (HAS_COLORMAP(cmapP)) {
|
|
Packit |
78deda |
prepareCmap(bmhdP, cmapP);
|
|
Packit |
78deda |
cmapToPpm(ofP, cmapP);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_error("You specified -cmaponly, but the ILBM "
|
|
Packit |
78deda |
"has no colormap");
|
|
Packit |
78deda |
} else if (bmhdP && bmhdP->nPlanes == 0) {
|
|
Packit |
78deda |
if (HAS_COLORMAP(cmapP)) {
|
|
Packit |
78deda |
prepareCmap(bmhdP, cmapP);
|
|
Packit |
78deda |
cmapToPpm(ofP, cmapP);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_error("ILBM has neither a color map nor color planes");
|
|
Packit |
78deda |
} else if (!bodyChunkProcessed) {
|
|
Packit |
78deda |
if (HAS_COLORMAP(cmapP)) {
|
|
Packit |
78deda |
pm_message("input is a colormap file");
|
|
Packit |
78deda |
prepareCmap(bmhdP, cmapP);
|
|
Packit |
78deda |
cmapToPpm(ofP, cmapP);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_error("ILBM has neither %s or %s chunk",
|
|
Packit |
78deda |
ID2string(ID_BODY), ID2string(ID_CMAP));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, char *argv[]) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
FILE * ifP;
|
|
Packit |
78deda |
int argn;
|
|
Packit |
78deda |
short cmaponly = 0, isdeepopt = 0;
|
|
Packit |
78deda |
bool endchunk;
|
|
Packit |
78deda |
bool bodyChunkProcessed;
|
|
Packit |
78deda |
long formsize, bytesread;
|
|
Packit |
78deda |
int viewportmodes = 0, fakeviewport = 0, viewportmask;
|
|
Packit |
78deda |
IFF_ID firstIffid;
|
|
Packit |
78deda |
BitMapHeader *bmhdP = NULL;
|
|
Packit |
78deda |
ColorMap * cmap;
|
|
Packit |
78deda |
DirectColor *dcol = NULL;
|
|
Packit |
78deda |
#define MAX_IGNORE 16
|
|
Packit |
78deda |
IFF_ID ignorelist[MAX_IGNORE];
|
|
Packit |
78deda |
int ignorecount = 0;
|
|
Packit |
78deda |
char *maskname;
|
|
Packit |
78deda |
const char * const usage =
|
|
Packit |
78deda |
"[-verbose] [-ignore <chunkID> [-ignore <chunkID>] ...] "
|
|
Packit |
78deda |
"[-isham|-isehb|-isdeep|-isnotham|-isnotehb|-isnotdeep] "
|
|
Packit |
78deda |
"[-cmaponly] [-adjustcolors] "
|
|
Packit |
78deda |
"[-transparent <color>] [-maskfile <filename>] [ilbmfile]";
|
|
Packit |
78deda |
ppm_init(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
viewportmask = 0xffffffff;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
argn = 1;
|
|
Packit |
78deda |
while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
|
|
Packit |
78deda |
if( pm_keymatch(argv[argn], "-verbose", 2) )
|
|
Packit |
78deda |
verbose = 1;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-noverbose", 4) )
|
|
Packit |
78deda |
verbose = 0;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isham", 4) )
|
|
Packit |
78deda |
fakeviewport |= vmHAM;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isehb", 4) )
|
|
Packit |
78deda |
fakeviewport |= vmEXTRA_HALFBRITE;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isdeep", 4) )
|
|
Packit |
78deda |
isdeepopt = 1;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isnotham", 7) )
|
|
Packit |
78deda |
viewportmask &= ~(vmHAM);
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isnotehb", 7) )
|
|
Packit |
78deda |
viewportmask &= ~(vmEXTRA_HALFBRITE);
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-isnotdeep", 7) )
|
|
Packit |
78deda |
isdeepopt = -1;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-cmaponly", 2) )
|
|
Packit |
78deda |
cmaponly = 1;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-adjustcolors", 2) )
|
|
Packit |
78deda |
adjustcolors = 1;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-noadjustcolors", 4) )
|
|
Packit |
78deda |
adjustcolors = 0;
|
|
Packit |
78deda |
else if( pm_keymatch(argv[argn], "-transparent", 2) ) {
|
|
Packit |
78deda |
if( ++argn >= argc )
|
|
Packit |
78deda |
pm_usage(usage);
|
|
Packit |
78deda |
transpName = argv[argn];
|
|
Packit |
78deda |
} else if( pm_keymatch(argv[argn], "-maskfile", 2) ) {
|
|
Packit |
78deda |
if( ++argn >= argc )
|
|
Packit |
78deda |
pm_usage(usage);
|
|
Packit |
78deda |
maskname = argv[argn];
|
|
Packit |
78deda |
maskfile = pm_openw(maskname);
|
|
Packit |
78deda |
} else if( pm_keymatch(argv[argn], "-ignore", 2) ) {
|
|
Packit |
78deda |
if( ++argn >= argc )
|
|
Packit |
78deda |
pm_usage(usage);
|
|
Packit |
78deda |
if( strlen(argv[argn]) != 4 )
|
|
Packit |
78deda |
pm_error("'-ignore' option needs a 4 byte chunk ID string "
|
|
Packit |
78deda |
"as argument");
|
|
Packit |
78deda |
if( ignorecount >= MAX_IGNORE )
|
|
Packit |
78deda |
pm_error("max %d chunk IDs to ignore", MAX_IGNORE);
|
|
Packit |
78deda |
ignorelist[ignorecount++] =
|
|
Packit |
78deda |
MAKE_ID(argv[argn][0], argv[argn][1], argv[argn][2],
|
|
Packit |
78deda |
argv[argn][3]);
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_usage(usage);
|
|
Packit |
78deda |
++argn;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( argn < argc ) {
|
|
Packit |
78deda |
ifP = pm_openr( argv[argn] );
|
|
Packit |
78deda |
argn++;
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
ifP = stdin;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if( argn != argc )
|
|
Packit |
78deda |
pm_usage(usage);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
wrotemask = false; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Read in the ILBM file. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
firstIffid = get_big_long(ifP, ID_FORM, NULL);
|
|
Packit |
78deda |
if (firstIffid != ID_FORM)
|
|
Packit |
78deda |
pm_error("input is not a FORM type IFF file");
|
|
Packit |
78deda |
formsize = get_big_long(ifP, ID_FORM, NULL);
|
|
Packit |
78deda |
typeid = get_big_long(ifP, ID_FORM, NULL);
|
|
Packit |
78deda |
if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 &&
|
|
Packit |
78deda |
typeid != ID_PBM)
|
|
Packit |
78deda |
pm_error("input is not an ILBM, RGBN, RGB8 or PBM "
|
|
Packit |
78deda |
"type FORM IFF file");
|
|
Packit |
78deda |
bytesread = 4; /* FORM and formsize do not count */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
cmap = alloc_cmap();
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Main loop, parsing the IFF FORM. */
|
|
Packit |
78deda |
bodyChunkProcessed = FALSE;
|
|
Packit |
78deda |
endchunk = FALSE;
|
|
Packit |
78deda |
while (!endchunk && formsize-bytesread >= 8) {
|
|
Packit |
78deda |
long bytesReadForChunk;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
processChunk(ifP, formsize, ignorelist, ignorecount,
|
|
Packit |
78deda |
fakeviewport, viewportmask,
|
|
Packit |
78deda |
isdeepopt, cmaponly,
|
|
Packit |
78deda |
&bodyChunkProcessed,
|
|
Packit |
78deda |
&endchunk, &bmhdP, cmap, &dcol,
|
|
Packit |
78deda |
&viewportmodes, &bytesReadForChunk);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesread += bytesReadForChunk;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (maskfile) {
|
|
Packit |
78deda |
pm_close(maskfile);
|
|
Packit |
78deda |
if (!wrotemask)
|
|
Packit |
78deda |
remove(maskname);
|
|
Packit |
78deda |
pbm_freerow(maskrow);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
maybeWriteColorMap(stdout, bmhdP, cmap, bodyChunkProcessed, cmaponly);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned int skipped;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (skipped = 0; fgetc(ifP) != EOF; ++skipped)
|
|
Packit |
78deda |
++bytesread;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (skipped > 0)
|
|
Packit |
78deda |
pm_message("skipped %u extraneous byte%s after last chunk",
|
|
Packit |
78deda |
skipped, (skipped == 1 ? "" : "s"));
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
pm_close(ifP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!endchunk && bytesread != formsize) {
|
|
Packit |
78deda |
pm_message("warning - file length/FORM size field mismatch "
|
|
Packit |
78deda |
"(%ld != %ld+8)",
|
|
Packit |
78deda |
bytesread+8 /* FORM+size */, formsize);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|