1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
3 *
4 * Copyright © 2008 Adrian Johnson
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
13 *
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
19 *
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
24 *
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
28 *
29 * The Original Code is the cairo graphics library.
30 *
31 * The Initial Developer of the Original Code is Adrian Johnson.
32 *
33 * Contributor(s):
34 * Adrian Johnson <ajohnson@redneon.com>
35 */
36
37 #include "cairoint.h"
38
39 #include "cairo-error-private.h"
40 #include "cairo-image-info-private.h"
41
42 /* JPEG (image/jpeg)
43 *
44 * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
45 */
46
47 /* Markers with no parameters. All other markers are followed by a two
48 * byte length of the parameters. */
49 #define TEM 0x01
50 #define RST_begin 0xd0
51 #define RST_end 0xd7
52 #define SOI 0xd8
53 #define EOI 0xd9
54
55 /* Start of frame markers. */
56 #define SOF0 0xc0
57 #define SOF1 0xc1
58 #define SOF2 0xc2
59 #define SOF3 0xc3
60 #define SOF5 0xc5
61 #define SOF6 0xc6
62 #define SOF7 0xc7
63 #define SOF9 0xc9
64 #define SOF10 0xca
65 #define SOF11 0xcb
66 #define SOF13 0xcd
67 #define SOF14 0xce
68 #define SOF15 0xcf
69
70 static const unsigned char *
_jpeg_skip_segment(const unsigned char * p)71 _jpeg_skip_segment (const unsigned char *p)
72 {
73 int len;
74
75 p++;
76 len = (p[0] << 8) | p[1];
77
78 return p + len;
79 }
80
81 static void
_jpeg_extract_info(cairo_image_info_t * info,const unsigned char * p)82 _jpeg_extract_info (cairo_image_info_t *info, const unsigned char *p)
83 {
84 info->width = (p[6] << 8) + p[7];
85 info->height = (p[4] << 8) + p[5];
86 info->num_components = p[8];
87 info->bits_per_component = p[3];
88 }
89
90 cairo_int_status_t
_cairo_image_info_get_jpeg_info(cairo_image_info_t * info,const unsigned char * data,long length)91 _cairo_image_info_get_jpeg_info (cairo_image_info_t *info,
92 const unsigned char *data,
93 long length)
94 {
95 const unsigned char *p = data;
96
97 while (p + 1 < data + length) {
98 if (*p != 0xff)
99 return CAIRO_INT_STATUS_UNSUPPORTED;
100 p++;
101
102 switch (*p) {
103 /* skip fill bytes */
104 case 0xff:
105 p++;
106 break;
107
108 case TEM:
109 case SOI:
110 case EOI:
111 p++;
112 break;
113
114 case SOF0:
115 case SOF1:
116 case SOF2:
117 case SOF3:
118 case SOF5:
119 case SOF6:
120 case SOF7:
121 case SOF9:
122 case SOF10:
123 case SOF11:
124 case SOF13:
125 case SOF14:
126 case SOF15:
127 /* Start of frame found. Extract the image parameters. */
128 if (p + 8 > data + length)
129 return CAIRO_INT_STATUS_UNSUPPORTED;
130
131 _jpeg_extract_info (info, p);
132 return CAIRO_STATUS_SUCCESS;
133
134 default:
135 if (*p >= RST_begin && *p <= RST_end) {
136 p++;
137 break;
138 }
139
140 if (p + 3 > data + length)
141 return CAIRO_INT_STATUS_UNSUPPORTED;
142
143 p = _jpeg_skip_segment (p);
144 break;
145 }
146 }
147
148 return CAIRO_STATUS_SUCCESS;
149 }
150
151 /* JPEG 2000 (image/jp2)
152 *
153 * http://www.jpeg.org/public/15444-1annexi.pdf
154 */
155
156 #define JPX_FILETYPE 0x66747970
157 #define JPX_JP2_HEADER 0x6A703268
158 #define JPX_IMAGE_HEADER 0x69686472
159
160 static const unsigned char _jpx_signature[] = {
161 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a
162 };
163
164 static const unsigned char *
_jpx_next_box(const unsigned char * p)165 _jpx_next_box (const unsigned char *p)
166 {
167 return p + get_unaligned_be32 (p);
168 }
169
170 static const unsigned char *
_jpx_get_box_contents(const unsigned char * p)171 _jpx_get_box_contents (const unsigned char *p)
172 {
173 return p + 8;
174 }
175
176 static cairo_bool_t
_jpx_match_box(const unsigned char * p,const unsigned char * end,uint32_t type)177 _jpx_match_box (const unsigned char *p, const unsigned char *end, uint32_t type)
178 {
179 uint32_t length;
180
181 if (p + 8 < end) {
182 length = get_unaligned_be32 (p);
183 if (get_unaligned_be32 (p + 4) == type && p + length < end)
184 return TRUE;
185 }
186
187 return FALSE;
188 }
189
190 static const unsigned char *
_jpx_find_box(const unsigned char * p,const unsigned char * end,uint32_t type)191 _jpx_find_box (const unsigned char *p, const unsigned char *end, uint32_t type)
192 {
193 while (p < end) {
194 if (_jpx_match_box (p, end, type))
195 return p;
196 p = _jpx_next_box (p);
197 }
198
199 return NULL;
200 }
201
202 static void
_jpx_extract_info(const unsigned char * p,cairo_image_info_t * info)203 _jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
204 {
205 info->height = get_unaligned_be32 (p);
206 info->width = get_unaligned_be32 (p + 4);
207 info->num_components = (p[8] << 8) + p[9];
208 info->bits_per_component = p[10];
209 }
210
211 cairo_int_status_t
_cairo_image_info_get_jpx_info(cairo_image_info_t * info,const unsigned char * data,unsigned long length)212 _cairo_image_info_get_jpx_info (cairo_image_info_t *info,
213 const unsigned char *data,
214 unsigned long length)
215 {
216 const unsigned char *p = data;
217 const unsigned char *end = data + length;
218
219 /* First 12 bytes must be the JPEG 2000 signature box. */
220 if (length < ARRAY_LENGTH(_jpx_signature) ||
221 memcmp(p, _jpx_signature, ARRAY_LENGTH(_jpx_signature)) != 0)
222 return CAIRO_INT_STATUS_UNSUPPORTED;
223
224 p += ARRAY_LENGTH(_jpx_signature);
225
226 /* Next box must be a File Type Box */
227 if (! _jpx_match_box (p, end, JPX_FILETYPE))
228 return CAIRO_INT_STATUS_UNSUPPORTED;
229
230 p = _jpx_next_box (p);
231
232 /* Locate the JP2 header box. */
233 p = _jpx_find_box (p, end, JPX_JP2_HEADER);
234 if (!p)
235 return CAIRO_INT_STATUS_UNSUPPORTED;
236
237 /* Step into the JP2 header box. First box must be the Image
238 * Header */
239 p = _jpx_get_box_contents (p);
240 if (! _jpx_match_box (p, end, JPX_IMAGE_HEADER))
241 return CAIRO_INT_STATUS_UNSUPPORTED;
242
243 /* Get the image info */
244 p = _jpx_get_box_contents (p);
245 _jpx_extract_info (p, info);
246
247 return CAIRO_STATUS_SUCCESS;
248 }
249
250 /* PNG (image/png)
251 *
252 * http://www.w3.org/TR/2003/REC-PNG-20031110/
253 */
254
255 #define PNG_IHDR 0x49484452
256
257 static const unsigned char _png_magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
258
259 cairo_int_status_t
_cairo_image_info_get_png_info(cairo_image_info_t * info,const unsigned char * data,unsigned long length)260 _cairo_image_info_get_png_info (cairo_image_info_t *info,
261 const unsigned char *data,
262 unsigned long length)
263 {
264 const unsigned char *p = data;
265 const unsigned char *end = data + length;
266
267 if (length < 8 || memcmp (data, _png_magic, 8) != 0)
268 return CAIRO_INT_STATUS_UNSUPPORTED;
269
270 p += 8;
271
272 /* The first chunk must be IDHR. IDHR has 13 bytes of data plus
273 * the 12 bytes of overhead for the chunk. */
274 if (p + 13 + 12 > end)
275 return CAIRO_INT_STATUS_UNSUPPORTED;
276
277 p += 4;
278 if (get_unaligned_be32 (p) != PNG_IHDR)
279 return CAIRO_INT_STATUS_UNSUPPORTED;
280
281 p += 4;
282 info->width = get_unaligned_be32 (p);
283 p += 4;
284 info->height = get_unaligned_be32 (p);
285
286 return CAIRO_STATUS_SUCCESS;
287 }
288
289 static const unsigned char *
_jbig2_find_data_end(const unsigned char * p,const unsigned char * end,int type)290 _jbig2_find_data_end (const unsigned char *p,
291 const unsigned char *end,
292 int type)
293 {
294 unsigned char end_seq[2];
295 int mmr;
296
297 /* Segments of type "Immediate generic region" may have an
298 * unspecified data length. The JBIG2 specification specifies the
299 * method to find the end of the data for these segments. */
300 if (type == 36 || type == 38 || type == 39) {
301 if (p + 18 < end) {
302 mmr = p[17] & 0x01;
303 if (mmr) {
304 /* MMR encoding ends with 0x00, 0x00 */
305 end_seq[0] = 0x00;
306 end_seq[1] = 0x00;
307 } else {
308 /* Template encoding ends with 0xff, 0xac */
309 end_seq[0] = 0xff;
310 end_seq[1] = 0xac;
311 }
312 p += 18;
313 while (p < end) {
314 if (p[0] == end_seq[0] && p[1] == end_seq[1]) {
315 /* Skip the 2 terminating bytes and the 4 byte row count that follows. */
316 p += 6;
317 if (p < end)
318 return p;
319 }
320 p++;
321 }
322 }
323 }
324
325 return NULL;
326 }
327
328 static const unsigned char *
_jbig2_get_next_segment(const unsigned char * p,const unsigned char * end,int * type,const unsigned char ** data,unsigned long * data_len)329 _jbig2_get_next_segment (const unsigned char *p,
330 const unsigned char *end,
331 int *type,
332 const unsigned char **data,
333 unsigned long *data_len)
334 {
335 unsigned long seg_num;
336 cairo_bool_t big_page_size;
337 int num_segs;
338 int ref_seg_bytes;
339 int referred_size;
340
341 if (p + 6 >= end)
342 return NULL;
343
344 seg_num = get_unaligned_be32 (p);
345 *type = p[4] & 0x3f;
346 big_page_size = (p[4] & 0x40) != 0;
347 p += 5;
348
349 num_segs = p[0] >> 5;
350 if (num_segs == 7) {
351 num_segs = get_unaligned_be32 (p) & 0x1fffffff;
352 ref_seg_bytes = 4 + ((num_segs + 1)/8);
353 } else {
354 ref_seg_bytes = 1;
355 }
356 p += ref_seg_bytes;
357
358 if (seg_num <= 256)
359 referred_size = 1;
360 else if (seg_num <= 65536)
361 referred_size = 2;
362 else
363 referred_size = 4;
364
365 p += num_segs * referred_size;
366 p += big_page_size ? 4 : 1;
367 if (p + 4 >= end)
368 return NULL;
369
370 *data_len = get_unaligned_be32 (p);
371 p += 4;
372 *data = p;
373
374 if (*data_len == 0xffffffff) {
375 /* if data length is -1 we have to scan through the data to find the end */
376 p = _jbig2_find_data_end (*data, end, *type);
377 if (!p || p >= end)
378 return NULL;
379
380 *data_len = p - *data;
381 } else {
382 p += *data_len;
383 }
384
385 if (p < end)
386 return p;
387 else
388 return NULL;
389 }
390
391 static void
_jbig2_extract_info(cairo_image_info_t * info,const unsigned char * p)392 _jbig2_extract_info (cairo_image_info_t *info, const unsigned char *p)
393 {
394 info->width = get_unaligned_be32 (p);
395 info->height = get_unaligned_be32 (p + 4);
396 info->num_components = 1;
397 info->bits_per_component = 1;
398 }
399
400 cairo_int_status_t
_cairo_image_info_get_jbig2_info(cairo_image_info_t * info,const unsigned char * data,unsigned long length)401 _cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
402 const unsigned char *data,
403 unsigned long length)
404 {
405 const unsigned char *p = data;
406 const unsigned char *end = data + length;
407 int seg_type;
408 const unsigned char *seg_data;
409 unsigned long seg_data_len;
410
411 while (p && p < end) {
412 p = _jbig2_get_next_segment (p, end, &seg_type, &seg_data, &seg_data_len);
413 if (p && seg_type == 48 && seg_data_len > 8) {
414 /* page information segment */
415 _jbig2_extract_info (info, seg_data);
416 return CAIRO_STATUS_SUCCESS;
417 }
418 }
419
420 return CAIRO_INT_STATUS_UNSUPPORTED;
421 }
422