188 lines
5.2 KiB
C
188 lines
5.2 KiB
C
|
#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;
|
||
|
}
|