]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/jbig2dec/jbig2_halftone.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / jbig2dec / jbig2_halftone.c
1 /* Copyright (C) 2001-2012 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.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16 /*
17     jbig2dec
18 */
19
20
21 /* JBIG2 Pattern Dictionary and Halftone Region decoding */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "os_types.h"
27
28 #include <string.h> /* memset() */
29
30 #include "jbig2.h"
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"
37
38 /**
39  * jbig2_hd_new: create a new dictionary from a collective bitmap
40  */
41 Jbig2PatternDict *
42 jbig2_hd_new(Jbig2Ctx *ctx,
43                 const Jbig2PatternDictParams *params,
44                 Jbig2Image *image)
45 {
46   Jbig2PatternDict *new;
47   const int N = params->GRAYMAX + 1;
48   const int HPW = params->HDPW;
49   const int HPH = params->HDPH;
50   int i;
51
52   /* allocate a new struct */
53   new = jbig2_new(ctx, Jbig2PatternDict, 1);
54   if (new != NULL) {
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);
60       return NULL;
61     }
62     new->n_patterns = N;
63     new->HPW = HPW;
64     new->HPH = HPH;
65
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) {
70         int j;
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);
76         return NULL;
77       }
78       /* compose with the REPLACE operator; the source
79          will be clipped to the destintion, selecting the
80          proper sub image */
81       jbig2_image_compose(ctx, new->patterns[i], image,
82                           -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
83     }
84   }
85   else
86   {
87       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
88           "failed to allocate collective bitmap dictionary");
89   }
90
91   return new;
92 }
93
94 /**
95  * jbig2_hd_release: release a pattern dictionary
96  */
97 void
98 jbig2_hd_release(Jbig2Ctx *ctx, Jbig2PatternDict *dict)
99 {
100   int i;
101
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);
107 }
108
109 /**
110  * jbig2_decode_pattern_dict: decode pattern dictionary data
111  *
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
118  *
119  * Implements the patten dictionary decoding proceedure
120  * described in section 6.7 of the JBIG2 spec.
121  *
122  * returns: a pointer to the resulting dictionary on success
123  * returns: 0 on failure
124  **/
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)
130 {
131   Jbig2PatternDict *hd = NULL;
132   Jbig2Image *image = NULL;
133   Jbig2GenericRegionParams rparams;
134   int code = 0;
135
136   /* allocate the collective image */
137   image = jbig2_image_new(ctx,
138         params->HDPW * (params->GRAYMAX + 1), params->HDPH);
139   if (image == NULL) {
140     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
141         "failed to allocate collective bitmap for halftone dict!");
142     return NULL;
143   }
144
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 */
149   rparams.USESKIP = 0;
150   rparams.gbat[0] = -(int8_t)params->HDPW;
151   rparams.gbat[1] = 0;
152   rparams.gbat[2] = -3;
153   rparams.gbat[3] = -1;
154   rparams.gbat[4] = 2;
155   rparams.gbat[5] = -2;
156   rparams.gbat[6] = -2;
157   rparams.gbat[7] = -2;
158
159   if (params->HDMMR) {
160     code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data, size, image);
161   } else {
162     Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size);
163     if (ws != NULL)
164     {
165       Jbig2ArithState *as = jbig2_arith_new(ctx, ws);
166       if (as != NULL)
167       {
168         code = jbig2_decode_generic_region(ctx, segment, &rparams,
169             as, image, GB_stats);
170       }
171       else
172       {
173         code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
174             "failed to allocate storage for as in halftone dict!");
175       }
176
177       jbig2_free(ctx->allocator, as);
178       jbig2_word_stream_buf_free(ctx, ws);
179     }
180     else
181     {
182       code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
183           "failed to allocate storage for ws in halftone dict!");
184     }
185   }
186
187   if (code == 0) hd = jbig2_hd_new(ctx, params, image);
188   jbig2_image_release(ctx, image);
189
190   return hd;
191 }
192
193 /* 7.4.4 */
194 int
195 jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment,
196                          const byte *segment_data)
197 {
198   Jbig2PatternDictParams params;
199   Jbig2ArithCx *GB_stats = NULL;
200   byte flags;
201   int offset = 0;
202
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");
207   }
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);
214   offset += 7;
215
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);
219
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);
224   }
225   if (flags & 0xf8) {
226     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
227         "Reserved flag bits non-zero");
228   }
229
230   /* 7.4.4.2 */
231   if (!params.HDMMR) {
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)
236     {
237       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
238           "failed to allocate GB_stats in pattern dictionary");
239       return 0;
240     }
241     memset(GB_stats, 0, stats_size);
242   }
243
244   segment->result = jbig2_decode_pattern_dict(ctx, segment, &params,
245                         segment_data + offset,
246                         segment->data_length - offset, GB_stats);
247
248   /* todo: retain GB_stats? */
249   if (!params.HDMMR) {
250     jbig2_free(ctx->allocator, GB_stats);
251   }
252
253   return (segment->result != NULL) ? 0 : -1;
254 }
255
256 /**
257  * jbig2_decode_gray_scale_image: decode gray-scale image
258  *
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
270  *
271  * Implements the decoding a gray-scale image described in
272  * annex C.5. This is part of the halftone region decoding.
273  *
274  * returns: array of gray-scale values with GSW x GSH width/height
275  *          0 on failure
276  **/
277 uint8_t **
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)
284 {
285   uint8_t **GSVALS = NULL;
286   size_t consumed_bytes = 0;
287   int i, j, code, stride;
288   int x, y;
289   Jbig2Image **GSPLANES;
290   Jbig2GenericRegionParams rparams;
291   Jbig2WordStream *ws = NULL;
292   Jbig2ArithState *as = NULL;
293
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);
299     return NULL;
300   }
301
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]);
310       }
311       jbig2_free(ctx->allocator, GSPLANES);
312       return NULL;
313     }
314   }
315
316   /* C.5 step 1. Decode GSPLANES[GSBPP-1] */ 
317   /* fill generic region decoder parameters */
318   rparams.MMR = GSMMR;
319   rparams.GBTEMPLATE = GSTEMPLATE;
320   rparams.TPGDON = 0;
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;
326   rparams.gbat[4] = 2;
327   rparams.gbat[5] = -2;
328   rparams.gbat[6] = -2;
329   rparams.gbat[7] = -2;
330
331   if (GSMMR) {
332     code = jbig2_decode_halftone_mmr(ctx, &rparams, data, size,
333                                      GSPLANES[GSBPP-1], &consumed_bytes);
334   } else {
335     ws = jbig2_word_stream_buf_new(ctx, data, size);
336     if (ws == NULL)
337     {
338       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
339         "failed to allocate ws in jbig2_decode_gray_scale_image");
340       goto cleanup;
341     }
342
343     as = jbig2_arith_new(ctx, ws);
344     if (as == NULL)
345     {
346       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
347         "failed to allocate as in jbig2_decode_gray_scale_image");
348       goto cleanup;
349     }
350
351     code = jbig2_decode_generic_region(ctx, segment, &rparams, as,
352                                        GSPLANES[GSBPP-1], GB_stats);
353
354   }
355   if (code != 0) {
356     jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
357                 "error decoding GSPLANES for halftone image");
358     goto cleanup;
359   }
360
361   /* C.5 step 2. Set j = GSBPP-2 */ 
362   j = GSBPP - 2;
363   /* C.5 step 3. decode loop */ 
364   while(j >= 0) {
365     /*  C.5 step 3. (a) */
366     if (GSMMR) {
367       code = jbig2_decode_halftone_mmr(ctx, &rparams, data + consumed_bytes,
368                                        size - consumed_bytes, GSPLANES[j],
369                                        &consumed_bytes);
370     } else {
371       code = jbig2_decode_generic_region(ctx, segment, &rparams, as,
372                                          GSPLANES[j], GB_stats);
373     }
374     if (code != 0) {
375       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
376                   "error decoding GSPLANES for halftone image");
377       goto cleanup;
378     }
379
380     /* C.5 step 3. (b):
381      * for each [x,y]
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];
386
387     /*  C.5 step 3. (c) */
388     --j;
389   }
390
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);
396     goto cleanup;
397   }
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]);
406       }
407       jbig2_free(ctx->allocator, GSVALS);
408       GSVALS = NULL;
409       goto cleanup;
410     }
411   }
412
413   /*  C.5 step 4.  */
414   for (x = 0; x < GSW; ++x) {
415     for (y = 0; y < GSH; ++y) {
416       GSVALS[x][y] = 0;
417
418       for (j = 0; j < GSBPP; ++j)
419         GSVALS[x][y] += jbig2_image_get_pixel(GSPLANES[j], x, y) << j;
420     }
421   }
422
423 cleanup:
424   /* free memory */
425   if (!GSMMR) {
426     jbig2_free(ctx->allocator, as);
427     jbig2_word_stream_buf_free(ctx, ws);
428   }
429   for (i=0; i< GSBPP; ++i)
430     jbig2_image_release(ctx, GSPLANES[i]);
431
432   jbig2_free(ctx->allocator, GSPLANES);
433
434   return GSVALS;
435 }
436
437 /**
438  * jbig2_decode_ht_region_get_hpats: get pattern dictionary 
439  *
440  * @ctx: jbig2 decoder context
441  * @segment: jbig2 halftone region segment 
442  *
443  * Returns the first referred pattern dictionary of segment 
444  *
445  * returns: pattern dictionary
446  *          0 if search failed
447  **/
448 Jbig2PatternDict * 
449 jbig2_decode_ht_region_get_hpats(Jbig2Ctx *ctx, Jbig2Segment *segment)
450 {
451   int index = 0;
452   Jbig2PatternDict *pattern_dict = NULL;
453   Jbig2Segment *rsegment = NULL;
454
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]);
458     if (rsegment) {
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;
462         return pattern_dict;
463       }
464     }
465     index++;
466   }
467   return pattern_dict;
468 }
469
470 /**
471  * jbig2_decode_halftone_region: decode a halftone region
472  *
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
479  *
480  * Implements the halftone region decoding proceedure
481  * described in section 6.6.5 of the JBIG2 spec.
482  *
483  * returns: 0 on success
484  *         <0 on failure
485  **/
486 int
487 jbig2_decode_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
488                              Jbig2HalftoneRegionParams *params,
489                              const byte *data, const size_t size,
490                              Jbig2Image *image,
491                              Jbig2ArithCx *GB_stats)
492 {
493   uint32_t HBPP;
494   uint32_t HNUMPATS;
495   uint8_t **GI;
496   Jbig2Image *HSKIP = NULL;
497   Jbig2PatternDict * HPATS;
498   int i;
499   uint32_t mg, ng;
500   int32_t x, y;
501   uint8_t gray_val;
502
503   /* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */
504   memset(image->data, params->HDEFPIXEL, image->stride * image->height);
505
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");
510   }
511
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 */
515
516   HPATS = jbig2_decode_ht_region_get_hpats(ctx, segment);
517   if (!HPATS) {
518     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
519     "no pattern dictionary found, skipping halftone image");
520     return -1;
521   }
522   HNUMPATS = HPATS->n_patterns;
523
524   /* calculate ceil(log2(HNUMPATS)) */
525   HBPP = 0; 
526   while(HNUMPATS > (1 << ++HBPP));
527
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,
533                                      GB_stats); 
534
535   if (!GI) {
536     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
537     "unable to acquire gray-scale image, skipping halftone image");
538     return -1;
539   }
540
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;
546
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",
552                     gray_val);
553         /* use highest aviable pattern */
554         gray_val = HNUMPATS - 1;
555       }
556       jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->op);
557     }
558   }
559
560   /* free GI */
561   for (i = 0; i < params->HGW; ++i) {
562     jbig2_free(ctx->allocator, GI[i]);
563   }
564   jbig2_free(ctx->allocator, GI);
565
566   return 0;
567 }
568
569 /**
570  * jbig2_halftone_region: read a halftone region segment header
571  **/
572 int
573 jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
574 {
575   int offset = 0;
576   Jbig2RegionSegmentInfo region_info;
577   Jbig2HalftoneRegionParams params;
578   Jbig2Image *image = NULL;
579   Jbig2ArithCx *GB_stats = NULL;
580   int code = 0;
581
582   /* 7.4.5.1 */
583   if (segment->data_length < 17) goto too_short;
584   jbig2_get_region_segment_info(&region_info, segment_data);
585   offset += 17;
586
587   if (segment->data_length < 18) goto too_short;
588
589   /* 7.4.5.1.1 */
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;
596   offset += 1;
597
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);
602
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);
607   }
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);
612   }
613
614   /* Figure 43 */
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);
620   offset += 16;
621
622   /* Figure 44 */
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);
626   offset += 4;
627
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);
635
636   /* 7.4.5.2.2 */
637   if (!params.HMMR) {
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)
642     {
643       return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
644           "failed to allocate GB_stats in halftone region");
645     }
646     memset(GB_stats, 0, stats_size);
647   }
648
649   image = jbig2_image_new(ctx, region_info.width, region_info.height);
650   if (image == NULL)
651   {
652     jbig2_free(ctx->allocator, GB_stats);
653     return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
654         "unable to allocate halftone image");
655   }
656
657   code = jbig2_decode_halftone_region(ctx, segment, &params,
658                 segment_data + offset, segment->data_length - offset,
659                 image, GB_stats);
660
661   /* todo: retain GB_stats? */
662   if (!params.HMMR) {
663     jbig2_free(ctx->allocator, GB_stats);
664   }
665
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);
669
670   return code;
671
672 too_short:
673     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
674                        "Segment too short");
675 }