beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-image-info.c
blob26e7ae5afd110889e2898e27710031c699ca1264
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
4 * Copyright © 2008 Adrian Johnson
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.
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
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/
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.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Adrian Johnson.
33 * Contributor(s):
34 * Adrian Johnson <ajohnson@redneon.com>
37 #include "cairoint.h"
39 #include "cairo-error-private.h"
40 #include "cairo-image-info-private.h"
42 /* JPEG (image/jpeg)
44 * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
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
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
70 static const unsigned char *
71 _jpeg_skip_segment (const unsigned char *p)
73 int len;
75 p++;
76 len = (p[0] << 8) | p[1];
78 return p + len;
81 static void
82 _jpeg_extract_info (cairo_image_info_t *info, const unsigned char *p)
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];
90 cairo_int_status_t
91 _cairo_image_info_get_jpeg_info (cairo_image_info_t *info,
92 const unsigned char *data,
93 long length)
95 const unsigned char *p = data;
97 while (p + 1 < data + length) {
98 if (*p != 0xff)
99 return CAIRO_INT_STATUS_UNSUPPORTED;
100 p++;
102 switch (*p) {
103 /* skip fill bytes */
104 case 0xff:
105 p++;
106 break;
108 case TEM:
109 case SOI:
110 case EOI:
111 p++;
112 break;
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;
131 _jpeg_extract_info (info, p);
132 return CAIRO_STATUS_SUCCESS;
134 default:
135 if (*p >= RST_begin && *p <= RST_end) {
136 p++;
137 break;
140 if (p + 2 > data + length)
141 return CAIRO_INT_STATUS_UNSUPPORTED;
143 p = _jpeg_skip_segment (p);
144 break;
148 return CAIRO_STATUS_SUCCESS;
151 /* JPEG 2000 (image/jp2)
153 * http://www.jpeg.org/public/15444-1annexi.pdf
156 #define JPX_FILETYPE 0x66747970
157 #define JPX_JP2_HEADER 0x6A703268
158 #define JPX_IMAGE_HEADER 0x69686472
160 static const unsigned char _jpx_signature[] = {
161 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a
164 static const unsigned char *
165 _jpx_next_box (const unsigned char *p)
167 return p + get_unaligned_be32 (p);
170 static const unsigned char *
171 _jpx_get_box_contents (const unsigned char *p)
173 return p + 8;
176 static cairo_bool_t
177 _jpx_match_box (const unsigned char *p, const unsigned char *end, uint32_t type)
179 uint32_t length;
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;
187 return FALSE;
190 static const unsigned char *
191 _jpx_find_box (const unsigned char *p, const unsigned char *end, uint32_t type)
193 while (p < end) {
194 if (_jpx_match_box (p, end, type))
195 return p;
196 p = _jpx_next_box (p);
199 return NULL;
202 static void
203 _jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
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];
211 cairo_int_status_t
212 _cairo_image_info_get_jpx_info (cairo_image_info_t *info,
213 const unsigned char *data,
214 unsigned long length)
216 const unsigned char *p = data;
217 const unsigned char *end = data + length;
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;
224 p += ARRAY_LENGTH(_jpx_signature);
226 /* Next box must be a File Type Box */
227 if (! _jpx_match_box (p, end, JPX_FILETYPE))
228 return CAIRO_INT_STATUS_UNSUPPORTED;
230 p = _jpx_next_box (p);
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;
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;
243 /* Get the image info */
244 p = _jpx_get_box_contents (p);
245 _jpx_extract_info (p, info);
247 return CAIRO_STATUS_SUCCESS;
250 /* PNG (image/png)
252 * http://www.w3.org/TR/2003/REC-PNG-20031110/
255 #define PNG_IHDR 0x49484452
257 static const unsigned char _png_magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
259 cairo_int_status_t
260 _cairo_image_info_get_png_info (cairo_image_info_t *info,
261 const unsigned char *data,
262 unsigned long length)
264 const unsigned char *p = data;
265 const unsigned char *end = data + length;
267 if (length < 8 || memcmp (data, _png_magic, 8) != 0)
268 return CAIRO_INT_STATUS_UNSUPPORTED;
270 p += 8;
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;
277 p += 4;
278 if (get_unaligned_be32 (p) != PNG_IHDR)
279 return CAIRO_INT_STATUS_UNSUPPORTED;
281 p += 4;
282 info->width = get_unaligned_be32 (p);
283 p += 4;
284 info->height = get_unaligned_be32 (p);
286 return CAIRO_STATUS_SUCCESS;
289 static const unsigned char *
290 _jbig2_find_data_end (const unsigned char *p,
291 const unsigned char *end,
292 int type)
294 unsigned char end_seq[2];
295 int mmr;
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;
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;
320 p++;
325 return NULL;
328 static const unsigned char *
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)
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;
341 if (p + 6 >= end)
342 return NULL;
344 seg_num = get_unaligned_be32 (p);
345 *type = p[4] & 0x3f;
346 big_page_size = (p[4] & 0x40) != 0;
347 p += 5;
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;
356 p += ref_seg_bytes;
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;
365 p += num_segs * referred_size;
366 p += big_page_size ? 4 : 1;
367 if (p + 4 >= end)
368 return NULL;
370 *data_len = get_unaligned_be32 (p);
371 p += 4;
372 *data = p;
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;
380 *data_len = p - *data;
381 } else {
382 p += *data_len;
385 if (p < end)
386 return p;
387 else
388 return NULL;
391 static void
392 _jbig2_extract_info (cairo_image_info_t *info, const unsigned char *p)
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;
400 cairo_int_status_t
401 _cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
402 const unsigned char *data,
403 unsigned long length)
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;
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;
420 return CAIRO_INT_STATUS_UNSUPPORTED;