--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "lbx.h"
+#include "byteorder.h"
+
+struct lbx_image {
+ FILE *f;
+ uint16_t width, height;
+ uint16_t wtf1, wtf2;
+ uint16_t offs, frames;
+ uint32_t offsets[];
+};
+
+struct lbx_image *lbximg_fopen(FILE *f)
+{
+ struct lbx_image tmp = {.f = f}, *new;
+
+ 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.wtf2, sizeof tmp.wtf2, 1, f) != 1) goto readerr;
+
+ tmp.width = letohs(tmp.width);
+ tmp.height = letohs(tmp.height);
+ tmp.wtf1 = letohs(tmp.wtf1);
+ tmp.offs = letohs(tmp.offs);
+ tmp.frames = letohs(tmp.frames);
+ tmp.wtf2 = letohs(tmp.wtf2);
+
+ /*
+ * DEBUG ONLY. These assertions exist to catch otherwise valid image
+ * files which differ from what I believe to be true of all LBX images.
+ * If we never find any exceptions, we can replace the assertions with
+ * assumptions.
+ */
+ assert(tmp.wtf1 == 0);
+ assert(tmp.offs == tmp.frames + 1);
+
+ new = malloc(sizeof *new + tmp.offs * sizeof *new->offsets);
+ if (!new) {
+ lbx_errno = -errno;
+ return NULL;
+ }
+
+ *new = tmp;
+
+ if (fread(new->offsets, sizeof *new->offsets, new->offs, f) != new->offs)
+ goto readerr;
+
+ return new;
+readerr:
+ if (feof(f)) {
+ lbx_errno = LBX_EEOF;
+ } else {
+ lbx_errno = -errno;
+ }
+
+ free(new);
+ return NULL;
+}
+
+void lbximg_close(struct lbx_image *img)
+{
+ if (!img) return;
+
+ if (img->f) {
+ fclose(img->f);
+ }
+
+ free(img);
+}