]> git.draconx.ca Git - liblbx.git/commitdiff
Implement new handling of the LBX image header data.
authorNick Bowler <draconx@gmail.com>
Fri, 4 Jan 2008 07:48:19 +0000 (02:48 -0500)
committerNick Bowler <draconx@gmail.com>
Fri, 4 Jan 2008 07:48:19 +0000 (02:48 -0500)
* 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.

src/image.c
src/image.h

index 2b1c2113c3974aa400b43f457b333404fba52050..2d34b52b0e2c742611e292c1d68cd8bcbec35e77 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include <assert.h>
 #include <errno.h>
 
 #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)
index 44e94a7806d2d8e742ef8794b78bbaa64a94c337..a1f2eff86c7df9af068c2ed5e2174993aa4f6263 100644 (file)
@@ -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);