From: Nick Bowler Date: Fri, 4 Jan 2008 07:48:19 +0000 (-0500) Subject: Implement new handling of the LBX image header data. X-Git-Url: https://git.draconx.ca/gitweb/liblbx.git/commitdiff_plain/488ae1c1e2b6e1767792010e4ea1f0e9447719d5 Implement new handling of the LBX image header data. * Change "#offsets" to "#frames". This makes lbximg capable of decoding all frames of images such as the TANM_ family and science.lbx.001 * Change interpretation of "pal" to a bitmask containing flags. Current flags handled are - 0x0400: render each frame on a blank slate (makes TANM_ family work). - 0x1000: image contains embedded palette, as previously understood. - 0x2000: image loops over all frames. * Change interpretation of previously-thought "#frames" to "leadin" - that is, indicates the first frame that is part of a looping animation. This is superseded by flag 0x2000, and yes - leadin == 0 means the same thing as that flag. This will allow science.lbx.001 to be looped correctly. This leads to the somewhat strange notion that all images loop, just that some simply loop over the last frame. Also update lbx_getinfo() to reflect the new information. --- diff --git a/src/image.c b/src/image.c index 2b1c211..2d34b52 100644 --- a/src/image.c +++ b/src/image.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -12,11 +13,15 @@ #include "lbx.h" #include "image.h" +#define FLAG_OVERWRITE 0x0400 /* Draw each frame on a clean slate (unsure). */ +#define FLAG_PALETTE 0x1000 /* Image contains embedded palette. */ +#define FLAG_LOOPING 0x2000 /* Loop over all frames in the image (unsure). */ + struct lbx_image { uint16_t width, height; uint16_t wtf1; - uint16_t offs, frames; - uint16_t pal; + uint16_t frames, leadin; + uint16_t flags; FILE *f; long foff; @@ -31,27 +36,24 @@ struct lbx_image { struct lbx_image *lbximg_fopen(FILE *f) { struct lbx_image tmp = {.f = f}, *new = NULL; + size_t rc; if (fread(&tmp.width, sizeof tmp.width, 1, f) != 1) goto readerr; if (fread(&tmp.height, sizeof tmp.height, 1, f) != 1) goto readerr; if (fread(&tmp.wtf1, sizeof tmp.wtf1, 1, f) != 1) goto readerr; - if (fread(&tmp.offs, sizeof tmp.offs, 1, f) != 1) goto readerr; if (fread(&tmp.frames, sizeof tmp.frames, 1, f) != 1) goto readerr; - if (fread(&tmp.pal, sizeof tmp.pal, 1, f) != 1) goto readerr; + if (fread(&tmp.leadin, sizeof tmp.leadin, 1, f) != 1) goto readerr; + if (fread(&tmp.flags, sizeof tmp.flags, 1, f) != 1) goto readerr; tmp.width = letohs(tmp.width); tmp.foff += sizeof tmp.width; tmp.height = letohs(tmp.height); tmp.foff += sizeof tmp.height; tmp.wtf1 = letohs(tmp.wtf1); tmp.foff += sizeof tmp.wtf1; - tmp.offs = letohs(tmp.offs); tmp.foff += sizeof tmp.offs; tmp.frames = letohs(tmp.frames); tmp.foff += sizeof tmp.frames; - tmp.pal = letohs(tmp.pal); tmp.foff += sizeof tmp.pal; - - /* For some reason, the format seems to need this. */ - tmp.offs++; - tmp.frames++; + tmp.leadin = letohs(tmp.leadin); tmp.foff += sizeof tmp.leadin; + tmp.flags = letohs(tmp.flags); tmp.foff += sizeof tmp.flags; /* Format constraints. */ - if (tmp.offs <= tmp.frames) { + if (tmp.frames <= tmp.leadin) { lbx_errno = LBX_EFORMAT; return NULL; } @@ -63,10 +65,9 @@ struct lbx_image *lbximg_fopen(FILE *f) * assumptions. */ _lbx_assert(tmp.wtf1 == 0); - _lbx_assert(tmp.offs == tmp.frames + 1); - _lbx_assert(tmp.pal == 0 || tmp.pal == 0x1000); + _lbx_assert(!(tmp.flags & ~(FLAG_PALETTE|FLAG_OVERWRITE|FLAG_LOOPING))); - new = malloc(sizeof *new + tmp.offs * sizeof *new->offsets); + new = malloc(sizeof *new + (tmp.frames+1) * sizeof *new->offsets); if (!new) { lbx_errno = -errno; return NULL; @@ -75,9 +76,10 @@ struct lbx_image *lbximg_fopen(FILE *f) *new = tmp; new->currentframe = -1; - if (fread(new->offsets, sizeof *new->offsets, new->offs, f)!= new->offs) + rc = fread(new->offsets, sizeof *new->offsets, new->frames+1, f); + if (rc < new->frames+1) goto readerr; - new->foff += sizeof *new->offsets * new->offs; + new->foff += sizeof *new->offsets * (new->frames+1); return new; readerr: @@ -205,10 +207,15 @@ unsigned char **lbximg_getframe(struct lbx_image *img, int frame) if (img->currentframe > frame) img->currentframe == -1; - /* We must have previous frame decoded to continue. */ - if (frame > img->currentframe + 1) { - if (!lbximg_getframe(img, frame-1)) - return NULL; + if (img->flags & FLAG_OVERWRITE) { + /* Clear the slate. */ + memset(img->framedata[0], 0, img->width * img->height); + } else { + /* We must have previous frame decoded to continue. */ + if (frame > img->currentframe + 1) { + if (!lbximg_getframe(img, frame-1)) + return NULL; + } } if (img->currentframe != frame) { @@ -263,7 +270,7 @@ int lbximg_loadpalette(FILE *f, struct lbx_colour palette[static 256]) int lbximg_getpalette(struct lbx_image *img, struct lbx_colour palette[static 256]) { - size_t hdrlen = 6*(sizeof img->pal)+(img->offs)*(sizeof *img->offsets); + size_t hdrlen = 6*(sizeof img->wtf1)+(img->frames+1)*(sizeof *img->offsets); unsigned int i; size_t rc; @@ -271,7 +278,7 @@ lbximg_getpalette(struct lbx_image *img, struct lbx_colour palette[static 256]) uint8_t entry[4]; /* Do nothing if the image doesn't have embedded palette data. */ - if (img->pal == 0) + if (!(img->flags & FLAG_PALETTE)) return 0; /* Palette data is located right after the header. */ @@ -323,10 +330,20 @@ readerr: void lbximg_getinfo(struct lbx_image *img, struct lbx_imginfo *info) { *info = (struct lbx_imginfo) { - .width = img->width, - .height = img->height, - .nframes = img->frames, + .width = img->width, + .height = img->height, + .nframes = img->frames, + .haspalette = (_Bool)(img->flags & FLAG_PALETTE), }; + + /* There seems to be two ways of specifying that an image loops. */ + if (img->flags & FLAG_LOOPING) { + info->loopstart = 0; + info->looping = 1; + } else if (img->leadin != img->frames - 1) { + info->loopstart = img->leadin; + info->looping = 1; + } } void lbximg_close(struct lbx_image *img) diff --git a/src/image.h b/src/image.h index 44e94a7..a1f2eff 100644 --- a/src/image.h +++ b/src/image.h @@ -13,7 +13,9 @@ struct lbx_colour { struct lbx_imginfo { unsigned int width, height; - unsigned int nframes; + unsigned int nframes, loopstart; + int haspalette; + int looping; }; LBX_IMG *lbximg_fopen(FILE *f);