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.
21 /* JBIG2 Pattern Dictionary and Halftone Region decoding */
28 #include <string.h> /* memset() */
31 #include "jbig2_priv.h"
32 #include "jbig2_arith.h"
33 #include "jbig2_generic.h"
34 #include "jbig2_mmr.h"
35 #include "jbig2_image.h"
36 #include "jbig2_halftone.h"
39 * jbig2_hd_new: create a new dictionary from a collective bitmap
42 jbig2_hd_new(Jbig2Ctx *ctx,
43 const Jbig2PatternDictParams *params,
46 Jbig2PatternDict *new;
47 const int N = params->GRAYMAX + 1;
48 const int HPW = params->HDPW;
49 const int HPH = params->HDPH;
52 /* allocate a new struct */
53 new = jbig2_new(ctx, Jbig2PatternDict, 1);
55 new->patterns = jbig2_new(ctx, Jbig2Image*, N);
56 if (new->patterns == NULL) {
57 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
58 "failed to allocate pattern in collective bitmap dictionary");
59 jbig2_free(ctx->allocator, new);
66 /* 6.7.5(4) - copy out the individual pattern images */
67 for (i = 0; i < N; i++) {
68 new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);
69 if (new->patterns[i] == NULL) {
71 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
72 "failed to allocate pattern element image");
73 for (j = 0; j < i; j++)
74 jbig2_free(ctx->allocator, new->patterns[j]);
75 jbig2_free(ctx->allocator, new);
78 /* compose with the REPLACE operator; the source
79 will be clipped to the destintion, selecting the
81 jbig2_image_compose(ctx, new->patterns[i], image,
82 -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
87 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
88 "failed to allocate collective bitmap dictionary");
95 * jbig2_hd_release: release a pattern dictionary
98 jbig2_hd_release(Jbig2Ctx *ctx, Jbig2PatternDict *dict)
102 if (dict == NULL) return;
103 for (i = 0; i < dict->n_patterns; i++)
104 if (dict->patterns[i]) jbig2_image_release(ctx, dict->patterns[i]);
105 jbig2_free(ctx->allocator, dict->patterns);
106 jbig2_free(ctx->allocator, dict);
110 * jbig2_decode_pattern_dict: decode pattern dictionary data
112 * @ctx: jbig2 decoder context
113 * @segment: jbig2 segment (header) structure
114 * @params: parameters from the pattern dictionary header
115 * @data: pointer to text region data to be decoded
116 * @size: length of text region data
117 * @GB_stats: artimetic coding context to use
119 * Implements the patten dictionary decoding proceedure
120 * described in section 6.7 of the JBIG2 spec.
122 * returns: a pointer to the resulting dictionary on success
123 * returns: 0 on failure
125 static Jbig2PatternDict *
126 jbig2_decode_pattern_dict(Jbig2Ctx *ctx, Jbig2Segment *segment,
127 const Jbig2PatternDictParams *params,
128 const byte *data, const size_t size,
129 Jbig2ArithCx *GB_stats)
131 Jbig2PatternDict *hd = NULL;
132 Jbig2Image *image = NULL;
133 Jbig2GenericRegionParams rparams;
136 /* allocate the collective image */
137 image = jbig2_image_new(ctx,
138 params->HDPW * (params->GRAYMAX + 1), params->HDPH);
140 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
141 "failed to allocate collective bitmap for halftone dict!");
145 /* fill out the generic region decoder parameters */
146 rparams.MMR = params->HDMMR;
147 rparams.GBTEMPLATE = params->HDTEMPLATE;
148 rparams.TPGDON = 0; /* not used if HDMMR = 1 */
150 rparams.gbat[0] = -(int8_t)params->HDPW;
152 rparams.gbat[2] = -3;
153 rparams.gbat[3] = -1;
155 rparams.gbat[5] = -2;
156 rparams.gbat[6] = -2;
157 rparams.gbat[7] = -2;
160 code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data, size, image);
162 Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size);
165 Jbig2ArithState *as = jbig2_arith_new(ctx, ws);
168 code = jbig2_decode_generic_region(ctx, segment, &rparams,
169 as, image, GB_stats);
173 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
174 "failed to allocate storage for as in halftone dict!");
177 jbig2_free(ctx->allocator, as);
178 jbig2_word_stream_buf_free(ctx, ws);
182 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
183 "failed to allocate storage for ws in halftone dict!");
187 if (code == 0) hd = jbig2_hd_new(ctx, params, image);
188 jbig2_image_release(ctx, image);
195 jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment,
196 const byte *segment_data)
198 Jbig2PatternDictParams params;
199 Jbig2ArithCx *GB_stats = NULL;
203 /* 7.4.4.1 - Data header */
204 if (segment->data_length < 7) {
205 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
206 "Segment too short");
208 flags = segment_data[0];
209 params.HDMMR = flags & 1;
210 params.HDTEMPLATE = (flags & 6) >> 1;
211 params.HDPW = segment_data[1];
212 params.HDPH = segment_data[2];
213 params.GRAYMAX = jbig2_get_uint32(segment_data + 3);
216 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
217 "pattern dictionary, flags=%02x, %d grays (%dx%d cell)",
218 flags, params.GRAYMAX + 1, params.HDPW, params.HDPH);
220 if (params.HDMMR && params.HDTEMPLATE) {
221 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
222 "HDTEMPLATE is %d when HDMMR is %d, contrary to spec",
223 params.HDTEMPLATE, params.HDMMR);
226 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
227 "Reserved flag bits non-zero");
232 /* allocate and zero arithmetic coding stats */
233 int stats_size = jbig2_generic_stats_size(ctx, params.HDTEMPLATE);
234 GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
235 if (GB_stats == NULL)
237 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
238 "failed to allocate GB_stats in pattern dictionary");
241 memset(GB_stats, 0, stats_size);
244 segment->result = jbig2_decode_pattern_dict(ctx, segment, ¶ms,
245 segment_data + offset,
246 segment->data_length - offset, GB_stats);
248 /* todo: retain GB_stats? */
250 jbig2_free(ctx->allocator, GB_stats);
253 return (segment->result != NULL) ? 0 : -1;
257 * jbig2_decode_gray_scale_image: decode gray-scale image
259 * @ctx: jbig2 decoder context
260 * @segment: jbig2 segment (header) structure
261 * @data: pointer to text region data to be decoded
262 * @size: length of text region data
263 * @GSMMR: if MMR is used
264 * @GSW: width of gray-scale image
265 * @GSH: height of gray-scale image
266 * @GSBPP: number of bitplanes/Jbig2Images to use
267 * @GSKIP: mask indicating which values should be skipped
268 * @GSTEMPLATE: template used to code the gray-scale bitplanes
269 * @GB_stats: artimetic coding context to use
271 * Implements the decoding a gray-scale image described in
272 * annex C.5. This is part of the halftone region decoding.
274 * returns: array of gray-scale values with GSW x GSH width/height
278 jbig2_decode_gray_scale_image(Jbig2Ctx *ctx, Jbig2Segment* segment,
279 const byte *data, const size_t size,
280 bool GSMMR, uint32_t GSW, uint32_t GSH,
281 uint32_t GSBPP, bool GSUSESKIP,
282 Jbig2Image *GSKIP, int GSTEMPLATE,
283 Jbig2ArithCx *GB_stats)
285 uint8_t **GSVALS = NULL;
286 size_t consumed_bytes = 0;
287 int i, j, code, stride;
289 Jbig2Image **GSPLANES;
290 Jbig2GenericRegionParams rparams;
291 Jbig2WordStream *ws = NULL;
292 Jbig2ArithState *as = NULL;
294 /* allocate GSPLANES */
295 GSPLANES = jbig2_new(ctx, Jbig2Image*, GSBPP);
296 if (GSPLANES == NULL) {
297 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
298 "failed to allocate %d bytes for GSPLANES", GSBPP);
302 for (i = 0; i < GSBPP; ++i) {
303 GSPLANES[i] = jbig2_image_new(ctx, GSW, GSH);
304 if (GSPLANES[i] == NULL) {
305 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
306 "failed to allocate %dx%d image for GSPLANES", GSW, GSH);
307 /* free already allocated */
308 for (j = i-1; j >= 0; --j) {
309 jbig2_image_release(ctx, GSPLANES[j]);
311 jbig2_free(ctx->allocator, GSPLANES);
316 /* C.5 step 1. Decode GSPLANES[GSBPP-1] */
317 /* fill generic region decoder parameters */
319 rparams.GBTEMPLATE = GSTEMPLATE;
321 rparams.USESKIP = GSUSESKIP;
322 rparams.gbat[0] = (GSTEMPLATE <= 1? 3 : 2);
323 rparams.gbat[1] = -1;
324 rparams.gbat[2] = -3;
325 rparams.gbat[3] = -1;
327 rparams.gbat[5] = -2;
328 rparams.gbat[6] = -2;
329 rparams.gbat[7] = -2;
332 code = jbig2_decode_halftone_mmr(ctx, &rparams, data, size,
333 GSPLANES[GSBPP-1], &consumed_bytes);
335 ws = jbig2_word_stream_buf_new(ctx, data, size);
338 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
339 "failed to allocate ws in jbig2_decode_gray_scale_image");
343 as = jbig2_arith_new(ctx, ws);
346 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
347 "failed to allocate as in jbig2_decode_gray_scale_image");
351 code = jbig2_decode_generic_region(ctx, segment, &rparams, as,
352 GSPLANES[GSBPP-1], GB_stats);
356 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
357 "error decoding GSPLANES for halftone image");
361 /* C.5 step 2. Set j = GSBPP-2 */
363 /* C.5 step 3. decode loop */
365 /* C.5 step 3. (a) */
367 code = jbig2_decode_halftone_mmr(ctx, &rparams, data + consumed_bytes,
368 size - consumed_bytes, GSPLANES[j],
371 code = jbig2_decode_generic_region(ctx, segment, &rparams, as,
372 GSPLANES[j], GB_stats);
375 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
376 "error decoding GSPLANES for halftone image");
382 * GSPLANES[j][x][y] = GSPLANES[j+1][x][y] XOR GSPLANES[j][x][y] */
383 stride = GSPLANES[0]->stride;
384 for (i=0; i < stride * GSH; ++i)
385 GSPLANES[j]->data[i] ^= GSPLANES[j+1]->data[i];
387 /* C.5 step 3. (c) */
391 /* allocate GSVALS */
392 GSVALS = jbig2_new(ctx, uint8_t* , GSW);
393 if (GSVALS == NULL) {
394 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
395 "failed to allocate GSVALS: %d bytes", GSW);
398 for (i=0; i<GSW; ++i) {
399 GSVALS[i] = jbig2_new(ctx, uint8_t , GSH);
400 if (GSVALS[i] == NULL) {
401 jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
402 "failed to allocate GSVALS: %d bytes", GSH * GSW);
403 /* free already allocated */
404 for (j = i-1; j >= 0; --j) {
405 jbig2_free(ctx->allocator, GSVALS[j]);
407 jbig2_free(ctx->allocator, GSVALS);
414 for (x = 0; x < GSW; ++x) {
415 for (y = 0; y < GSH; ++y) {
418 for (j = 0; j < GSBPP; ++j)
419 GSVALS[x][y] += jbig2_image_get_pixel(GSPLANES[j], x, y) << j;
426 jbig2_free(ctx->allocator, as);
427 jbig2_word_stream_buf_free(ctx, ws);
429 for (i=0; i< GSBPP; ++i)
430 jbig2_image_release(ctx, GSPLANES[i]);
432 jbig2_free(ctx->allocator, GSPLANES);
438 * jbig2_decode_ht_region_get_hpats: get pattern dictionary
440 * @ctx: jbig2 decoder context
441 * @segment: jbig2 halftone region segment
443 * Returns the first referred pattern dictionary of segment
445 * returns: pattern dictionary
449 jbig2_decode_ht_region_get_hpats(Jbig2Ctx *ctx, Jbig2Segment *segment)
452 Jbig2PatternDict *pattern_dict = NULL;
453 Jbig2Segment *rsegment = NULL;
455 /* loop through all referred segments */
456 while (!pattern_dict && segment->referred_to_segment_count > index) {
457 rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
459 /* segment type is pattern dictionary and result is not empty */
460 if ((rsegment->flags & 0x3f) == 16 && rsegment->result) {
461 pattern_dict = (Jbig2PatternDict *) rsegment->result;
471 * jbig2_decode_halftone_region: decode a halftone region
473 * @ctx: jbig2 decoder context
474 * @segment: jbig2 halftone region segment
475 * @params: parameters
476 * @data: pointer to halftone region data to be decoded
477 * @size: length of halftone region data
478 * @GB_stats: artimetic coding context to use
480 * Implements the halftone region decoding proceedure
481 * described in section 6.6.5 of the JBIG2 spec.
483 * returns: 0 on success
487 jbig2_decode_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
488 Jbig2HalftoneRegionParams *params,
489 const byte *data, const size_t size,
491 Jbig2ArithCx *GB_stats)
496 Jbig2Image *HSKIP = NULL;
497 Jbig2PatternDict * HPATS;
503 /* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */
504 memset(image->data, params->HDEFPIXEL, image->stride * image->height);
506 /* 6.6.5 point 2. compute HSKIP */
507 if (params->HENABLESKIP == 1) {
508 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
509 "unhandled option HENABLESKIP");
512 /* 6.6.5 point 3. set HBPP to ceil(log2(HNUMPATS)):
513 * we need the number of patterns used in this region (HNUMPATS)
514 * get it from referred pattern dictionary */
516 HPATS = jbig2_decode_ht_region_get_hpats(ctx, segment);
518 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
519 "no pattern dictionary found, skipping halftone image");
522 HNUMPATS = HPATS->n_patterns;
524 /* calculate ceil(log2(HNUMPATS)) */
526 while(HNUMPATS > (1 << ++HBPP));
528 /* 6.6.5 point 4. decode gray-scale image as mentioned in annex C */
529 GI = jbig2_decode_gray_scale_image(ctx, segment, data, size,
530 params->HMMR, params->HGW,
531 params->HGH, HBPP, params->HENABLESKIP,
532 HSKIP, params->HTEMPLATE,
536 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
537 "unable to acquire gray-scale image, skipping halftone image");
541 /* 6.6.5 point 5. place patterns with procedure mentioned in 6.6.5.2 */
542 for (mg = 0 ; mg < params->HGH ; ++mg) {
543 for (ng = 0 ; ng < params->HGW ; ++ng ) {
544 x = (params->HGX + mg * params->HRY + ng * params->HRX) >> 8;
545 y = (params->HGY + mg * params->HRX - ng * params->HRY) >> 8;
547 /* prevent pattern index >= HNUMPATS */
548 gray_val = GI[ng][mg];
549 if (gray_val >= HNUMPATS) {
550 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
551 "gray-scale image uses value %d which larger than pattern dictionary",
553 /* use highest aviable pattern */
554 gray_val = HNUMPATS - 1;
556 jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
561 for (i = 0; i < params->HGW; ++i) {
562 jbig2_free(ctx->allocator, GI[i]);
564 jbig2_free(ctx->allocator, GI);
570 * jbig2_halftone_region: read a halftone region segment header
573 jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
576 Jbig2RegionSegmentInfo region_info;
577 Jbig2HalftoneRegionParams params;
578 Jbig2Image *image = NULL;
579 Jbig2ArithCx *GB_stats = NULL;
583 if (segment->data_length < 17) goto too_short;
584 jbig2_get_region_segment_info(®ion_info, segment_data);
587 if (segment->data_length < 18) goto too_short;
590 params.flags = segment_data[offset];
591 params.HMMR = params.flags & 1;
592 params.HTEMPLATE = (params.flags & 6) >> 1;
593 params.HENABLESKIP = (params.flags & 8) >> 3;
594 params.op = (Jbig2ComposeOp)((params.flags & 0x70) >> 4);
595 params.HDEFPIXEL = (params.flags &0x80) >> 7;
598 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
599 "halftone region: %d x %d @ (%x,%d) flags=%02x",
600 region_info.width, region_info.height,
601 region_info.x, region_info.y, params.flags);
603 if (params.HMMR && params.HTEMPLATE) {
604 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
605 "HTEMPLATE is %d when HMMR is %d, contrary to spec",
606 params.HTEMPLATE, params.HMMR);
608 if (params.HMMR && params.HENABLESKIP) {
609 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
610 "HENABLESKIP is %d when HMMR is %d, contrary to spec",
611 params.HENABLESKIP, params.HMMR);
615 if (segment->data_length - offset < 16) goto too_short;
616 params.HGW = jbig2_get_uint32(segment_data + offset);
617 params.HGH = jbig2_get_uint32(segment_data + offset + 4);
618 params.HGX = jbig2_get_int32(segment_data + offset + 8);
619 params.HGY = jbig2_get_int32(segment_data + offset + 12);
623 if (segment->data_length - offset < 4) goto too_short;
624 params.HRX = jbig2_get_uint16(segment_data + offset);
625 params.HRY = jbig2_get_uint16(segment_data + offset + 2);
628 jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
629 " grid %d x %d @ (%d.%d,%d.%d) vector (%d.%d,%d.%d)",
630 params.HGW, params.HGH,
631 params.HGX >> 8, params.HGX & 0xff,
632 params.HGY >> 8, params.HGY & 0xff,
633 params.HRX >> 8, params.HRX & 0xff,
634 params.HRY >> 8, params.HRY & 0xff);
638 /* allocate and zero arithmetic coding stats */
639 int stats_size = jbig2_generic_stats_size(ctx, params.HTEMPLATE);
640 GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
641 if (GB_stats == NULL)
643 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
644 "failed to allocate GB_stats in halftone region");
646 memset(GB_stats, 0, stats_size);
649 image = jbig2_image_new(ctx, region_info.width, region_info.height);
652 jbig2_free(ctx->allocator, GB_stats);
653 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
654 "unable to allocate halftone image");
657 code = jbig2_decode_halftone_region(ctx, segment, ¶ms,
658 segment_data + offset, segment->data_length - offset,
661 /* todo: retain GB_stats? */
663 jbig2_free(ctx->allocator, GB_stats);
666 jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
667 image, region_info.x, region_info.y, region_info.op);
668 jbig2_image_release(ctx, image);
673 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
674 "Segment too short");