]> git.draconx.ca Git - liblbx.git/blobdiff - src/image.c
liblbx: Clean up embedded palette handling
[liblbx.git] / src / image.c
index 786e17aa729c43667b8f4b51be4303fbca85b2c1..853852000492e3413cf8e17f851ee6458c0be9e5 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <stdbool.h>
 #include <inttypes.h>
 #include <errno.h>
 
@@ -52,14 +53,11 @@ struct lbx_image_priv {
 
        unsigned short wtf, flags;
        unsigned char  wtf2;
-       unsigned short palstart, palcount;
 
        const struct lbx_file_ops *fops;
        int (*dtor)(void *handle);
        void *f;
 
-       long paloff;
-
        /* State of frame readout */
        unsigned currentx, currenty, currentn;
        int read_state;
@@ -143,27 +141,6 @@ struct lbx_image *lbx_img_open(void *f, const struct lbx_file_ops *fops,
                img->offsets[i] = unpack_32_le(buf);
        }
 
-       if (img->flags & FLAG_PALETTE) {
-               unsigned char buf[4];
-
-               if (fops->read(buf, sizeof buf, f) != sizeof buf) {
-                       if (fops->eof(f))
-                               lbx_error_raise(LBX_EEOF);
-                       free(img);
-                       return NULL;
-               }
-
-               img->palstart = unpack_16_le(buf+0);
-               img->palcount = unpack_16_le(buf+2);
-               img->paloff   = fops->tell(f);
-
-               if (img->palstart + img->palcount > 256) {
-                       lbx_error_raise(LBX_EFORMAT);
-                       free(img);
-                       return NULL;
-               }
-       }
-
        return &img->pub;
 }
 
@@ -345,29 +322,29 @@ long lbx_img_read_row_data(struct lbx_image *pub, void *buf)
        return img->currentn;
 }
 
-int
-lbx_img_loadpalette(void *f, const struct lbx_file_ops *fops,
-                    struct lbx_colour palette[static 256])
+static int read_palette(void *f, const struct lbx_file_ops *fops,
+                        struct lbx_colour *palette, unsigned count,
+                       bool external)
 {
-       unsigned char entry[4];
-       int i;
+       assert(count <= 256);
+       for (unsigned i = 0; i < count; i++) {
+               unsigned char buf[4];
 
-       for (i = 0; i < 256; i++) {
-               if (fops->read(entry, sizeof entry, f) != sizeof entry) {
+               if (fops->read(buf, 4, f) != 4) {
                        if (fops->eof(f))
                                lbx_error_raise(LBX_EEOF);
                        return -1;
                }
 
-               if (entry[0] != 1) {
+               if (buf[0] != external) {
                        lbx_error_raise(LBX_EFORMAT);
                        return -1;
                }
 
                palette[i] = (struct lbx_colour) {
-                       .red    = entry[1] & 0x3f,
-                       .green  = entry[2] & 0x3f,
-                       .blue   = entry[3] & 0x3f,
+                       .red    = buf[1] & 0x3f,
+                       .green  = buf[2] & 0x3f,
+                       .blue   = buf[3] & 0x3f,
                        .active = 1,
                };
        }
@@ -375,42 +352,48 @@ lbx_img_loadpalette(void *f, const struct lbx_file_ops *fops,
        return 0;
 }
 
-int
-lbx_img_getpalette(struct lbx_image *pub, struct lbx_colour palette[static 256])
+int lbx_img_loadpalette(void *f, const struct lbx_file_ops *fops,
+                        struct lbx_colour *palette)
+{
+       return read_palette(f, fops, palette, 256, true);
+}
+
+int lbx_img_getpalette(struct lbx_image *pub, struct lbx_colour *out)
 {
        struct lbx_image_priv *img = (struct lbx_image_priv *)pub;
-       unsigned char entry[4];
-       unsigned int i;
-       size_t rc;
+       unsigned long palette_start, palette_count, palette_offset;
+       unsigned char buf[4];
+       int rc;
 
        /* Do nothing if the image doesn't have embedded palette data. */
        if (!(img->flags & FLAG_PALETTE))
                return 0;
 
-       if (img->fops->seek(img->f, img->paloff, SEEK_SET)) {
+       palette_offset = 16 + 4ul * img->pub.frames;
+       if (img->fops->seek(img->f, palette_offset, SEEK_SET)) {
                return -1;
        }
 
-       for (i = 0; i < img->palcount; i++) {
-               rc = img->fops->read(entry, sizeof entry, img->f);
-               if (rc < sizeof entry) {
-                       goto readerr;
-               }
+       /* Read embedded palette header */
+       if (img->fops->read(buf, 4, img->f) < 4)
+               goto readerr;
 
-               if (entry[0] != 0) {
-                       lbx_error_raise(LBX_EFORMAT);
-                       return -1;
-               }
+       palette_start = unpack_16_le(buf+0);
+       palette_count = unpack_16_le(buf+2);
+       if (palette_start + palette_count > 256) {
+               lbx_error_raise(LBX_EFORMAT);
+               return -1;
+       }
 
-               palette[img->palstart + i] = (struct lbx_colour){
-                       .red    = entry[1],
-                       .green  = entry[2],
-                       .blue   = entry[3],
-                       .active = 1,
-               };
+       if (out) {
+               rc = read_palette(img->f, img->fops,
+                                 out+palette_start, palette_count,
+                                 false);
+               if (rc < 0)
+                       return -1;
        }
 
-       return 0;
+       return palette_count;
 readerr:
        if (img->fops->eof(img->f))
                lbx_error_raise(LBX_EEOF);
@@ -421,9 +404,7 @@ void lbx_img_getinfo(struct lbx_image *pub, struct lbx_imginfo *info)
 {
        struct lbx_image_priv *img = (struct lbx_image_priv *)pub;
 
-       *info = (struct lbx_imginfo) {
-               .palettesz  = (img->flags & FLAG_PALETTE) ? img->palcount : 0,
-       };
+       *info = (struct lbx_imginfo) { 0 };
 
        /* There seems to be two ways of specifying that an image loops. */
        if (img->flags & FLAG_LOOPING) {