Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Imaging/libImaging/JpegDecode.c
diff options
context:
space:
mode:
Diffstat (limited to 'Imaging/libImaging/JpegDecode.c')
-rw-r--r--Imaging/libImaging/JpegDecode.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/Imaging/libImaging/JpegDecode.c b/Imaging/libImaging/JpegDecode.c
new file mode 100644
index 0000000..0e61aef
--- /dev/null
+++ b/Imaging/libImaging/JpegDecode.c
@@ -0,0 +1,266 @@
+/*
+ * The Python Imaging Library.
+ * $Id: JpegDecode.c 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * decoder for JPEG image data.
+ *
+ * history:
+ * 1996-05-02 fl Created
+ * 1996-05-05 fl Handle small JPEG files correctly
+ * 1996-05-28 fl Added "draft mode" support
+ * 1997-01-25 fl Added colour conversion override
+ * 1998-01-31 fl Adapted to libjpeg 6a
+ * 1998-07-12 fl Extended YCbCr support
+ * 1998-12-29 fl Added new state to handle suspension in multipass modes
+ * 2000-10-12 fl Suppress warnings
+ * 2000-12-04 fl Suppress errors beyond end of image data
+ *
+ * Copyright (c) 1998-2000 Secret Labs AB
+ * Copyright (c) 1996-2000 Fredrik Lundh
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBJPEG
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDLIB_H
+#undef HAVE_STDDEF_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Suspending input handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+stub(j_decompress_ptr cinfo)
+{
+ /* empty */
+}
+
+METHODDEF(boolean)
+fill_input_buffer(j_decompress_ptr cinfo)
+{
+ /* Suspension */
+ return FALSE;
+}
+
+METHODDEF(void)
+skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ JPEGSOURCE* source = (JPEGSOURCE*) cinfo->src;
+
+ if (num_bytes > (long) source->pub.bytes_in_buffer) {
+ /* We need to skip more data than we have in the buffer.
+ This will force the JPEG library to suspend decoding. */
+ source->skip = num_bytes - source->pub.bytes_in_buffer;
+ source->pub.next_input_byte += source->pub.bytes_in_buffer;
+ source->pub.bytes_in_buffer = 0;
+ } else {
+ /* Skip portion of the buffer */
+ source->pub.bytes_in_buffer -= num_bytes;
+ source->pub.next_input_byte += num_bytes;
+ source->skip = 0;
+ }
+}
+
+
+GLOBAL(void)
+jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE* source)
+{
+ cinfo->src = (void*) source;
+
+ /* Prepare for suspending reader */
+ source->pub.init_source = stub;
+ source->pub.fill_input_buffer = fill_input_buffer;
+ source->pub.skip_input_data = skip_input_data;
+ source->pub.resync_to_restart = jpeg_resync_to_restart;
+ source->pub.term_source = stub;
+ source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+
+ source->skip = 0;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Error handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+error(j_common_ptr cinfo)
+{
+ JPEGERROR* error;
+ error = (JPEGERROR*) cinfo->err;
+ longjmp(error->setjmp_buffer, 1);
+}
+
+METHODDEF(void)
+output(j_common_ptr cinfo)
+{
+ /* nothing */
+}
+
+/* -------------------------------------------------------------------- */
+/* Decoder */
+/* -------------------------------------------------------------------- */
+
+int
+ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
+{
+ JPEGSTATE* context = (JPEGSTATE*) state->context;
+ int ok;
+
+ if (setjmp(context->error.setjmp_buffer)) {
+ /* JPEG error handler */
+ jpeg_destroy_decompress(&context->cinfo);
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (!state->state) {
+
+ /* Setup decompression context */
+ context->cinfo.err = jpeg_std_error(&context->error.pub);
+ context->error.pub.error_exit = error;
+ context->error.pub.output_message = output;
+ jpeg_create_decompress(&context->cinfo);
+ jpeg_buffer_src(&context->cinfo, &context->source);
+
+ /* Ready to decode */
+ state->state = 1;
+
+ }
+
+ /* Load the source buffer */
+ context->source.pub.next_input_byte = buf;
+ context->source.pub.bytes_in_buffer = bytes;
+
+ if (context->source.skip > 0) {
+ skip_input_data(&context->cinfo, context->source.skip);
+ if (context->source.skip > 0)
+ return context->source.pub.next_input_byte - buf;
+ }
+
+ switch (state->state) {
+
+ case 1:
+
+ /* Read JPEG header, until we find an image body. */
+ do {
+
+ /* Note that we cannot return unless we have decoded
+ as much data as possible. */
+ ok = jpeg_read_header(&context->cinfo, FALSE);
+
+ } while (ok == JPEG_HEADER_TABLES_ONLY);
+
+ if (ok == JPEG_SUSPENDED)
+ break;
+
+ /* Decoder settings */
+
+ /* jpegmode indicates whats in the file; if not set, we'll
+ trust the decoder */
+ if (strcmp(context->jpegmode, "L") == 0)
+ context->cinfo.jpeg_color_space = JCS_GRAYSCALE;
+ else if (strcmp(context->jpegmode, "RGB") == 0)
+ context->cinfo.jpeg_color_space = JCS_RGB;
+ else if (strcmp(context->jpegmode, "CMYK") == 0)
+ context->cinfo.jpeg_color_space = JCS_CMYK;
+ else if (strcmp(context->jpegmode, "YCbCr") == 0)
+ context->cinfo.jpeg_color_space = JCS_YCbCr;
+ else if (strcmp(context->jpegmode, "YCbCrK") == 0) {
+ context->cinfo.jpeg_color_space = JCS_YCCK;
+ }
+
+ /* rawmode indicates what we want from the decoder. if not
+ set, conversions are disabled */
+ if (strcmp(context->rawmode, "L") == 0)
+ context->cinfo.out_color_space = JCS_GRAYSCALE;
+ else if (strcmp(context->rawmode, "RGB") == 0)
+ context->cinfo.out_color_space = JCS_RGB;
+ else if (strcmp(context->rawmode, "CMYK") == 0)
+ context->cinfo.out_color_space = JCS_CMYK;
+ else if (strcmp(context->rawmode, "YCbCr") == 0)
+ context->cinfo.out_color_space = JCS_YCbCr;
+ else if (strcmp(context->rawmode, "YCbCrK") == 0)
+ context->cinfo.out_color_space = JCS_YCCK;
+ else {
+ /* Disable decoder conversions */
+ context->cinfo.jpeg_color_space = JCS_UNKNOWN;
+ context->cinfo.out_color_space = JCS_UNKNOWN;
+ }
+
+ if (context->scale > 1) {
+ context->cinfo.scale_num = 1;
+ context->cinfo.scale_denom = context->scale;
+ }
+ if (context->draft) {
+ context->cinfo.do_fancy_upsampling = FALSE;
+ context->cinfo.dct_method = JDCT_FASTEST;
+ }
+
+ state->state++;
+ /* fall through */
+
+ case 2:
+
+ /* Set things up for decompression (this processes the entire
+ file if necessary to return data line by line) */
+ if (!jpeg_start_decompress(&context->cinfo))
+ break;
+
+ state->state++;
+ /* fall through */
+
+ case 3:
+
+ /* Decompress a single line of data */
+ ok = 1;
+ while (state->y < state->ysize) {
+ ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1);
+ if (ok != 1)
+ break;
+ state->shuffle((UINT8*) im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->buffer,
+ state->xsize);
+ state->y++;
+ }
+ if (ok != 1)
+ break;
+ state->state++;
+ /* fall through */
+
+ case 4:
+
+ /* Finish decompression */
+ if (!jpeg_finish_decompress(&context->cinfo)) {
+ /* FIXME: add strictness mode test */
+ if (state->y < state->ysize)
+ break;
+ }
+
+ /* Clean up */
+ jpeg_destroy_decompress(&context->cinfo);
+ /* if (jerr.pub.num_warnings) return BROKEN; */
+ return -1;
+
+ }
+
+ /* Return number of bytes consumed */
+ return context->source.pub.next_input_byte - buf;
+
+}
+
+#endif
+