--- /dev/null
+/*
+ * JPEG decoding using IJG libjpeg
+ * tested with library release 6b of 27-Mar-1998 (jpegsrc.v6b.tar.gz)
+ *
+ * based on djpeg.c & example.c, (c) 1991-1997, Thomas G. Lane,
+ * part of the Independent JPEG Group's software.
+ *
+ * adapted by Marek Peca <mp@duch.cz> 2009/04
+ * for the EUROBOT competition team
+ * of the Dept. of Control Engineering http://dce.fel.cvut.cz/
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+#include <jpeglib.h>
+
+#include "decjpeg.h"
+
+/** error manager **/
+
+struct error_mgr {
+ struct jpeg_error_mgr jerr;
+ jmp_buf setjmp_addr;
+};
+
+void error_exit(j_common_ptr cinfo) {
+ struct error_mgr *err = (struct error_mgr*)cinfo->err;
+ longjmp(err->setjmp_addr, 1);
+}
+
+/** compressed source manager **/
+
+struct source_mgr {
+ struct jpeg_source_mgr jsrc;
+ uint8_t *buffer;
+ size_t length;
+};
+
+void init_source(j_decompress_ptr cinfo) {
+ struct source_mgr *src = (struct source_mgr*)cinfo->src;
+
+ src->jsrc.next_input_byte = src->buffer;
+ src->jsrc.bytes_in_buffer = src->length;
+}
+
+boolean fill_input_buffer(j_decompress_ptr cinfo) {
+ return FALSE;
+}
+
+void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
+ struct source_mgr *src = (struct source_mgr*)cinfo->src;
+
+ src->jsrc.next_input_byte += (size_t)num_bytes;
+ src->jsrc.bytes_in_buffer -= (size_t)num_bytes;
+}
+
+void term_source(j_decompress_ptr cinfo) {
+ /*NOP*/
+}
+
+/** actual decoding routine **/
+
+/**
+ * Decode JPEG image to RGB image, from memory buffer to memory buffer
+ * @param jpeg JPEG encoded image data
+ * @param jpeg_size >= actual length of JPEG data
+ * @param rgb RGB (24 bit) output buffer
+ * @param max_rgb_size >= size of RGB buffer (stop filling and return without
+ * an error, if full)
+ * @param w return width (NULL if not interested)
+ * @param h return height (NULL if not interested)
+ * @return -1 fatal error occured, 0 OK, >0 number of JPEG lib warnings
+ */
+int jpeg_decode(uint8_t *jpeg, size_t jpeg_size,
+ uint8_t *rgb, size_t max_rgb_size,
+ unsigned *w, unsigned *h)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct error_mgr err;
+ struct source_mgr src;
+ uint8_t *ptr = rgb, *out_row[] = { ptr };
+ size_t row_size;
+
+ jpeg_create_decompress(&cinfo);
+
+#if 1
+ /* setup custom error handling (deactivate default exit()) */
+ cinfo.err = jpeg_std_error(&err.jerr);
+ err.jerr.error_exit = error_exit;
+ if (setjmp(err.setjmp_addr)) {
+ jpeg_destroy_decompress(&cinfo);
+ /* fatal error occured */
+ return -1;
+ }
+#else
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+#endif
+
+#if 1
+ /* initialize custom source -- whole JPEG memory buffer */
+ cinfo.src = (struct jpeg_source_mgr*)&src;
+ src.jsrc.init_source = init_source;
+ src.jsrc.fill_input_buffer = fill_input_buffer;
+ src.jsrc.skip_input_data = skip_input_data;
+ src.jsrc.resync_to_restart = jpeg_resync_to_restart; /* default */
+ src.jsrc.term_source = term_source;
+ src.buffer = jpeg;
+ src.length = jpeg_size;
+ /* should it be here, or in init_source only? */
+ src.jsrc.next_input_byte = src.buffer;
+ src.jsrc.bytes_in_buffer = src.length;
+#else
+ jpeg_stdio_src(&cinfo, stdin);
+#endif
+
+ jpeg_read_header(&cinfo, TRUE);
+
+ if (w)
+ *w = cinfo.image_width;
+ if (h)
+ *h = cinfo.image_height;
+
+ /* RGB should be selected.. */
+
+ jpeg_start_decompress(&cinfo);
+
+ row_size = 3*cinfo.output_width;
+ while ((cinfo.output_scanline < cinfo.output_height) &&
+ (ptr + row_size <= rgb + max_rgb_size)) {
+ out_row[0] = ptr;
+ jpeg_read_scanlines(&cinfo, out_row, 1);
+ ptr += row_size;
+ }
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ /* 0 no problems, >0 some warnings */
+ return err.jerr.num_warnings;
+}