diff options
Diffstat (limited to 'Build/source/libs/poppler/poppler-0.24.4/poppler/DCTStream.cc')
-rw-r--r-- | Build/source/libs/poppler/poppler-0.24.4/poppler/DCTStream.cc | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/Build/source/libs/poppler/poppler-0.24.4/poppler/DCTStream.cc b/Build/source/libs/poppler/poppler-0.24.4/poppler/DCTStream.cc new file mode 100644 index 00000000000..bfdb0eaf80a --- /dev/null +++ b/Build/source/libs/poppler/poppler-0.24.4/poppler/DCTStream.cc @@ -0,0 +1,266 @@ +//======================================================================== +// +// DCTStream.cc +// +// This file is licensed under the GPLv2 or later +// +// Copyright 2005 Jeff Muizelaar <jeff@infidigm.net> +// Copyright 2005-2010, 2012 Albert Astals Cid <aacid@kde.org> +// Copyright 2009 Ryszard Trojnacki <rysiek@menel.com> +// Copyright 2010 Carlos Garcia Campos <carlosgc@gnome.org> +// Copyright 2011 Daiki Ueno <ueno@unixuser.org> +// Copyright 2011 Tomas Hoger <thoger@redhat.com> +// Copyright 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de> +// +//======================================================================== + +#include "DCTStream.h" + +static void str_init_source(j_decompress_ptr cinfo) +{ +} + +static boolean str_fill_input_buffer(j_decompress_ptr cinfo) +{ + int c; + struct str_src_mgr * src = (struct str_src_mgr *)cinfo->src; + if (src->index == 0) { + c = 0xFF; + src->index++; + } + else if (src->index == 1) { + c = 0xD8; + src->index++; + } + else c = src->str->getChar(); + if (c != EOF) + { + src->buffer = c; + src->pub.next_input_byte = &src->buffer; + src->pub.bytes_in_buffer = 1; + return TRUE; + } + else return FALSE; +} + +static void str_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + struct str_src_mgr * src = (struct str_src_mgr *)cinfo->src; + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + str_fill_input_buffer(cinfo); + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + +static void str_term_source(j_decompress_ptr cinfo) +{ +} + +DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion) : + FilterStream(strA) { + colorXform = colorXformA; + if (dict != NULL) { + Object obj; + + dict->dictLookup("Width", &obj, recursion); + err.width = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0; + obj.free(); + dict->dictLookup("Height", &obj, recursion); + err.height = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0; + obj.free(); + } else + err.height = err.width = 0; + init(); +} + +DCTStream::~DCTStream() { + jpeg_destroy_decompress(&cinfo); + delete str; +} + +static void exitErrorHandler(jpeg_common_struct *error) { + j_decompress_ptr cinfo = (j_decompress_ptr)error; + str_error_mgr * err = (struct str_error_mgr *)cinfo->err; + if (cinfo->err->msg_code == JERR_IMAGE_TOO_BIG && err->width != 0 && err->height != 0) { + cinfo->image_height = err->height; + cinfo->image_width = err->width; + } else { + longjmp(err->setjmp_buffer, 1); + } +} + +void DCTStream::init() +{ + jpeg_std_error(&err.pub); + err.pub.error_exit = &exitErrorHandler; + src.pub.init_source = str_init_source; + src.pub.fill_input_buffer = str_fill_input_buffer; + src.pub.skip_input_data = str_skip_input_data; + src.pub.resync_to_restart = jpeg_resync_to_restart; + src.pub.term_source = str_term_source; + src.pub.bytes_in_buffer = 0; + src.pub.next_input_byte = NULL; + src.str = str; + src.index = 0; + current = NULL; + limit = NULL; + + cinfo.err = &err.pub; + if (!setjmp(err.setjmp_buffer)) { + jpeg_create_decompress(&cinfo); + cinfo.src = (jpeg_source_mgr *)&src; + } + row_buffer = NULL; +} + +void DCTStream::reset() { + int row_stride; + + str->reset(); + + if (row_buffer) + { + jpeg_destroy_decompress(&cinfo); + init(); + } + + // JPEG data has to start with 0xFF 0xD8 + // but some pdf like the one on + // https://bugs.freedesktop.org/show_bug.cgi?id=3299 + // does have some garbage before that this seeks for + // the start marker... + bool startFound = false; + int c = 0, c2 = 0; + while (!startFound) + { + if (!c) + { + c = str->getChar(); + if (c == -1) + { + error(errSyntaxError, -1, "Could not find start of jpeg data"); + return; + } + if (c != 0xFF) c = 0; + } + else + { + c2 = str->getChar(); + if (c2 != 0xD8) + { + c = 0; + c2 = 0; + } + else startFound = true; + } + } + + if (!setjmp(err.setjmp_buffer)) + { + if (jpeg_read_header(&cinfo, TRUE) != JPEG_SUSPENDED) + { + // figure out color transform + if (colorXform == -1 && !cinfo.saw_Adobe_marker) { + if (cinfo.num_components == 3) { + if (cinfo.saw_JFIF_marker) { + colorXform = 1; + } else if (cinfo.cur_comp_info[0]->component_id == 82 && + cinfo.cur_comp_info[1]->component_id == 71 && + cinfo.cur_comp_info[2]->component_id == 66) { // ASCII "RGB" + colorXform = 0; + } else { + colorXform = 1; + } + } else { + colorXform = 0; + } + } else if (cinfo.saw_Adobe_marker) { + colorXform = cinfo.Adobe_transform; + } + + switch (cinfo.num_components) { + case 3: + cinfo.jpeg_color_space = colorXform ? JCS_YCbCr : JCS_RGB; + break; + case 4: + cinfo.jpeg_color_space = colorXform ? JCS_YCCK : JCS_CMYK; + break; + } + + jpeg_start_decompress(&cinfo); + + row_stride = cinfo.output_width * cinfo.output_components; + row_buffer = cinfo.mem->alloc_sarray((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + } + } +} + +// we can not go with inline since gcc +// refuses to inline because of setjmp +#define DO_GET_CHAR \ + if (current == limit) { \ + if (cinfo.output_scanline < cinfo.output_height) \ + { \ + if (!setjmp(err.setjmp_buffer)) \ + { \ + if (!jpeg_read_scanlines(&cinfo, row_buffer, 1)) c = EOF; \ + else { \ + current = &row_buffer[0][0]; \ + limit = &row_buffer[0][(cinfo.output_width - 1) * cinfo.output_components] + cinfo.output_components; \ + c = *current; \ + ++current; \ + } \ + } \ + else c = EOF; \ + } \ + else c = EOF; \ + } else { \ + c = *current; \ + ++current; \ + } \ + +int DCTStream::getChar() { + int c; + + DO_GET_CHAR + + return c; +} + +int DCTStream::getChars(int nChars, Guchar *buffer) { + int c; + for (int i = 0; i < nChars; ++i) { + DO_GET_CHAR + if (likely(c != EOF)) buffer[i] = c; + else return i; + } + return nChars; +} + +int DCTStream::lookChar() { + if (unlikely(current == NULL)) { + return EOF; + } + return *current; +} + +GooString *DCTStream::getPSFilter(int psLevel, const char *indent) { + GooString *s; + + if (psLevel < 2) { + return NULL; + } + if (!(s = str->getPSFilter(psLevel, indent))) { + return NULL; + } + s->append(indent)->append("<< >> /DCTDecode filter\n"); + return s; +} + +GBool DCTStream::isBinary(GBool last) { + return str->isBinary(gTrue); +} |