1 //========================================================================
5 // This file is licensed under the GPLv2 or later
7 // Copyright 2005 Jeff Muizelaar <jeff@infidigm.net>
8 // Copyright 2005-2010, 2012 Albert Astals Cid <aacid@kde.org>
9 // Copyright 2009 Ryszard Trojnacki <rysiek@menel.com>
10 // Copyright 2010 Carlos Garcia Campos <carlosgc@gnome.org>
11 // Copyright 2011 Daiki Ueno <ueno@unixuser.org>
12 // Copyright 2011 Tomas Hoger <thoger@redhat.com>
13 // Copyright 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
15 //========================================================================
17 #include "DCTStream.h"
19 static void str_init_source(j_decompress_ptr cinfo
)
23 static boolean
str_fill_input_buffer(j_decompress_ptr cinfo
)
26 struct str_src_mgr
* src
= (struct str_src_mgr
*)cinfo
->src
;
27 if (src
->index
== 0) {
31 else if (src
->index
== 1) {
35 else c
= src
->str
->getChar();
39 src
->pub
.next_input_byte
= &src
->buffer
;
40 src
->pub
.bytes_in_buffer
= 1;
46 static void str_skip_input_data(j_decompress_ptr cinfo
, long num_bytes
)
48 struct str_src_mgr
* src
= (struct str_src_mgr
*)cinfo
->src
;
50 while (num_bytes
> (long) src
->pub
.bytes_in_buffer
) {
51 num_bytes
-= (long) src
->pub
.bytes_in_buffer
;
52 str_fill_input_buffer(cinfo
);
54 src
->pub
.next_input_byte
+= (size_t) num_bytes
;
55 src
->pub
.bytes_in_buffer
-= (size_t) num_bytes
;
59 static void str_term_source(j_decompress_ptr cinfo
)
63 DCTStream::DCTStream(Stream
*strA
, int colorXformA
, Object
*dict
, int recursion
) :
65 colorXform
= colorXformA
;
69 dict
->dictLookup("Width", &obj
, recursion
);
70 err
.width
= (obj
.isInt() && obj
.getInt() <= JPEG_MAX_DIMENSION
) ? obj
.getInt() : 0;
72 dict
->dictLookup("Height", &obj
, recursion
);
73 err
.height
= (obj
.isInt() && obj
.getInt() <= JPEG_MAX_DIMENSION
) ? obj
.getInt() : 0;
76 err
.height
= err
.width
= 0;
80 DCTStream::~DCTStream() {
81 jpeg_destroy_decompress(&cinfo
);
85 static void exitErrorHandler(jpeg_common_struct
*error
) {
86 j_decompress_ptr cinfo
= (j_decompress_ptr
)error
;
87 str_error_mgr
* err
= (struct str_error_mgr
*)cinfo
->err
;
88 if (cinfo
->err
->msg_code
== JERR_IMAGE_TOO_BIG
&& err
->width
!= 0 && err
->height
!= 0) {
89 cinfo
->image_height
= err
->height
;
90 cinfo
->image_width
= err
->width
;
92 longjmp(err
->setjmp_buffer
, 1);
96 void DCTStream::init()
98 jpeg_std_error(&err
.pub
);
99 err
.pub
.error_exit
= &exitErrorHandler
;
100 src
.pub
.init_source
= str_init_source
;
101 src
.pub
.fill_input_buffer
= str_fill_input_buffer
;
102 src
.pub
.skip_input_data
= str_skip_input_data
;
103 src
.pub
.resync_to_restart
= jpeg_resync_to_restart
;
104 src
.pub
.term_source
= str_term_source
;
105 src
.pub
.bytes_in_buffer
= 0;
106 src
.pub
.next_input_byte
= NULL
;
112 cinfo
.err
= &err
.pub
;
113 if (!setjmp(err
.setjmp_buffer
)) {
114 jpeg_create_decompress(&cinfo
);
115 cinfo
.src
= (jpeg_source_mgr
*)&src
;
120 void DCTStream::reset() {
127 jpeg_destroy_decompress(&cinfo
);
131 // JPEG data has to start with 0xFF 0xD8
132 // but some pdf like the one on
133 // https://bugs.freedesktop.org/show_bug.cgi?id=3299
134 // does have some garbage before that this seeks for
135 // the start marker...
136 bool startFound
= false;
145 error(errSyntaxError
, -1, "Could not find start of jpeg data");
148 if (c
!= 0xFF) c
= 0;
158 else startFound
= true;
162 if (!setjmp(err
.setjmp_buffer
))
164 if (jpeg_read_header(&cinfo
, TRUE
) != JPEG_SUSPENDED
)
166 // figure out color transform
167 if (colorXform
== -1 && !cinfo
.saw_Adobe_marker
) {
168 if (cinfo
.num_components
== 3) {
169 if (cinfo
.saw_JFIF_marker
) {
171 } else if (cinfo
.cur_comp_info
[0]->component_id
== 82 &&
172 cinfo
.cur_comp_info
[1]->component_id
== 71 &&
173 cinfo
.cur_comp_info
[2]->component_id
== 66) { // ASCII "RGB"
181 } else if (cinfo
.saw_Adobe_marker
) {
182 colorXform
= cinfo
.Adobe_transform
;
185 switch (cinfo
.num_components
) {
187 cinfo
.jpeg_color_space
= colorXform
? JCS_YCbCr
: JCS_RGB
;
190 cinfo
.jpeg_color_space
= colorXform
? JCS_YCCK
: JCS_CMYK
;
194 jpeg_start_decompress(&cinfo
);
196 row_stride
= cinfo
.output_width
* cinfo
.output_components
;
197 row_buffer
= cinfo
.mem
->alloc_sarray((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, row_stride
, 1);
202 // we can not go with inline since gcc
203 // refuses to inline because of setjmp
204 #define DO_GET_CHAR \
205 if (current == limit) { \
206 if (cinfo.output_scanline < cinfo.output_height) \
208 if (!setjmp(err.setjmp_buffer)) \
210 if (!jpeg_read_scanlines(&cinfo, row_buffer, 1)) c = EOF; \
212 current = &row_buffer[0][0]; \
213 limit = &row_buffer[0][(cinfo.output_width - 1) * cinfo.output_components] + cinfo.output_components; \
226 int DCTStream::getChar() {
234 int DCTStream::getChars(int nChars
, Guchar
*buffer
) {
236 for (int i
= 0; i
< nChars
; ++i
) {
238 if (likely(c
!= EOF
)) buffer
[i
] = c
;
244 int DCTStream::lookChar() {
245 if (unlikely(current
== NULL
)) {
251 GooString
*DCTStream::getPSFilter(int psLevel
, const char *indent
) {
257 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
260 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
264 GBool
DCTStream::isBinary(GBool last
) {
265 return str
->isBinary(gTrue
);