neuttower/tiff.c

188 lines
5.2 KiB
C
Executable file

#include <dos.h>
#include "tiff.h"
#include "video.h"
/*** T I F F ***/
typedef struct {
unsigned int endian;
unsigned int version;
unsigned long ifdOffset;
} TifHeader_t;
#define TIF_WIDTH 256
#define TIF_HEIGHT 257
#define TIF_BITSPERSAMPLE 258
#define TIF_COMPRESSION 259
#define TIF_STRIPOFFSETS 273
#define TIF_ROWSPERSTRIP 278
typedef struct {
unsigned int id;
unsigned int dataType;
unsigned long dataCount;
unsigned long dataOffset;
} TifTag_t;
TifImageMeta_t tifLoadMeta(FILE *f) {
TifImageMeta_t meta = {0, 0, 0, 0, 0};
TifHeader_t header;
TifTag_t tag;
unsigned int i, tagCount;
fseek(f, 0, SEEK_SET);
fread(&header, 8, 1, f);
if (header.endian != 0x4949 || header.version != 0x2a) {
goto fail;
}
fseek(f, header.ifdOffset, SEEK_SET);
fread(&tagCount, 2, 1, f);
for (i = 0; i < tagCount; i ++) {
fread(&tag, 12, 1, f);
if (tag.id == TIF_WIDTH) {
meta.width = tag.dataOffset;
} else if (tag.id == TIF_HEIGHT) {
meta.height = tag.dataOffset;
} else if (tag.id == TIF_BITSPERSAMPLE) {
if (tag.dataOffset != 4) goto fail;
} else if (tag.id == TIF_COMPRESSION) {
if (tag.dataOffset != 1) goto fail;
} else if (tag.id == TIF_STRIPOFFSETS) {
meta.stripCount = tag.dataCount;
meta.stripOffsets = tag.dataOffset;
} else if (tag.id == TIF_ROWSPERSTRIP) {
meta.rowsPerStrip = tag.dataOffset;
}
}
return meta;
fail:
meta.stripCount = 0;
return meta;
}
int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w) {
int istrip;
int irow;
int ipixelpair;
int y = 0;
unsigned long offset;
unsigned char rowData[MAX_WIDTH >> 1];
volatile unsigned char far *out = &VID[vidOffset];
unsigned char b, g, r, i;
if (meta.width > MAX_WIDTH || (meta.width % 8) != 0) {
return 0;
}
setWriteMode(0);
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
fread(&offset, 4, 1, f);
fseek(f, offset, SEEK_SET);
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
int ipixelpairLim = meta.width >> 1;
fread(rowData, 1, ipixelpairLim, f);
b = g = r = i = 0;
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
unsigned char pixelpair = rowData[ipixelpair];
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
int gpair = (pixelpair & 0x02) >> 1 | (pixelpair & 0x20) >> 4;
int rpair = (pixelpair & 0x04) >> 2 | (pixelpair & 0x40) >> 5;
int ipair = (pixelpair & 0x08) >> 3 | (pixelpair & 0x80) >> 6;
int shift = (3 - (ipixelpair % 4)) << 1;
b |= bpair << shift;
g |= gpair << shift;
r |= rpair << shift;
i |= ipair << shift;
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
// todo: use write mode 2, this is slooww
setPlane(PLANE_B); *out = b;
setPlane(PLANE_R); *out = r;
setPlane(PLANE_G); *out = g;
setPlane(PLANE_I); *out = i;
out ++;
b = g = r = i = 0;
}
}
y++;
if (y == maxY) {
return y;
}
out += (w - meta.width) >> 3;
}
}
return y;
}
int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int far *planeBuf, int maxY, int yRepeat, int planes) {
int istrip;
int irow;
int ipixelpair;
int y = 0;
unsigned long offset;
unsigned char rowData[MAX_WIDTH >> 1];
unsigned int planeStride = (meta.width >> 4) * yRepeat;
unsigned int far *bp = planeBuf;
unsigned int far *gp = bp + planeStride;
unsigned int far *rp = gp + planeStride;
unsigned int far *ip = rp + planeStride;
unsigned int far *mp = ip + planeStride;
unsigned int bv, gv, rv, iv;
if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) {
return 0;
}
for (istrip = 0; istrip < meta.stripCount; istrip ++) {
fseek(f, meta.stripOffsets + (istrip << 2), SEEK_SET);
fread(&offset, 4, 1, f);
fseek(f, offset, SEEK_SET);
for (irow = 0; irow < meta.rowsPerStrip; irow ++) {
int ipixelpairLim = meta.width >> 1;
fread(rowData, 1, ipixelpairLim, f);
bv = gv = rv = iv = 0;
for (ipixelpair = 0; ipixelpair < ipixelpairLim; ipixelpair ++) {
unsigned char pixelpair = rowData[ipixelpair];
int bpair = (pixelpair & 0x01) | (pixelpair & 0x10) >> 3;
int gpair = (pixelpair & 0x02) >> 1 | (pixelpair & 0x20) >> 4;
int rpair = (pixelpair & 0x04) >> 2 | (pixelpair & 0x40) >> 5;
int ipair = (pixelpair & 0x08) >> 3 | (pixelpair & 0x80) >> 6;
int shift = (7 - (ipixelpair % 8)) << 1;
bv |= bpair << shift;
gv |= gpair << shift;
rv |= rpair << shift;
iv |= ipair << shift;
if (shift == 0 || ipixelpair == ipixelpairLim - 1) {
*bp++ = bv;
*gp++ = gv;
*rp++ = rv;
*ip++ = iv;
if (planes == 5) {
iv = ~(bv & gv & rv & iv);
*mp++ = iv;
}
bv = gv = rv = iv = 0;
}
}
y++;
if (y == maxY) {
return y;
}
if (y % yRepeat == 0) {
bp += planeStride * (planes - 1);
gp += planeStride * (planes - 1);
rp += planeStride * (planes - 1);
ip += planeStride * (planes - 1);
mp += planeStride * (planes - 1);
}
}
}
return y;
}