brender-v1.1.2/TOOLS/LOADIFF.C
2022-05-04 18:14:23 -07:00

415 lines
7.1 KiB
C

/*
* Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: loadiff.c 1.1 1995/03/16 12:02:01 sam Exp $
* $Locker: $
*
* Reading IFF ILBM and PBM files
*
* $BC<"make -f ifftopix.mak %s.obj;">
*/
/* static char rscid[] = "$Id: loadiff.c 1.1 1995/03/16 12:02:01 sam Exp $"; */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <argstd.h>
#include <lists.h>
#include <error.h>
#include "bitmap.h"
#include "loadiff.h"
struct BitMapHeader BMhd;
struct Chunk Header;
void ExpandILBM(struct Bitmap * bm, struct BitMapHeader * bmhd, BYTE * sourcebuf);
void ExpandPBM(struct Bitmap * bm, struct BitMapHeader * bmhd, BYTE * sourcebuf);
UDWORD SwapLong(UDWORD l)
{
union {
UDWORD l;
UBYTE c[4];
} swap;
UBYTE t;
swap.l = l;
t = swap.c[3];
swap.c[3] = swap.c[0];
swap.c[0] = t;
t = swap.c[2];
swap.c[2] = swap.c[1];
swap.c[1] = t;
return swap.l;
}
UWORD SwapWord(UWORD w)
{
union {
UWORD w;
UBYTE c[2];
} swap;
UBYTE t;
swap.w = w;
t = swap.c[1];
swap.c[1] = swap.c[0];
swap.c[0] = t;
return swap.w;
}
void ReadHeader(FILE * fh, struct Chunk * hp)
{
fread(hp, sizeof(*hp), 1, fh);
hp->ckID = SwapLong(hp->ckID);
hp->ckSize = SwapLong(hp->ckSize);
}
void ReadBMHD(FILE * fh, struct BitMapHeader * bmp)
{
fread(bmp, sizeof(*bmp), 1, fh);
bmp->w = SwapWord(bmp->w);
bmp->h = SwapWord(bmp->h);
bmp->x = SwapWord(bmp->x);
bmp->y = SwapWord(bmp->y);
bmp->transparentColor = SwapWord(bmp->transparentColor);
bmp->pageWidth = SwapWord(bmp->pageWidth);
bmp->pageHeight = SwapWord(bmp->pageHeight);
}
void ReadLong(FILE * fh, UDWORD * lp)
{
fread(lp, sizeof(*lp), 1, fh);
*lp = SwapLong(*lp);
}
/*
* Unpack planes
*/
void ExpandILBM(struct Bitmap * bm, struct BitMapHeader * bmhd, BYTE * bodydata)
{
signed char n, *destbuf;
int plane, linelen, rowbytes, i, j, k;
linelen = 2 * ((bmhd->w + 15) >> 4);
/*
* Allocate the plane buffers
*/
j = 2 * ((bmhd->w + 15) >> 4) * bmhd->h;
for (i = 0; i < bmhd->nPlanes; i++)
bm->planes[i] = CALLOC(j, 1);
for (i = 0; i < bmhd->h; i++) {
for (plane = 0; plane < bmhd->nPlanes; plane++) {
destbuf = (char *) (bm->planes[plane]) + (i * linelen);
if (bmhd->compression == 1) {
/*
* compressed screen
*/
rowbytes = linelen;
while (rowbytes) {
/*
* unpack until 1 scan-line complete
*/
n = *bodydata++;
/*
* uncompressed block - copy n bytes verbatim
*/
if (n >= 0) {
k = (int)n+1;
memcpy(destbuf, bodydata, k);
rowbytes -= k;
destbuf += k;
bodydata += k;
} else {
/*
* compressed block - expand n duplicate bytes
*/
k = -(int)n + 1;
rowbytes -= k;
memset(destbuf, *bodydata++, k);
destbuf += k;
}
}
} else {
/*
* uncompressed - just copy
*/
memcpy(destbuf, bodydata, linelen);
bodydata += linelen;
destbuf += linelen;
}
}
}
}
/*
* Unpack an PBM to byte per pixel
*/
void ExpandPBM(struct Bitmap * bm, struct BitMapHeader * bmhd, BYTE * bodydata)
{
UBYTE *destbuf, *databuf;
int i, linelen, rowbytes, n;
long planebytes = 0;
/*
* Allocate the picture data buffer
*/
linelen = (bmhd->w + 1) & ~1;
/*
* Allocate a byte per pixel data area
*/
planebytes = (long) linelen * (long) bmhd->h;
if(planebytes > UINT_MAX)
ERROR2("picture is too big - %dx%d",bmhd->w,bmhd->h);
databuf = CALLOC(planebytes, 1);
/*
* Fill in the bitmap elements
*/
bm->width = bmhd->w;
bm->height = bmhd->h;
bm->background = bmhd->transparentColor;
/*
* Unpack the file data into bitplanes
*/
for (i = 0; i < bmhd->h; i++) {
destbuf = databuf + (i * linelen);
if (bmhd->compression == 1) {
/*
* compressed screen
*/
rowbytes = linelen;
while (rowbytes) {
/*
* unpack until 1 scan-line complete
*/
n = *bodydata++;
/*
* uncompressed block - copy n bytes verbatim
*/
if (n >= 0) {
memcpy(destbuf, bodydata, ++n);
rowbytes -= n;
destbuf += n;
bodydata += n;
} else {
/*
* compressed block - expand n duplicate bytes
*/
n = -n + 1;
rowbytes -= n;
memset(destbuf, *bodydata++, n);
destbuf += n;
}
}
} else {
/*
* uncompressed - just copy
*/
memcpy(destbuf, bodydata, linelen);
bodydata += linelen;
destbuf += linelen;
}
}
bm->planes[0] = databuf;
}
struct Bitmap *ReadPicture_IFF(char *filename)
{
UDWORD id;
BYTE *bodydata = NULL;
struct Bitmap *bm = NULL;
struct Bitmap *nbm = NULL;
FILE *fh = FOPEN(filename,"rb");
/*
* Allocate the bitmap structure
*/
bm = CALLOC(sizeof(struct Bitmap), 1);
ReadHeader(fh, &Header);
if (Header.ckID != ID_FORM)
goto badiff;
ReadLong(fh, &id);
switch (id) {
case ID_ILBM:
bm->type = BMT_PLANES;
break;
case ID_PBM:
bm->type = BMT_BYTEPERPIXEL;
break;
default:
goto badiff;
};
for (;;) {
ReadHeader(fh, &Header);
if (feof(fh))
return NULL;
if (Header.ckID == ID_BODY)
break;
switch (Header.ckID) {
case ID_BMHD:
ReadBMHD(fh, &BMhd);
break;
case ID_CMAP:
bm->palette = MALLOC(Header.ckSize);
bm->npalette = Header.ckSize / 3;
fread(bm->palette, 1, Header.ckSize, fh);
break;
default:
fseek(fh, ROUNDODDUP(Header.ckSize), SEEK_CUR);
}
}
/*
* Fill in the bitmap elements
*/
bm->width = BMhd.w;
bm->height = BMhd.h;
bm->nplanes = BMhd.nPlanes;
bm->background = BMhd.transparentColor;
/*
* Read data into RAM for ease of decompression
*/
bodydata = MALLOC(Header.ckSize);
fread(bodydata, 1, Header.ckSize, fh);
switch (bm->type) {
case BMT_PLANES:
ExpandILBM(bm, &BMhd, bodydata);
break;
case BMT_BYTEPERPIXEL:
ExpandPBM(bm, &BMhd, bodydata);
break;
}
/*
* Close the file
*/
FCLOSE(fh);
/*
* Get rid of the original file data
*/
FREE(bodydata);
/*
* Convert a bitplane picture to byte per pixel
*/
if (bm->type == BMT_PLANES) {
nbm = ConvertToBytePerPixel(bm);
FreeBitmap(bm);
return nbm;
} else {
return bm;
}
badiff:
FREE(bm);
FCLOSE(fh);
return NULL;
}
int ReadPalette_IFF(struct Bitmap * bmp, char *filename, int num, int from, int to)
{
UDWORD id;
UBYTE *new_palette;
int num_colours, i;
FILE *fh = FOPEN(filename,"rb");
/*
* Dig the palette out of the input IFF file
*/
ReadHeader(fh, &Header);
if (Header.ckID != ID_FORM)
return 1;
ReadLong(fh, &id);
switch (id) {
case ID_ILBM:
break;
case ID_PBM:
break;
default:
return 1;
};
for (;;) {
ReadHeader(fh, &Header);
if (feof(fh))
return 1;
if (Header.ckID == ID_CMAP) {
new_palette = MALLOC(Header.ckSize);
num_colours = Header.ckSize / 3;
fread(new_palette, 1, Header.ckSize, fh);
break;
} else {
fseek(fh, ROUNDODDUP(Header.ckSize), SEEK_CUR);
}
}
/*
* Assume default if no subrange is given
*/
if (num == 0) {
from = to = 0;
num = num_colours;
}
/*
* Paste the new palette into the given bitmap
*/
if (from + num > num_colours)
return 1;
if (to + num > bmp->npalette)
return 1;
for (i = 0; i < num * 3; i++)
bmp->palette[to * 3 + i] = new_palette[from * 3 + i];
FREE(new_palette);
FCLOSE(fh);
return 0;
}