+static inline uns
+libjpeg_read_byte(struct libjpeg_read_internals *i)
+{
+ DBG("libjpeg_read_byte()");
+ if (!i->src.bytes_in_buffer)
+ if (!libjpeg_fill_input_buffer(&i->cinfo))
+ ERREXIT(&i->cinfo, JERR_CANT_SUSPEND);
+ i->src.bytes_in_buffer--;
+ return *i->src.next_input_byte++;
+}
+
+static inline void
+libjpeg_read_buf(struct libjpeg_read_internals *i, byte *buf, uns len)
+{
+ DBG("libjpeg_read_buf(len=%u)", len);
+ while (len)
+ {
+ if (!i->src.bytes_in_buffer)
+ if (!libjpeg_fill_input_buffer(&i->cinfo))
+ ERREXIT(&i->cinfo, JERR_CANT_SUSPEND);
+ uns buf_size = i->src.bytes_in_buffer;
+ uns read_size = MIN(buf_size, len);
+ memcpy(buf, i->src.next_input_byte, read_size);
+ i->src.bytes_in_buffer -= read_size;
+ i->src.next_input_byte += read_size;
+ len -= read_size;
+ }
+}
+
+static byte libjpeg_exif_header[6] = { 'E', 'x', 'i', 'f', 0, 0 };
+
+static boolean
+libjpeg_app1_preprocessor(j_decompress_ptr cinfo)
+{
+ struct libjpeg_read_internals *i = (struct libjpeg_read_internals *)cinfo;
+ struct image_io *io = i->err.io;
+ uns len = libjpeg_read_byte(i) << 8;
+ len += libjpeg_read_byte(i);
+ DBG("Found APP1 marker, len=%u", len);
+ if (len < 2)
+ return TRUE;
+ len -= 2;
+ if (len < 7 /*|| io->exif_size*/)
+ {
+ libjpeg_skip_input_data(cinfo, len);
+ return TRUE;
+ }
+ byte header[6];
+ libjpeg_read_buf(i, header, 6);
+ if (memcmp(header, libjpeg_exif_header, 6))
+ {
+ libjpeg_skip_input_data(cinfo, len - 6);
+ return TRUE;
+ }
+ io->exif_size = len;
+ io->exif_data = mp_alloc(io->internal_pool, len);
+ memcpy(io->exif_data, header, 6);
+ libjpeg_read_buf(i, io->exif_data + 6, len - 6);
+ DBG("Parsed EXIF of length %u", len);
+ return TRUE;
+}
+