+write_masked_index_frame(png_structp png, png_infop info,
+ unsigned char **framedata, unsigned char **mask)
+{
+ png_uint_32 width = png_get_image_width(png, info);
+ png_uint_32 height = png_get_image_height(png, info);
+ unsigned char (*row)[2];
+ jmp_buf parent;
+
+ if (width >= PNG_UINT_32_MAX / sizeof *row)
+ fatal(png, -1, "image too wide to allocate row buffer");
+
+ row = png_malloc(png, width * sizeof *row);
+
+ /*
+ * We need to establish our own error handler to free the row buffer.
+ * Some care must be taken to save/restore the caller's handler.
+ */
+ memcpy(&parent, &png_jmpbuf(png), sizeof parent);
+ if (setjmp(png_jmpbuf(png))) {
+ png_free(png, row);
+
+ memcpy(&png_jmpbuf(png), &parent, sizeof parent);
+ png_longjmp(png, 1);
+ }
+
+ png_write_info(png, info);
+ for (png_uint_32 y = 0; y < height; y++) {
+ for (png_uint_32 x = 0; x < width; x++) {
+ row[x][0] = framedata[y][x];
+ row[x][1] = mask[y][x] ? -1 : 0;
+ }
+ png_write_row(png, (void *)row);
+ }
+ png_write_end(png, NULL);
+
+ memcpy(&png_jmpbuf(png), &parent, sizeof parent);
+}
+
+static void
+write_palette_frame(png_structp png, png_infop info,
+ unsigned char **framedata, struct lbx_colour *palette)