- rc = fread(new->offsets, sizeof *new->offsets, new->frames+1, f);
- if (rc < new->frames+1)
- goto readerr;
- new->foff += sizeof *new->offsets * (new->frames+1);
-
- if (new->flags & FLAG_PALETTE) {
- if (fread(&new->palstart, sizeof new->palstart, 1, f) != 1)
- goto readerr;
- if (fread(&new->palcount, sizeof new->palcount, 1, f) != 1)
- goto readerr;
-
- new->palstart = letohs(new->palstart);
- new->palcount = letohs(new->palcount);
- new->foff += sizeof new->palstart + sizeof new->palcount;
- new->paloff = new->foff;
-
- if (new->palstart + new->palcount > 256) {
- lbx_errno = LBX_EFORMAT;
- free(new);
+struct lbx_image *lbx_img_open(void *f, const struct lbx_file_ops *fops,
+ int (*destructor)(void *))
+{
+ unsigned char hdr_buf[HDR_LEN];
+ struct lbx_image_priv *img;
+
+ if (fops->read(hdr_buf, sizeof hdr_buf, f) != sizeof hdr_buf) {
+ if (fops->eof(f))
+ lbx_error_raise(LBX_EEOF);
+ return NULL;
+ }
+
+ img = lbx_img_init(hdr_buf);
+ if (!img)
+ return NULL;
+
+ img->f = f;
+ img->fops = fops;
+ img->dtor = destructor;
+
+ /*
+ * DEBUG ONLY. These assertions exist to catch otherwise valid image
+ * files which differ from what I believe to be true of all LBX images.
+ * When we can decode every image, then these assertions should be
+ * replaced with constraints.
+ */
+ _lbx_assert(img->wtf == 0); /* version? */
+ _lbx_assert(img->wtf2 == 0); /* very likely is simply reserved. */
+ _lbx_assert(!(img->flags & ~FLAG_ALL));
+
+ /* Read all offsets. Should be merged with identical code in lbx.c */
+ for (unsigned i = 0; i <= img->pub.frames; i++) {
+ unsigned char buf[4];
+
+ if (fops->read(buf, sizeof buf, f) != sizeof buf) {
+ if (fops->eof(f))
+ lbx_error_raise(LBX_EEOF);
+ free(img);