We don't need to read the embedded palette information with the rest of
the header, we can defer that to much later when the palette is actually
needed. This makes more sense conceptually, simplifies the code a bit,
and saves some bytes in the image state structure.
Since we're basically rewriting lbx_img_getpalette anyway, take this
opportunity to give it a better interface. It now returns the number
of embedded palette entries, allowing us to eliminate the palette size
feature in lbx_img_getinfo.
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include <errno.h>
#include <inttypes.h>
#include <errno.h>
unsigned short wtf, flags;
unsigned char wtf2;
unsigned short wtf, flags;
unsigned char wtf2;
- unsigned short palstart, palcount;
const struct lbx_file_ops *fops;
int (*dtor)(void *handle);
void *f;
const struct lbx_file_ops *fops;
int (*dtor)(void *handle);
void *f;
/* State of frame readout */
unsigned currentx, currenty, currentn;
int read_state;
/* State of frame readout */
unsigned currentx, currenty, currentn;
int read_state;
img->offsets[i] = unpack_32_le(buf);
}
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;
- }
- }
-
-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 (fops->eof(f))
lbx_error_raise(LBX_EEOF);
return -1;
}
+ if (buf[0] != external) {
lbx_error_raise(LBX_EFORMAT);
return -1;
}
palette[i] = (struct lbx_colour) {
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,
-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;
{
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;
/* 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)) {
- 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;
readerr:
if (img->fops->eof(img->f))
lbx_error_raise(LBX_EEOF);
readerr:
if (img->fops->eof(img->f))
lbx_error_raise(LBX_EEOF);
{
struct lbx_image_priv *img = (struct lbx_image_priv *)pub;
{
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) {
/* There seems to be two ways of specifying that an image loops. */
if (img->flags & FLAG_LOOPING) {
struct lbx_imginfo {
unsigned char loopstart;
struct lbx_imginfo {
unsigned char loopstart;
- int palettesz, looping;
};
struct lbx_image *lbx_img_open(void *f, const struct lbx_file_ops *fops,
};
struct lbx_image *lbx_img_open(void *f, const struct lbx_file_ops *fops,
long lbx_img_read_row_header(struct lbx_image *img, unsigned *x, unsigned *y);
long lbx_img_read_row_data(struct lbx_image *img, void *buf);
long lbx_img_read_row_header(struct lbx_image *img, unsigned *x, unsigned *y);
long lbx_img_read_row_data(struct lbx_image *img, void *buf);
+int lbx_img_getpalette(struct lbx_image *img, struct lbx_colour *palette);
int lbx_img_loadpalette(void *f, const struct lbx_file_ops *fops,
int lbx_img_loadpalette(void *f, const struct lbx_file_ops *fops,
- struct lbx_colour palette[static 256]);
-int lbx_img_getpalette(struct lbx_image *img,
- struct lbx_colour palette[static 256]);
+ struct lbx_colour *palette);
void lbx_img_getinfo(struct lbx_image *img, struct lbx_imginfo *info);
void lbx_img_getinfo(struct lbx_image *img, struct lbx_imginfo *info);
static int loadoverride(FILE *f, struct lbx_colour palette[static 256])
{
static int loadoverride(FILE *f, struct lbx_colour palette[static 256])
{
- struct lbx_image *overimg = lbx_img_open(f, &lbx_default_fops, NULL);
- struct lbx_imginfo info;
+ struct lbx_image *img;
+ int rc, ret = 0;
+ img = lbx_img_open(f, &lbx_default_fops, NULL);
+ if (!img) {
tool_err(-1, "failed to open override image: %s", lbx_errmsg());
return -1;
}
tool_err(-1, "failed to open override image: %s", lbx_errmsg());
return -1;
}
- lbx_img_getinfo(overimg, &info);
-
- if (!info.palettesz) {
- tool_err(-1, "override image has no palette.");
- lbx_img_close(overimg);
- return -1;
- }
- if (lbx_img_getpalette(overimg, palette) == -1) {
+ rc = lbx_img_getpalette(img, palette);
+ if (rc < 0) {
tool_err(-1, "error reading override palette: %s", lbx_errmsg());
tool_err(-1, "error reading override palette: %s", lbx_errmsg());
- lbx_img_close(overimg);
- return -1;
+ ret = -1;
+ } else if (rc == 0) {
+ tool_err(-1, "override image has no palette.");
+ ret = -1;
- lbx_img_close(overimg);
- return 0;
+ lbx_img_close(img);
+ return ret;
-static int loadpalette(struct lbx_image *img, struct lbx_imginfo *info,
- FILE *palf, FILE *override,
- struct lbx_colour palette[static 256])
+static int loadpalette(struct lbx_image *img, FILE *palf, FILE *override,
+ struct lbx_colour *palette)
- int i;
-
- /* For sanity. */
- if (!palf && !info->palettesz && !override) {
- tool_err(-1, "no palette available.");
- return -1;
- }
/* Default the palette to a wonderful pink. */
/* Default the palette to a wonderful pink. */
- for (i = 0; i < 256; i++) {
+ for (unsigned i = 0; i < 256; i++) {
palette[i] = (struct lbx_colour){0x3f, 0x00, 0x3f};
}
/* Read the external palette, if any. */
palette[i] = (struct lbx_colour){0x3f, 0x00, 0x3f};
}
/* Read the external palette, if any. */
- if (palf && lbx_img_loadpalette(palf, &lbx_default_fops, palette) != 0) {
- tool_err(-1, "error reading external palette: %s", lbx_errmsg());
- return -1;
+ if (palf) {
+ rc = lbx_img_loadpalette(palf, &lbx_default_fops, palette);
+ if (rc < 0) {
+ tool_err(-1, "error reading external palette: %s", lbx_errmsg());
+ return -1;
+ }
+
+ ret = 0;
- /* Read the embedded palette, if any. */
- if (info->palettesz && lbx_img_getpalette(img, palette) == -1) {
+ /* Read the embedded palette */
+ rc = lbx_img_getpalette(img, palette);
+ if (rc < 0) {
tool_err(-1, "error reading embedded palette: %s", lbx_errmsg());
return -1;
tool_err(-1, "error reading embedded palette: %s", lbx_errmsg());
return -1;
+ } else if (rc > 0) {
+ ret = 0;
}
/* Read the override palette, if any. */
}
/* Read the override palette, if any. */
- if (override && loadoverride(override, palette) == -1) {
- return -1;
+ if (override) {
+ rc = loadoverride(override, palette);
+ if (rc < 0)
+ return -1;
+ ret = 0;
+ /* If we literally have no palette data at all, may as well fail. */
+ if (ret < 0)
+ tool_err(-1, "no palette available.");
+ return ret;
}
/* Return true iff a divides b. */
}
/* Return true iff a divides b. */
{
unsigned char *pixels = NULL, *pixel_mask = NULL, *framebits = NULL;
struct lbx_colour palette[256];
{
unsigned char *pixels = NULL, *pixel_mask = NULL, *framebits = NULL;
struct lbx_colour palette[256];
- struct lbx_imginfo info;
int rc, ret = EXIT_FAILURE;
int extracted = 0;
unsigned int i;
int rc, ret = EXIT_FAILURE;
int extracted = 0;
unsigned int i;
assert(fmt >= 0 && fmt < sizeof formats / sizeof formats[0]);
assert(fmt >= 0 && fmt < sizeof formats / sizeof formats[0]);
- lbx_img_getinfo(img, &info);
-
npixels = img->width;
if (img->height && npixels >= SIZE_MAX / img->height) {
tool_err(-1, "image too large");
npixels = img->width;
if (img->height && npixels >= SIZE_MAX / img->height) {
tool_err(-1, "image too large");
- if (loadpalette(img, &info, palf, override, palette) == -1) {
+ if (loadpalette(img, palf, override, palette) == -1) {
ret = EXIT_FAILURE;
goto err;
}
ret = EXIT_FAILURE;
goto err;
}
if (verbose || mode == MODE_IDENT) {
struct lbx_imginfo info;
if (verbose || mode == MODE_IDENT) {
struct lbx_imginfo info;
if (!file)
file = "stdin";
if (!file)
file = "stdin";
+ palette_count = lbx_img_getpalette(img, NULL);
+ if (palette_count < 0) {
+ tool_err(-1, "error reading image: %s", lbx_errmsg());
+ return EXIT_FAILURE;
+ }
+
lbx_img_getinfo(img, &info);
printf("%s is %hux%hu LBX image, %hhu frame(s)%s%s%s\n",
file, img->width, img->height, img->frames,
lbx_img_getinfo(img, &info);
printf("%s is %hux%hu LBX image, %hhu frame(s)%s%s%s\n",
file, img->width, img->height, img->frames,
- info.palettesz ? ", embedded palette" : "",
+ palette_count ? ", embedded palette" : "",
img->chunk ? ", chunked" : "",
info.looping ? ", loops" : "");
}
img->chunk ? ", chunked" : "",
info.looping ? ", loops" : "");
}