1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
4 This software is provided AS-IS with no warranty, either express or
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
26 #include <stddef.h> /* size_t */
29 #include "jbig2_priv.h"
30 #include "jbig2_huffman.h"
31 #include "jbig2_symbol_dict.h"
32 #include "jbig2_metadata.h"
33 #include "jbig2_arith.h"
34 #include "jbig2_halftone.h"
37 jbig2_parse_segment_header (Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size,
38 size_t *p_header_size)
42 uint32_t rtscarf_long;
43 uint32_t *referred_to_segments;
44 int referred_to_segment_count;
45 int referred_to_segment_size;
49 /* minimum possible size of a jbig2 segment header */
53 result = jbig2_new(ctx, Jbig2Segment, 1);
56 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
57 "failed to allocate segment in jbig2_parse_segment_header");
62 result->number = jbig2_get_uint32(buf);
65 result->flags = buf[4];
67 /* 7.2.4 referred-to segments */
69 if ((rtscarf & 0xe0) == 0xe0)
71 rtscarf_long = jbig2_get_uint32(buf + 5);
72 referred_to_segment_count = rtscarf_long & 0x1fffffff;
73 offset = 5 + 4 + (referred_to_segment_count + 1) / 8;
77 referred_to_segment_count = (rtscarf >> 5);
80 result->referred_to_segment_count = referred_to_segment_count;
82 /* we now have enough information to compute the full header length */
83 referred_to_segment_size = result->number <= 256 ? 1:
84 result->number <= 65536 ? 2 : 4; /* 7.2.5 */
85 pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */
86 if (offset + referred_to_segment_count*referred_to_segment_size + pa_size + 4 > buf_size)
88 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
89 "jbig2_parse_segment_header() called with insufficient data", -1);
90 jbig2_free (ctx->allocator, result);
95 if (referred_to_segment_count)
99 referred_to_segments = jbig2_new(ctx, uint32_t,
100 referred_to_segment_count * referred_to_segment_size);
101 if (referred_to_segments == NULL)
103 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
104 "could not allocate referred_to_segments "
105 "in jbig2_parse_segment_header");
109 for (i = 0; i < referred_to_segment_count; i++) {
110 referred_to_segments[i] =
111 (referred_to_segment_size == 1) ? buf[offset] :
112 (referred_to_segment_size == 2) ? jbig2_get_uint16(buf+offset) :
113 jbig2_get_uint32(buf + offset);
114 offset += referred_to_segment_size;
115 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
116 "segment %d refers to segment %d",
117 result->number, referred_to_segments[i]);
119 result->referred_to_segments = referred_to_segments;
121 else /* no referred-to segments */
123 result->referred_to_segments = NULL;
127 if (result->flags & 0x40) {
128 result->page_association = jbig2_get_uint32(buf + offset);
131 result->page_association = buf[offset++];
133 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
134 "segment %d is associated with page %d",
135 result->number, result->page_association);
138 result->data_length = jbig2_get_uint32(buf + offset);
139 *p_header_size = offset + 4;
141 /* no body parsing results yet */
142 result->result = NULL;
148 jbig2_free_segment (Jbig2Ctx *ctx, Jbig2Segment *segment)
150 if (segment->referred_to_segments != NULL) {
151 jbig2_free(ctx->allocator, segment->referred_to_segments);
153 /* todo: we need either some separate fields or
154 a more complex result object rather than this
155 brittle special casing */
156 switch (segment->flags & 63) {
157 case 0: /* symbol dictionary */
158 if (segment->result != NULL)
159 jbig2_sd_release(ctx, (Jbig2SymbolDict*)segment->result);
161 case 4: /* intermediate text region */
162 case 40: /* intermediate refinement region */
163 if (segment->result != NULL)
164 jbig2_image_release(ctx, (Jbig2Image*)segment->result);
166 case 16: /* pattern dictionary */
167 if (segment->result != NULL)
168 jbig2_hd_release(ctx, (Jbig2PatternDict*)segment->result);
170 case 53: /* user-supplied huffman table */
171 if (segment->result != NULL)
172 jbig2_table_free(ctx, (Jbig2HuffmanParams*)segment->result);
175 if (segment->result != NULL)
176 jbig2_metadata_free(ctx, (Jbig2Metadata*)segment->result);
179 /* anything else is probably an undefined pointer */
182 jbig2_free (ctx->allocator, segment);
185 /* find a segment by number */
187 jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number)
189 int index, index_max = ctx->segment_index - 1;
190 const Jbig2Ctx *global_ctx = ctx->global_ctx;
192 /* FIXME: binary search would be better */
193 for (index = index_max; index >= 0; index--)
194 if (ctx->segments[index]->number == number)
195 return (ctx->segments[index]);
198 for (index = global_ctx->segment_index - 1; index >= 0; index--)
199 if (global_ctx->segments[index]->number == number)
200 return (global_ctx->segments[index]);
202 /* didn't find a match */
206 /* parse the generic portion of a region segment data header */
208 jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info,
209 const uint8_t *segment_data)
212 info->width = jbig2_get_int32(segment_data);
213 info->height = jbig2_get_int32(segment_data + 4);
214 info->x = jbig2_get_int32(segment_data + 8);
215 info->y = jbig2_get_int32(segment_data + 12);
216 info->flags = segment_data[16];
217 info->op = (Jbig2ComposeOp)(info->flags & 0x7);
220 /* dispatch code for extension segment parsing */
221 int jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment,
222 const uint8_t *segment_data)
224 uint32_t type = jbig2_get_uint32(segment_data);
225 bool reserved = type & 0x20000000;
226 /* bool dependent = type & 0x40000000; (NYI) */
227 bool necessary = type & 0x80000000;
229 if (necessary && !reserved) {
230 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
231 "extension segment is marked 'necessary' but "
232 "not 'reservered' contrary to spec");
236 case 0x20000000: return jbig2_comment_ascii(ctx, segment, segment_data);
237 case 0x20000002: return jbig2_comment_unicode(ctx, segment, segment_data);
240 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
241 "unhandled necessary extension segment type 0x%08x", type);
243 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
244 "unhandled extension segment");
249 /* general segment parsing dispatch */
250 int jbig2_parse_segment (Jbig2Ctx *ctx, Jbig2Segment *segment,
251 const uint8_t *segment_data)
253 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
254 "Segment %d, flags=%x, type=%d, data_length=%d",
255 segment->number, segment->flags, segment->flags & 63,
256 segment->data_length);
257 switch (segment->flags & 63)
260 return jbig2_symbol_dictionary(ctx, segment, segment_data);
261 case 4: /* intermediate text region */
262 case 6: /* immediate text region */
263 case 7: /* immediate lossless text region */
264 return jbig2_text_region(ctx, segment, segment_data);
266 return jbig2_pattern_dictionary(ctx, segment, segment_data);
267 case 20: /* intermediate halftone region */
268 case 22: /* immediate halftone region */
269 case 23: /* immediate lossless halftone region */
270 return jbig2_halftone_region(ctx, segment, segment_data);
272 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
273 "unhandled segment type 'intermediate generic region'");
274 case 38: /* immediate generic region */
275 case 39: /* immediate lossless generic region */
276 return jbig2_immediate_generic_region(ctx, segment, segment_data);
277 case 40: /* intermediate generic refinement region */
278 case 42: /* immediate generic refinement region */
279 case 43: /* immediate lossless generic refinement region */
280 return jbig2_refinement_region(ctx, segment, segment_data);
282 return jbig2_page_info(ctx, segment, segment_data);
284 return jbig2_end_of_page(ctx, segment, segment_data);
286 return jbig2_end_of_stripe(ctx, segment, segment_data);
288 ctx->state = JBIG2_FILE_EOF;
289 return jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
292 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
293 "unhandled segment type 'profile'");
294 case 53: /* user-supplied huffman table */
295 return jbig2_table(ctx, segment, segment_data);
297 return jbig2_parse_extension_segment(ctx, segment, segment_data);
299 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
300 "unknown segment type %d", segment->flags & 63);