1 | /* Copyright (C) 2001-2019 Artifex Software, Inc. |
2 | All Rights Reserved. |
3 | |
4 | This software is provided AS-IS with no warranty, either express or |
5 | implied. |
6 | |
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. |
10 | |
11 | Refer to licensing information at http://www.artifex.com or contact |
12 | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | */ |
15 | |
16 | /* |
17 | jbig2dec |
18 | */ |
19 | |
20 | #ifdef HAVE_CONFIG_H |
21 | #include "config.h" |
22 | #endif |
23 | #include "os_types.h" |
24 | |
25 | #include <stddef.h> /* size_t */ |
26 | |
27 | #include "jbig2.h" |
28 | #include "jbig2_priv.h" |
29 | #include "jbig2_arith.h" |
30 | #include "jbig2_arith_int.h" |
31 | #include "jbig2_arith_iaid.h" |
32 | #include "jbig2_generic.h" |
33 | #include "jbig2_image.h" |
34 | #include "jbig2_halftone.h" |
35 | #include "jbig2_huffman.h" |
36 | #include "jbig2_page.h" |
37 | #include "jbig2_refinement.h" |
38 | #include "jbig2_segment.h" |
39 | #include "jbig2_symbol_dict.h" |
40 | #include "jbig2_text.h" |
41 | |
42 | #if !defined (UINT32_MAX) |
43 | #define UINT32_MAX 0xffffffff |
44 | #endif |
45 | |
46 | Jbig2Segment * |
47 | (Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size, size_t *) |
48 | { |
49 | Jbig2Segment *result; |
50 | uint8_t rtscarf; |
51 | uint32_t rtscarf_long; |
52 | uint32_t *referred_to_segments; |
53 | uint32_t referred_to_segment_count; |
54 | uint32_t referred_to_segment_size; |
55 | uint32_t pa_size; |
56 | uint32_t offset; |
57 | |
58 | /* minimum possible size of a jbig2 segment header */ |
59 | if (buf_size < 11) |
60 | return NULL; |
61 | |
62 | result = jbig2_new(ctx, Jbig2Segment, 1); |
63 | if (result == NULL) { |
64 | jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate segment" ); |
65 | return NULL; |
66 | } |
67 | |
68 | /* 7.2.2 */ |
69 | result->number = jbig2_get_uint32(buf); |
70 | |
71 | /* 7.2.3 */ |
72 | result->flags = buf[4]; |
73 | |
74 | /* 7.2.4 referred-to segments */ |
75 | rtscarf = buf[5]; |
76 | if ((rtscarf & 0xe0) == 0xe0) { |
77 | rtscarf_long = jbig2_get_uint32(buf + 5); |
78 | referred_to_segment_count = rtscarf_long & 0x1fffffff; |
79 | offset = 5 + 4 + (referred_to_segment_count + 1) / 8; |
80 | } else { |
81 | referred_to_segment_count = (rtscarf >> 5); |
82 | offset = 5 + 1; |
83 | } |
84 | result->referred_to_segment_count = referred_to_segment_count; |
85 | |
86 | /* we now have enough information to compute the full header length */ |
87 | referred_to_segment_size = result->number <= 256 ? 1 : result->number <= 65536 ? 2 : 4; /* 7.2.5 */ |
88 | pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */ |
89 | if (offset + referred_to_segment_count * referred_to_segment_size + pa_size + 4 > buf_size) { |
90 | jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "insufficient data to parse segment header" , -1); |
91 | jbig2_free(ctx->allocator, result); |
92 | return NULL; |
93 | } |
94 | |
95 | /* 7.2.5 */ |
96 | if (referred_to_segment_count) { |
97 | uint32_t i; |
98 | |
99 | referred_to_segments = jbig2_new(ctx, uint32_t, referred_to_segment_count * referred_to_segment_size); |
100 | if (referred_to_segments == NULL) { |
101 | jbig2_error(ctx, JBIG2_SEVERITY_FATAL, result->number, "failed to allocate referred to segments" ); |
102 | return NULL; |
103 | } |
104 | |
105 | for (i = 0; i < referred_to_segment_count; i++) { |
106 | referred_to_segments[i] = |
107 | (referred_to_segment_size == 1) ? buf[offset] : |
108 | (referred_to_segment_size == 2) ? jbig2_get_uint16(buf + offset) : jbig2_get_uint32(buf + offset); |
109 | offset += referred_to_segment_size; |
110 | jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "segment %d refers to segment %d" , result->number, referred_to_segments[i]); |
111 | } |
112 | result->referred_to_segments = referred_to_segments; |
113 | } else { /* no referred-to segments */ |
114 | |
115 | result->referred_to_segments = NULL; |
116 | } |
117 | |
118 | /* 7.2.6 */ |
119 | if (pa_size == 4) { |
120 | result->page_association = jbig2_get_uint32(buf + offset); |
121 | offset += 4; |
122 | } else { |
123 | result->page_association = buf[offset++]; |
124 | } |
125 | jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number, "segment %d is associated with page %d" , result->number, result->page_association); |
126 | |
127 | /* 7.2.7 */ |
128 | result->rows = UINT32_MAX; |
129 | result->data_length = jbig2_get_uint32(buf + offset); |
130 | *p_header_size = offset + 4; |
131 | |
132 | /* no body parsing results yet */ |
133 | result->result = NULL; |
134 | |
135 | return result; |
136 | } |
137 | |
138 | void |
139 | jbig2_free_segment(Jbig2Ctx *ctx, Jbig2Segment *segment) |
140 | { |
141 | if (segment == NULL) |
142 | return; |
143 | |
144 | jbig2_free(ctx->allocator, segment->referred_to_segments); |
145 | /* todo: we need either some separate fields or |
146 | a more complex result object rather than this |
147 | brittle special casing */ |
148 | switch (segment->flags & 63) { |
149 | case 0: /* symbol dictionary */ |
150 | if (segment->result != NULL) |
151 | jbig2_sd_release(ctx, (Jbig2SymbolDict *) segment->result); |
152 | break; |
153 | case 4: /* intermediate text region */ |
154 | case 40: /* intermediate refinement region */ |
155 | if (segment->result != NULL) |
156 | jbig2_image_release(ctx, (Jbig2Image *) segment->result); |
157 | break; |
158 | case 16: /* pattern dictionary */ |
159 | if (segment->result != NULL) |
160 | jbig2_hd_release(ctx, (Jbig2PatternDict *) segment->result); |
161 | break; |
162 | case 53: /* user-supplied huffman table */ |
163 | if (segment->result != NULL) |
164 | jbig2_table_free(ctx, (Jbig2HuffmanParams *) segment->result); |
165 | break; |
166 | default: |
167 | /* anything else is probably an undefined pointer */ |
168 | break; |
169 | } |
170 | jbig2_free(ctx->allocator, segment); |
171 | } |
172 | |
173 | /* find a segment by number */ |
174 | Jbig2Segment * |
175 | jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number) |
176 | { |
177 | int index, index_max = ctx->segment_index - 1; |
178 | const Jbig2Ctx *global_ctx = ctx->global_ctx; |
179 | |
180 | /* FIXME: binary search would be better */ |
181 | for (index = index_max; index >= 0; index--) |
182 | if (ctx->segments[index]->number == number) |
183 | return (ctx->segments[index]); |
184 | |
185 | if (global_ctx) |
186 | for (index = global_ctx->segment_index - 1; index >= 0; index--) |
187 | if (global_ctx->segments[index]->number == number) |
188 | return (global_ctx->segments[index]); |
189 | |
190 | /* didn't find a match */ |
191 | return NULL; |
192 | } |
193 | |
194 | /* parse the generic portion of a region segment data header */ |
195 | void |
196 | jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info, const uint8_t *segment_data) |
197 | { |
198 | /* 7.4.1 */ |
199 | info->width = jbig2_get_uint32(segment_data); |
200 | info->height = jbig2_get_uint32(segment_data + 4); |
201 | info->x = jbig2_get_uint32(segment_data + 8); |
202 | info->y = jbig2_get_uint32(segment_data + 12); |
203 | info->flags = segment_data[16]; |
204 | info->op = (Jbig2ComposeOp)(info->flags & 0x7); |
205 | } |
206 | |
207 | /* dispatch code for extension segment parsing */ |
208 | static int |
209 | jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
210 | { |
211 | uint32_t type; |
212 | bool reserved; |
213 | bool necessary; |
214 | |
215 | if (segment->data_length < 4) |
216 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short" ); |
217 | |
218 | type = jbig2_get_uint32(segment_data); |
219 | reserved = type & 0x20000000; |
220 | /* Not implemented since this bit |
221 | is only needed by encoders. |
222 | dependent = type & 0x40000000; |
223 | */ |
224 | necessary = type & 0x80000000; |
225 | |
226 | if (necessary && !reserved) { |
227 | jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "extension segment is marked 'necessary' but not 'reserved' contrary to spec" ); |
228 | } |
229 | |
230 | switch (type) { |
231 | case 0x20000000: |
232 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ignoring ASCII comment" ); |
233 | break; |
234 | case 0x20000002: |
235 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "ignoring UCS-2 comment" ); |
236 | break; |
237 | default: |
238 | if (necessary) { |
239 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unhandled necessary extension segment type 0x%08x" , type); |
240 | } else { |
241 | jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unhandled non-necessary extension segment, skipping" ); |
242 | } |
243 | } |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | /* dispatch code for profile segment parsing */ |
249 | static int |
250 | jbig2_parse_profile_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
251 | { |
252 | uint32_t profiles; |
253 | uint32_t i; |
254 | uint32_t profile; |
255 | int index; |
256 | const char *requirements; |
257 | const char *generic_region; |
258 | const char *refinement_region; |
259 | const char *halftone_region; |
260 | const char *numerical_data; |
261 | |
262 | if (segment->data_length < 4) |
263 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Segment too short" ); |
264 | index = 0; |
265 | |
266 | profiles = jbig2_get_uint32(&segment_data[index]); |
267 | index += 4; |
268 | |
269 | for (i = 0; i < profiles; i++) { |
270 | if (segment->data_length - index < 4) |
271 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short to store profile" ); |
272 | |
273 | profile = jbig2_get_uint32(&segment_data[index]); |
274 | index += 4; |
275 | |
276 | switch (profile) { |
277 | case 0x00000001: |
278 | requirements = "All JBIG2 capabilities" ; |
279 | generic_region = "No restriction" ; |
280 | refinement_region = "No restriction" ; |
281 | halftone_region = "No restriction" ; |
282 | numerical_data = "No restriction" ; |
283 | break; |
284 | case 0x00000002: |
285 | requirements = "Maximum compression" ; |
286 | generic_region = "Arithmetic only; any template used" ; |
287 | refinement_region = "No restriction" ; |
288 | halftone_region = "No restriction" ; |
289 | numerical_data = "Arithmetic only" ; |
290 | break; |
291 | case 0x00000003: |
292 | requirements = "Medium complexity and medium compression" ; |
293 | generic_region = "Arithmetic only; only 10-pixel and 13-pixel templates" ; |
294 | refinement_region = "10-pixel template only" ; |
295 | halftone_region = "No skip mask used" ; |
296 | numerical_data = "Arithmetic only" ; |
297 | break; |
298 | case 0x00000004: |
299 | requirements = "Low complexity with progressive lossless capability" ; |
300 | generic_region = "MMR only" ; |
301 | refinement_region = "10-pixel template only" ; |
302 | halftone_region = "No skip mask used" ; |
303 | numerical_data = "Huffman only" ; |
304 | break; |
305 | case 0x00000005: |
306 | requirements = "Low complexity" ; |
307 | generic_region = "MMR only" ; |
308 | refinement_region = "Not available" ; |
309 | halftone_region = "No skip mask used" ; |
310 | numerical_data = "Huffman only" ; |
311 | break; |
312 | default: |
313 | requirements = "Unknown" ; |
314 | generic_region = "Unknown" ; |
315 | refinement_region = "Unknown" ; |
316 | halftone_region = "Unknown" ; |
317 | numerical_data = "Unknown" ; |
318 | break; |
319 | } |
320 | |
321 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "Supported profile: 0x%08x" , profile); |
322 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Requirements: %s" , requirements); |
323 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Generic region coding: %s" , generic_region); |
324 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Refinement region coding: %s" , refinement_region); |
325 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Halftone region coding: %s" , halftone_region); |
326 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, " Numerical data: %s" , numerical_data); |
327 | } |
328 | |
329 | return 0; |
330 | } |
331 | |
332 | /* general segment parsing dispatch */ |
333 | int |
334 | jbig2_parse_segment(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data) |
335 | { |
336 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, |
337 | "segment %d, flags=%x, type=%d, data_length=%d" , segment->number, segment->flags, segment->flags & 63, segment->data_length); |
338 | switch (segment->flags & 63) { |
339 | case 0: |
340 | return jbig2_symbol_dictionary(ctx, segment, segment_data); |
341 | case 4: /* intermediate text region */ |
342 | case 6: /* immediate text region */ |
343 | case 7: /* immediate lossless text region */ |
344 | return jbig2_text_region(ctx, segment, segment_data); |
345 | case 16: |
346 | return jbig2_pattern_dictionary(ctx, segment, segment_data); |
347 | case 20: /* intermediate halftone region */ |
348 | case 22: /* immediate halftone region */ |
349 | case 23: /* immediate lossless halftone region */ |
350 | return jbig2_halftone_region(ctx, segment, segment_data); |
351 | case 36: |
352 | return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unhandled segment type 'intermediate generic region' (NYI)" ); |
353 | case 38: /* immediate generic region */ |
354 | case 39: /* immediate lossless generic region */ |
355 | return jbig2_immediate_generic_region(ctx, segment, segment_data); |
356 | case 40: /* intermediate generic refinement region */ |
357 | case 42: /* immediate generic refinement region */ |
358 | case 43: /* immediate lossless generic refinement region */ |
359 | return jbig2_refinement_region(ctx, segment, segment_data); |
360 | case 48: |
361 | return jbig2_page_info(ctx, segment, segment_data); |
362 | case 49: |
363 | return jbig2_end_of_page(ctx, segment, segment_data); |
364 | case 50: |
365 | return jbig2_end_of_stripe(ctx, segment, segment_data); |
366 | case 51: |
367 | ctx->state = JBIG2_FILE_EOF; |
368 | jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of file" ); |
369 | break; |
370 | case 52: |
371 | return jbig2_parse_profile_segment(ctx, segment, segment_data); |
372 | case 53: /* user-supplied huffman table */ |
373 | return jbig2_table(ctx, segment, segment_data); |
374 | case 54: |
375 | return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unhandled segment type 'color palette' (NYI)" ); |
376 | case 62: |
377 | return jbig2_parse_extension_segment(ctx, segment, segment_data); |
378 | default: |
379 | jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unknown segment type %d" , segment->flags & 63); |
380 | } |
381 | return 0; |
382 | } |
383 | |