Pillow
304 строки · 9.6 Кб
1/*
2* The Python Imaging Library.
3* $Id$
4*
5* decoder for JPEG image data.
6*
7* history:
8* 1996-05-02 fl Created
9* 1996-05-05 fl Handle small JPEG files correctly
10* 1996-05-28 fl Added "draft mode" support
11* 1997-01-25 fl Added colour conversion override
12* 1998-01-31 fl Adapted to libjpeg 6a
13* 1998-07-12 fl Extended YCbCr support
14* 1998-12-29 fl Added new state to handle suspension in multipass modes
15* 2000-10-12 fl Suppress warnings
16* 2000-12-04 fl Suppress errors beyond end of image data
17*
18* Copyright (c) 1998-2000 Secret Labs AB
19* Copyright (c) 1996-2000 Fredrik Lundh
20*
21* See the README file for details on usage and redistribution.
22*/
23
24#include "Imaging.h"25
26#ifdef HAVE_LIBJPEG27
28#undef HAVE_PROTOTYPES29#undef HAVE_STDLIB_H30#undef HAVE_STDDEF_H31#undef UINT832#undef UINT1633#undef UINT3234#undef INT1635#undef INT3236
37#include "Jpeg.h"38
39#define STRINGIFY(x) #x40#define TOSTRING(x) STRINGIFY(x)41
42// There is no way to compare versions on compile time,
43// so we have to do that in runtime.
44#ifdef LIBJPEG_TURBO_VERSION45char *libjpeg_turbo_version = TOSTRING(LIBJPEG_TURBO_VERSION);46#else47char *libjpeg_turbo_version = NULL;48#endif49
50int
51ImagingJpegUseJCSExtensions() {52int use_jcs_extensions = 0;53#ifdef JCS_EXTENSIONS54#if defined(LIBJPEG_TURBO_VERSION_NUMBER)55#if LIBJPEG_TURBO_VERSION_NUMBER >= 100201056use_jcs_extensions = 1;57#endif58#else59if (libjpeg_turbo_version) {60use_jcs_extensions = strcmp(libjpeg_turbo_version, "1.2.1") >= 0;61}62#endif63#endif64return use_jcs_extensions;65}
66
67/* -------------------------------------------------------------------- */
68/* Suspending input handler */
69/* -------------------------------------------------------------------- */
70
71METHODDEF(void)72stub(j_decompress_ptr cinfo) { /* empty */ }73
74METHODDEF(boolean)75fill_input_buffer(j_decompress_ptr cinfo) {76/* Suspension */77return FALSE;78}
79
80METHODDEF(void)81skip_input_data(j_decompress_ptr cinfo, long num_bytes) {82JPEGSOURCE *source = (JPEGSOURCE *)cinfo->src;83
84if (num_bytes > (long)source->pub.bytes_in_buffer) {85/* We need to skip more data than we have in the buffer.86This will force the JPEG library to suspend decoding. */
87source->skip = num_bytes - source->pub.bytes_in_buffer;88source->pub.next_input_byte += source->pub.bytes_in_buffer;89source->pub.bytes_in_buffer = 0;90} else {91/* Skip portion of the buffer */92source->pub.bytes_in_buffer -= num_bytes;93source->pub.next_input_byte += num_bytes;94source->skip = 0;95}96}
97
98GLOBAL(void)99jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE *source) {100cinfo->src = (void *)source;101
102/* Prepare for suspending reader */103source->pub.init_source = stub;104source->pub.fill_input_buffer = fill_input_buffer;105source->pub.skip_input_data = skip_input_data;106source->pub.resync_to_restart = jpeg_resync_to_restart;107source->pub.term_source = stub;108source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */109
110source->skip = 0;111}
112
113/* -------------------------------------------------------------------- */
114/* Error handler */
115/* -------------------------------------------------------------------- */
116
117METHODDEF(void)118error(j_common_ptr cinfo) {119JPEGERROR *error;120error = (JPEGERROR *)cinfo->err;121longjmp(error->setjmp_buffer, 1);122}
123
124METHODDEF(void)125output(j_common_ptr cinfo) { /* nothing */ }126
127/* -------------------------------------------------------------------- */
128/* Decoder */
129/* -------------------------------------------------------------------- */
130
131int
132ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {133JPEGSTATE *context = (JPEGSTATE *)state->context;134int ok;135
136if (setjmp(context->error.setjmp_buffer)) {137/* JPEG error handler */138jpeg_destroy_decompress(&context->cinfo);139state->errcode = IMAGING_CODEC_BROKEN;140return -1;141}142
143if (!state->state) {144/* Setup decompression context */145context->cinfo.err = jpeg_std_error(&context->error.pub);146context->error.pub.error_exit = error;147context->error.pub.output_message = output;148jpeg_create_decompress(&context->cinfo);149jpeg_buffer_src(&context->cinfo, &context->source);150
151/* Ready to decode */152state->state = 1;153}154
155/* Load the source buffer */156context->source.pub.next_input_byte = buf;157context->source.pub.bytes_in_buffer = bytes;158
159if (context->source.skip > 0) {160skip_input_data(&context->cinfo, context->source.skip);161if (context->source.skip > 0) {162return context->source.pub.next_input_byte - buf;163}164}165
166switch (state->state) {167case 1:168
169/* Read JPEG header, until we find an image body. */170do {171/* Note that we cannot return unless we have decoded172as much data as possible. */
173ok = jpeg_read_header(&context->cinfo, FALSE);174
175} while (ok == JPEG_HEADER_TABLES_ONLY);176
177if (ok == JPEG_SUSPENDED) {178break;179}180
181/* Decoder settings */182
183/* jpegmode indicates what's in the file; if not set, we'll184trust the decoder */
185if (strcmp(context->jpegmode, "L") == 0) {186context->cinfo.jpeg_color_space = JCS_GRAYSCALE;187} else if (strcmp(context->jpegmode, "RGB") == 0) {188context->cinfo.jpeg_color_space = JCS_RGB;189} else if (strcmp(context->jpegmode, "CMYK") == 0) {190context->cinfo.jpeg_color_space = JCS_CMYK;191} else if (strcmp(context->jpegmode, "YCbCr") == 0) {192context->cinfo.jpeg_color_space = JCS_YCbCr;193} else if (strcmp(context->jpegmode, "YCbCrK") == 0) {194context->cinfo.jpeg_color_space = JCS_YCCK;195}196
197/* rawmode indicates what we want from the decoder. if not198set, conversions are disabled */
199if (strcmp(context->rawmode, "L") == 0) {200context->cinfo.out_color_space = JCS_GRAYSCALE;201} else if (strcmp(context->rawmode, "RGB") == 0) {202context->cinfo.out_color_space = JCS_RGB;203}204#ifdef JCS_EXTENSIONS205else if (strcmp(context->rawmode, "RGBX") == 0) {206context->cinfo.out_color_space = JCS_EXT_RGBX;207}208#endif209else if (strcmp(context->rawmode, "CMYK") == 0 ||210strcmp(context->rawmode, "CMYK;I") == 0) {211context->cinfo.out_color_space = JCS_CMYK;212} else if (strcmp(context->rawmode, "YCbCr") == 0) {213context->cinfo.out_color_space = JCS_YCbCr;214} else if (strcmp(context->rawmode, "YCbCrK") == 0) {215context->cinfo.out_color_space = JCS_YCCK;216} else {217/* Disable decoder conversions */218context->cinfo.jpeg_color_space = JCS_UNKNOWN;219context->cinfo.out_color_space = JCS_UNKNOWN;220}221
222if (context->scale > 1) {223context->cinfo.scale_num = 1;224context->cinfo.scale_denom = context->scale;225}226if (context->draft) {227context->cinfo.do_fancy_upsampling = FALSE;228context->cinfo.dct_method = JDCT_FASTEST;229}230
231state->state++;232/* fall through */233
234case 2:235
236/* Set things up for decompression (this processes the entire237file if necessary to return data line by line) */
238if (!jpeg_start_decompress(&context->cinfo)) {239break;240}241
242state->state++;243/* fall through */244
245case 3:246
247/* Decompress a single line of data */248ok = 1;249while (state->y < state->ysize) {250ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1);251if (ok != 1) {252break;253}254state->shuffle(255(UINT8 *)im->image[state->y + state->yoff] +256state->xoff * im->pixelsize,257state->buffer,258state->xsize259);260state->y++;261}262if (ok != 1) {263break;264}265state->state++;266/* fall through */267
268case 4:269
270/* Finish decompression */271if (!jpeg_finish_decompress(&context->cinfo)) {272/* FIXME: add strictness mode test */273if (state->y < state->ysize) {274break;275}276}277
278/* Clean up */279jpeg_destroy_decompress(&context->cinfo);280/* if (jerr.pub.num_warnings) return BROKEN; */281return -1;282}283
284/* Return number of bytes consumed */285return context->source.pub.next_input_byte - buf;286}
287
288/* -------------------------------------------------------------------- */
289/* Cleanup */
290/* -------------------------------------------------------------------- */
291
292int
293ImagingJpegDecodeCleanup(ImagingCodecState state) {294/* called to free the decompression engine when the decode terminates295due to a corrupt or truncated image
296*/
297JPEGSTATE *context = (JPEGSTATE *)state->context;298
299/* Clean up */300jpeg_destroy_decompress(&context->cinfo);301return -1;302}
303
304#endif305