+ 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++) {
+ unsigned long offset = (unsigned long) y * width + x;
+ bool vis;
+
+ vis = mask[offset/CHAR_BIT] & (1u << offset%CHAR_BIT);
+ row[x][0] = pixels[offset];
+ row[x][1] = -vis;
+ }
+ png_write_row(png, (void *)row);
+ }
+ png_write_end(png, NULL);
+
+ memcpy(&png_jmpbuf(png), &parent, sizeof parent);
+}
+
+static void
+write_index_frame(png_structp png, png_infop info, unsigned char *pixels)
+{
+ png_uint_32 width = png_get_image_width(png, info);
+ png_uint_32 height = png_get_image_height(png, info);
+
+ png_write_info(png, info);
+ for (png_uint_32 y = 0; y < height; y++) {
+ unsigned long offset = (unsigned long) y * width;
+
+ png_write_row(png, (void *)(pixels+offset));