/src/mupdf/thirdparty/jbig2dec/jbig2_halftone.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* Copyright (C) 2001-2023 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.,  39 Mesa Street, Suite 108A, San Francisco,  | 
13  |  |    CA 94129, USA, for further information.  | 
14  |  | */  | 
15  |  |  | 
16  |  | /*  | 
17  |  |     jbig2dec  | 
18  |  | */  | 
19  |  |  | 
20  |  | /* JBIG2 Pattern Dictionary and Halftone Region decoding */  | 
21  |  |  | 
22  |  | #ifdef HAVE_CONFIG_H  | 
23  |  | #include "config.h"  | 
24  |  | #endif  | 
25  |  | #include "os_types.h"  | 
26  |  |  | 
27  |  | #include <string.h>             /* memset() */  | 
28  |  |  | 
29  |  | #include "jbig2.h"  | 
30  |  | #include "jbig2_priv.h"  | 
31  |  | #include "jbig2_arith.h"  | 
32  |  | #include "jbig2_generic.h"  | 
33  |  | #include "jbig2_image.h"  | 
34  |  | #include "jbig2_halftone.h"  | 
35  |  | #include "jbig2_mmr.h"  | 
36  |  | #include "jbig2_page.h"  | 
37  |  | #include "jbig2_segment.h"  | 
38  |  |  | 
39  |  | /**  | 
40  |  |  * jbig2_hd_new: create a new dictionary from a collective bitmap  | 
41  |  |  */  | 
42  |  | static Jbig2PatternDict *  | 
43  |  | jbig2_hd_new(Jbig2Ctx *ctx, const Jbig2PatternDictParams *params, Jbig2Image *image)  | 
44  | 120  | { | 
45  | 120  |     Jbig2PatternDict *new;  | 
46  | 120  |     const uint32_t N = params->GRAYMAX + 1;  | 
47  | 120  |     const uint32_t HPW = params->HDPW;  | 
48  | 120  |     const uint32_t HPH = params->HDPH;  | 
49  | 120  |     int code;  | 
50  | 120  |     uint32_t i, j;  | 
51  |  |  | 
52  | 120  |     if (N == 0) { | 
53  |  |         /* We've wrapped. */  | 
54  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "params->GRAYMAX out of range");  | 
55  | 0  |         return NULL;  | 
56  | 0  |     }  | 
57  |  |  | 
58  |  |     /* allocate a new struct */  | 
59  | 120  |     new = jbig2_new(ctx, Jbig2PatternDict, 1);  | 
60  | 120  |     if (new != NULL) { | 
61  | 120  |         new->patterns = jbig2_new(ctx, Jbig2Image *, N);  | 
62  | 120  |         if (new->patterns == NULL) { | 
63  | 2  |             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate pattern in collective bitmap dictionary");  | 
64  | 2  |             jbig2_free(ctx->allocator, new);  | 
65  | 2  |             return NULL;  | 
66  | 2  |         }  | 
67  | 118  |         new->n_patterns = N;  | 
68  | 118  |         new->HPW = HPW;  | 
69  | 118  |         new->HPH = HPH;  | 
70  |  |  | 
71  |  |         /* 6.7.5(4) - copy out the individual pattern images */  | 
72  | 7.50M  |         for (i = 0; i < N; i++) { | 
73  | 7.50M  |             new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);  | 
74  | 7.50M  |             if (new->patterns[i] == NULL) { | 
75  | 7  |                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate pattern element image");  | 
76  |  |                 /* new->patterns[i] above did not succeed, so releasing patterns 0..i-1 is enough */  | 
77  | 4.86M  |                 for (j = 0; j < i; j++)  | 
78  | 4.86M  |                     jbig2_image_release(ctx, new->patterns[j]);  | 
79  | 7  |                 jbig2_free(ctx->allocator, new->patterns);  | 
80  | 7  |                 jbig2_free(ctx->allocator, new);  | 
81  | 7  |                 return NULL;  | 
82  | 7  |             }  | 
83  |  |             /* compose with the REPLACE operator; the source  | 
84  |  |                will be clipped to the destination, selecting the  | 
85  |  |                proper sub image */  | 
86  | 7.50M  |             code = jbig2_image_compose(ctx, new->patterns[i], image, -i * (int32_t) HPW, 0, JBIG2_COMPOSE_REPLACE);  | 
87  | 7.50M  |             if (code < 0) { | 
88  | 0  |                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to compose image into collective bitmap dictionary");  | 
89  |  |                 /* new->patterns[i] above succeeded, so release all patterns 0..i */  | 
90  | 0  |                 for (j = 0; j <= i; j++)  | 
91  | 0  |                     jbig2_image_release(ctx, new->patterns[j]);  | 
92  | 0  |                 jbig2_free(ctx->allocator, new->patterns);  | 
93  | 0  |                 jbig2_free(ctx->allocator, new);  | 
94  | 0  |                 return NULL;  | 
95  | 0  |             }  | 
96  | 7.50M  |         }  | 
97  | 118  |     } else { | 
98  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to allocate collective bitmap dictionary");  | 
99  | 0  |     }  | 
100  |  |  | 
101  | 111  |     return new;  | 
102  | 120  | }  | 
103  |  |  | 
104  |  | /**  | 
105  |  |  * jbig2_hd_release: release a pattern dictionary  | 
106  |  |  */  | 
107  |  | void  | 
108  |  | jbig2_hd_release(Jbig2Ctx *ctx, Jbig2PatternDict *dict)  | 
109  | 111  | { | 
110  | 111  |     int i;  | 
111  |  |  | 
112  | 111  |     if (dict == NULL)  | 
113  | 0  |         return;  | 
114  | 111  |     if (dict->patterns != NULL)  | 
115  | 2.63M  |         for (i = 0; i < dict->n_patterns; i++)  | 
116  | 2.63M  |             jbig2_image_release(ctx, dict->patterns[i]);  | 
117  | 111  |     jbig2_free(ctx->allocator, dict->patterns);  | 
118  | 111  |     jbig2_free(ctx->allocator, dict);  | 
119  | 111  | }  | 
120  |  |  | 
121  |  | /**  | 
122  |  |  * jbig2_decode_pattern_dict: decode pattern dictionary data  | 
123  |  |  *  | 
124  |  |  * @ctx: jbig2 decoder context  | 
125  |  |  * @segment: jbig2 segment (header) structure  | 
126  |  |  * @params: parameters from the pattern dictionary header  | 
127  |  |  * @data: pointer to text region data to be decoded  | 
128  |  |  * @size: length of text region data  | 
129  |  |  * @GB_stats: arithmetic coding context to use  | 
130  |  |  *  | 
131  |  |  * Implements the pattern dictionary decoding procedure  | 
132  |  |  * described in section 6.7 of the JBIG2 spec.  | 
133  |  |  *  | 
134  |  |  * returns: a pointer to the resulting dictionary on success  | 
135  |  |  * returns: 0 on failure  | 
136  |  |  **/  | 
137  |  | static Jbig2PatternDict *  | 
138  |  | jbig2_decode_pattern_dict(Jbig2Ctx *ctx, Jbig2Segment *segment,  | 
139  |  |                           const Jbig2PatternDictParams *params, const byte *data, const size_t size, Jbig2ArithCx *GB_stats)  | 
140  | 138  | { | 
141  | 138  |     Jbig2PatternDict *hd = NULL;  | 
142  | 138  |     Jbig2Image *image = NULL;  | 
143  | 138  |     Jbig2GenericRegionParams rparams;  | 
144  | 138  |     int code = 0;  | 
145  |  |  | 
146  |  |     /* allocate the collective image */  | 
147  | 138  |     image = jbig2_image_new(ctx, params->HDPW * (params->GRAYMAX + 1), params->HDPH);  | 
148  | 138  |     if (image == NULL) { | 
149  | 2  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate collective bitmap for halftone dictionary");  | 
150  | 2  |         return NULL;  | 
151  | 2  |     }  | 
152  |  |  | 
153  |  |     /* fill out the generic region decoder parameters */  | 
154  | 136  |     rparams.MMR = params->HDMMR;  | 
155  | 136  |     rparams.GBTEMPLATE = params->HDTEMPLATE;  | 
156  | 136  |     rparams.TPGDON = 0;         /* not used if HDMMR = 1 */  | 
157  | 136  |     rparams.USESKIP = 0;  | 
158  | 136  |     rparams.gbat[0] = -(int8_t) params->HDPW;  | 
159  | 136  |     rparams.gbat[1] = 0;  | 
160  | 136  |     rparams.gbat[2] = -3;  | 
161  | 136  |     rparams.gbat[3] = -1;  | 
162  | 136  |     rparams.gbat[4] = 2;  | 
163  | 136  |     rparams.gbat[5] = -2;  | 
164  | 136  |     rparams.gbat[6] = -2;  | 
165  | 136  |     rparams.gbat[7] = -2;  | 
166  |  |  | 
167  | 136  |     if (params->HDMMR) { | 
168  | 135  |         code = jbig2_decode_generic_mmr(ctx, segment, &rparams, data, size, image);  | 
169  | 135  |     } else { | 
170  | 1  |         Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size);  | 
171  |  |  | 
172  | 1  |         if (ws != NULL) { | 
173  | 1  |             Jbig2ArithState *as = jbig2_arith_new(ctx, ws);  | 
174  |  |  | 
175  | 1  |             if (as != NULL) { | 
176  | 1  |                 code = jbig2_decode_generic_region(ctx, segment, &rparams, as, image, GB_stats);  | 
177  | 1  |             } else { | 
178  | 0  |                 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when handling halftone dictionary");  | 
179  | 0  |             }  | 
180  |  |  | 
181  | 1  |             jbig2_free(ctx->allocator, as);  | 
182  | 1  |             jbig2_word_stream_buf_free(ctx, ws);  | 
183  | 1  |         } else { | 
184  | 0  |             code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when handling halftone dictionary");  | 
185  | 0  |         }  | 
186  | 1  |     }  | 
187  |  |  | 
188  | 136  |     if (code == 0)  | 
189  | 120  |         hd = jbig2_hd_new(ctx, params, image);  | 
190  | 16  |     else  | 
191  | 16  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode immediate generic region");  | 
192  | 136  |     jbig2_image_release(ctx, image);  | 
193  |  |  | 
194  | 136  |     return hd;  | 
195  | 138  | }  | 
196  |  |  | 
197  |  | /* 7.4.4 */  | 
198  |  | int  | 
199  |  | jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)  | 
200  | 139  | { | 
201  | 139  |     Jbig2PatternDictParams params;  | 
202  | 139  |     Jbig2ArithCx *GB_stats = NULL;  | 
203  | 139  |     byte flags;  | 
204  | 139  |     int offset = 0;  | 
205  |  |  | 
206  |  |     /* 7.4.4.1 - Data header */  | 
207  | 139  |     if (segment->data_length < 7) { | 
208  | 1  |         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");  | 
209  | 1  |     }  | 
210  | 138  |     flags = segment_data[0];  | 
211  | 138  |     params.HDMMR = flags & 1;  | 
212  | 138  |     params.HDTEMPLATE = (flags & 6) >> 1;  | 
213  | 138  |     params.HDPW = segment_data[1];  | 
214  | 138  |     params.HDPH = segment_data[2];  | 
215  | 138  |     params.GRAYMAX = jbig2_get_uint32(segment_data + 3);  | 
216  | 138  |     offset += 7;  | 
217  |  |  | 
218  | 138  |     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,  | 
219  | 138  |                 "pattern dictionary, flags=%02x, %d grays (%dx%d cell)", flags, params.GRAYMAX + 1, params.HDPW, params.HDPH);  | 
220  |  |  | 
221  | 138  |     if (params.HDMMR && params.HDTEMPLATE) { | 
222  | 137  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "HDTEMPLATE is %d when HDMMR is %d, contrary to spec", params.HDTEMPLATE, params.HDMMR);  | 
223  | 137  |     }  | 
224  | 138  |     if (flags & 0xf8) { | 
225  | 87  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved flag bits non-zero");  | 
226  | 87  |     }  | 
227  |  |  | 
228  |  |     /* 7.4.4.2 */  | 
229  | 138  |     if (!params.HDMMR) { | 
230  |  |         /* allocate and zero arithmetic coding stats */  | 
231  | 1  |         int stats_size = jbig2_generic_stats_size(ctx, params.HDTEMPLATE);  | 
232  |  |  | 
233  | 1  |         GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);  | 
234  | 1  |         if (GB_stats == NULL)  | 
235  | 0  |             return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when handling pattern dictionary");  | 
236  | 1  |         memset(GB_stats, 0, stats_size);  | 
237  | 1  |     }  | 
238  |  |  | 
239  | 138  |     segment->result = jbig2_decode_pattern_dict(ctx, segment, ¶ms, segment_data + offset, segment->data_length - offset, GB_stats);  | 
240  |  |  | 
241  |  |     /* todo: retain GB_stats? */  | 
242  | 138  |     if (!params.HDMMR) { | 
243  | 1  |         jbig2_free(ctx->allocator, GB_stats);  | 
244  | 1  |     }  | 
245  |  |  | 
246  | 138  |     return (segment->result != NULL) ? 0 : -1;  | 
247  | 138  | }  | 
248  |  |  | 
249  |  | /**  | 
250  |  |  * jbig2_decode_gray_scale_image: decode gray-scale image  | 
251  |  |  *  | 
252  |  |  * @ctx: jbig2 decoder context  | 
253  |  |  * @segment: jbig2 segment (header) structure  | 
254  |  |  * @data: pointer to text region data to be decoded  | 
255  |  |  * @size: length of text region data  | 
256  |  |  * @GSMMR: if MMR is used  | 
257  |  |  * @GSW: width of gray-scale image  | 
258  |  |  * @GSH: height of gray-scale image  | 
259  |  |  * @GSBPP: number of bitplanes/Jbig2Images to use  | 
260  |  |  * @GSKIP: mask indicating which values should be skipped  | 
261  |  |  * @GSTEMPLATE: template used to code the gray-scale bitplanes  | 
262  |  |  * @GB_stats: arithmetic coding context to use  | 
263  |  |  *  | 
264  |  |  * Implements the decoding a gray-scale image described in  | 
265  |  |  * annex C.5. This is part of the halftone region decoding.  | 
266  |  |  *  | 
267  |  |  * returns: array of gray-scale values with GSW x GSH width/height  | 
268  |  |  *          0 on failure  | 
269  |  |  **/  | 
270  |  | static uint16_t **  | 
271  |  | jbig2_decode_gray_scale_image(Jbig2Ctx *ctx, Jbig2Segment *segment,  | 
272  |  |                               const byte *data, const size_t size,  | 
273  |  |                               bool GSMMR, uint32_t GSW, uint32_t GSH,  | 
274  |  |                               uint32_t GSBPP, bool GSUSESKIP, Jbig2Image *GSKIP, int GSTEMPLATE, Jbig2ArithCx *GB_stats)  | 
275  | 0  | { | 
276  | 0  |     uint16_t **GSVALS = NULL;  | 
277  | 0  |     size_t consumed_bytes = 0;  | 
278  | 0  |     uint32_t i, j, stride, x, y;  | 
279  | 0  |     int code;  | 
280  | 0  |     Jbig2Image **GSPLANES;  | 
281  | 0  |     Jbig2GenericRegionParams rparams;  | 
282  | 0  |     Jbig2WordStream *ws = NULL;  | 
283  | 0  |     Jbig2ArithState *as = NULL;  | 
284  |  |  | 
285  |  |     /* allocate GSPLANES */  | 
286  | 0  |     GSPLANES = jbig2_new(ctx, Jbig2Image *, GSBPP);  | 
287  | 0  |     if (GSPLANES == NULL) { | 
288  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate %d bytes for GSPLANES", GSBPP);  | 
289  | 0  |         return NULL;  | 
290  | 0  |     }  | 
291  |  |  | 
292  | 0  |     for (i = 0; i < GSBPP; ++i) { | 
293  | 0  |         GSPLANES[i] = jbig2_image_new(ctx, GSW, GSH);  | 
294  | 0  |         if (GSPLANES[i] == NULL) { | 
295  | 0  |             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate %dx%d image for GSPLANES", GSW, GSH);  | 
296  |  |             /* free already allocated */  | 
297  | 0  |             for (j = i; j > 0;)  | 
298  | 0  |                 jbig2_image_release(ctx, GSPLANES[--j]);  | 
299  | 0  |             jbig2_free(ctx->allocator, GSPLANES);  | 
300  | 0  |             return NULL;  | 
301  | 0  |         }  | 
302  | 0  |     }  | 
303  |  |  | 
304  |  |     /* C.5 step 1. Decode GSPLANES[GSBPP-1] */  | 
305  |  |     /* fill generic region decoder parameters */  | 
306  | 0  |     rparams.MMR = GSMMR;  | 
307  | 0  |     rparams.GBTEMPLATE = GSTEMPLATE;  | 
308  | 0  |     rparams.TPGDON = 0;  | 
309  | 0  |     rparams.USESKIP = GSUSESKIP;  | 
310  | 0  |     rparams.SKIP = GSKIP;  | 
311  | 0  |     rparams.gbat[0] = (GSTEMPLATE <= 1 ? 3 : 2);  | 
312  | 0  |     rparams.gbat[1] = -1;  | 
313  | 0  |     rparams.gbat[2] = -3;  | 
314  | 0  |     rparams.gbat[3] = -1;  | 
315  | 0  |     rparams.gbat[4] = 2;  | 
316  | 0  |     rparams.gbat[5] = -2;  | 
317  | 0  |     rparams.gbat[6] = -2;  | 
318  | 0  |     rparams.gbat[7] = -2;  | 
319  |  | 
  | 
320  | 0  |     if (GSMMR) { | 
321  | 0  |         code = jbig2_decode_halftone_mmr(ctx, &rparams, data, size, GSPLANES[GSBPP - 1], &consumed_bytes);  | 
322  | 0  |     } else { | 
323  | 0  |         ws = jbig2_word_stream_buf_new(ctx, data, size);  | 
324  | 0  |         if (ws == NULL) { | 
325  | 0  |             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when decoding gray scale image");  | 
326  | 0  |             goto cleanup;  | 
327  | 0  |         }  | 
328  |  |  | 
329  | 0  |         as = jbig2_arith_new(ctx, ws);  | 
330  | 0  |         if (as == NULL) { | 
331  | 0  |             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when decoding gray scale image");  | 
332  | 0  |             goto cleanup;  | 
333  | 0  |         }  | 
334  |  |  | 
335  | 0  |         code = jbig2_decode_generic_region(ctx, segment, &rparams, as, GSPLANES[GSBPP - 1], GB_stats);  | 
336  | 0  |     }  | 
337  | 0  |     if (code < 0) { | 
338  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error decoding GSPLANES for halftone image");  | 
339  | 0  |         goto cleanup;  | 
340  | 0  |     }  | 
341  |  |  | 
342  |  |     /* C.5 step 2. Set j = GSBPP-2 */  | 
343  | 0  |     j = GSBPP - 1;  | 
344  |  |     /* C.5 step 3. decode loop */  | 
345  | 0  |     while (j > 0) { | 
346  | 0  |         j--;  | 
347  |  |         /*  C.5 step 3. (a) */  | 
348  | 0  |         if (GSMMR) { | 
349  | 0  |             code = jbig2_decode_halftone_mmr(ctx, &rparams, data + consumed_bytes, size - consumed_bytes, GSPLANES[j], &consumed_bytes);  | 
350  | 0  |         } else { | 
351  | 0  |             code = jbig2_decode_generic_region(ctx, segment, &rparams, as, GSPLANES[j], GB_stats);  | 
352  | 0  |         }  | 
353  | 0  |         if (code < 0) { | 
354  | 0  |             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode GSPLANES for halftone image");  | 
355  | 0  |             goto cleanup;  | 
356  | 0  |         }  | 
357  |  |  | 
358  |  |         /* C.5 step 3. (b):  | 
359  |  |          * for each [x,y]  | 
360  |  |          * GSPLANES[j][x][y] = GSPLANES[j+1][x][y] XOR GSPLANES[j][x][y] */  | 
361  | 0  |         stride = GSPLANES[j]->stride;  | 
362  | 0  |         for (i = 0; i < stride * GSH; ++i)  | 
363  | 0  |             GSPLANES[j]->data[i] ^= GSPLANES[j + 1]->data[i];  | 
364  |  |  | 
365  |  |         /*  C.5 step 3. (c) */  | 
366  | 0  |     }  | 
367  |  |  | 
368  |  |     /* allocate GSVALS */  | 
369  | 0  |     GSVALS = jbig2_new(ctx, uint16_t *, GSW);  | 
370  | 0  |     if (GSVALS == NULL) { | 
371  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate GSVALS: %d bytes", GSW);  | 
372  | 0  |         goto cleanup;  | 
373  | 0  |     }  | 
374  | 0  |     for (i = 0; i < GSW; ++i) { | 
375  | 0  |         GSVALS[i] = jbig2_new(ctx, uint16_t, GSH);  | 
376  | 0  |         if (GSVALS[i] == NULL) { | 
377  | 0  |             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate GSVALS: %d bytes", GSH * GSW);  | 
378  |  |             /* free already allocated */  | 
379  | 0  |             for (j = i; j > 0;)  | 
380  | 0  |                 jbig2_free(ctx->allocator, GSVALS[--j]);  | 
381  | 0  |             jbig2_free(ctx->allocator, GSVALS);  | 
382  | 0  |             GSVALS = NULL;  | 
383  | 0  |             goto cleanup;  | 
384  | 0  |         }  | 
385  | 0  |     }  | 
386  |  |  | 
387  |  |     /*  C.5 step 4.  */  | 
388  | 0  |     for (x = 0; x < GSW; ++x) { | 
389  | 0  |         for (y = 0; y < GSH; ++y) { | 
390  | 0  |             GSVALS[x][y] = 0;  | 
391  |  | 
  | 
392  | 0  |             for (j = 0; j < GSBPP; ++j)  | 
393  | 0  |                 GSVALS[x][y] += jbig2_image_get_pixel(GSPLANES[j], x, y) << j;  | 
394  | 0  |         }  | 
395  | 0  |     }  | 
396  |  | 
  | 
397  | 0  | cleanup:  | 
398  |  |     /* free memory */  | 
399  | 0  |     if (!GSMMR) { | 
400  | 0  |         jbig2_free(ctx->allocator, as);  | 
401  | 0  |         jbig2_word_stream_buf_free(ctx, ws);  | 
402  | 0  |     }  | 
403  | 0  |     for (i = 0; i < GSBPP; ++i)  | 
404  | 0  |         jbig2_image_release(ctx, GSPLANES[i]);  | 
405  |  | 
  | 
406  | 0  |     jbig2_free(ctx->allocator, GSPLANES);  | 
407  |  | 
  | 
408  | 0  |     return GSVALS;  | 
409  | 0  | }  | 
410  |  |  | 
411  |  | /**  | 
412  |  |  * jbig2_decode_ht_region_get_hpats: get pattern dictionary  | 
413  |  |  *  | 
414  |  |  * @ctx: jbig2 decoder context  | 
415  |  |  * @segment: jbig2 halftone region segment  | 
416  |  |  *  | 
417  |  |  * Returns the first referred pattern dictionary of segment  | 
418  |  |  *  | 
419  |  |  * returns: pattern dictionary  | 
420  |  |  *          0 if search failed  | 
421  |  |  **/  | 
422  |  | static Jbig2PatternDict *  | 
423  |  | jbig2_decode_ht_region_get_hpats(Jbig2Ctx *ctx, Jbig2Segment *segment)  | 
424  | 0  | { | 
425  | 0  |     int index = 0;  | 
426  | 0  |     Jbig2PatternDict *pattern_dict = NULL;  | 
427  | 0  |     Jbig2Segment *rsegment = NULL;  | 
428  |  |  | 
429  |  |     /* loop through all referred segments */  | 
430  | 0  |     while (!pattern_dict && segment->referred_to_segment_count > index) { | 
431  | 0  |         rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);  | 
432  | 0  |         if (rsegment) { | 
433  |  |             /* segment type is pattern dictionary and result is not empty */  | 
434  | 0  |             if ((rsegment->flags & 0x3f) == 16 && rsegment->result) { | 
435  | 0  |                 pattern_dict = (Jbig2PatternDict *) rsegment->result;  | 
436  | 0  |                 return pattern_dict;  | 
437  | 0  |             }  | 
438  | 0  |         }  | 
439  | 0  |         index++;  | 
440  | 0  |     }  | 
441  | 0  |     return pattern_dict;  | 
442  | 0  | }  | 
443  |  |  | 
444  |  | /**  | 
445  |  |  * jbig2_decode_halftone_region: decode a halftone region  | 
446  |  |  *  | 
447  |  |  * @ctx: jbig2 decoder context  | 
448  |  |  * @segment: jbig2 halftone region segment  | 
449  |  |  * @params: parameters  | 
450  |  |  * @data: pointer to halftone region data to be decoded  | 
451  |  |  * @size: length of halftone region data  | 
452  |  |  * @GB_stats: arithmetic coding context to use  | 
453  |  |  *  | 
454  |  |  * Implements the halftone region decoding procedure  | 
455  |  |  * described in section 6.6.5 of the JBIG2 spec.  | 
456  |  |  *  | 
457  |  |  * returns: 0 on success  | 
458  |  |  *         <0 on failure  | 
459  |  |  **/  | 
460  |  | static int  | 
461  |  | jbig2_decode_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment,  | 
462  |  |                              Jbig2HalftoneRegionParams *params, const byte *data, const size_t size, Jbig2Image *image, Jbig2ArithCx *GB_stats)  | 
463  | 0  | { | 
464  | 0  |     uint32_t HBPP;  | 
465  | 0  |     uint32_t HNUMPATS;  | 
466  | 0  |     uint16_t **GI = NULL;  | 
467  | 0  |     Jbig2Image *HSKIP = NULL;  | 
468  | 0  |     Jbig2PatternDict *HPATS;  | 
469  | 0  |     uint32_t i;  | 
470  | 0  |     uint32_t mg, ng;  | 
471  | 0  |     uint16_t gray_val;  | 
472  | 0  |     int code = 0;  | 
473  |  |  | 
474  |  |     /* We need the patterns used in this region, get them from the referred pattern dictionary */  | 
475  | 0  |     HPATS = jbig2_decode_ht_region_get_hpats(ctx, segment);  | 
476  | 0  |     if (!HPATS) { | 
477  | 0  |         code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "no pattern dictionary found, skipping halftone image");  | 
478  | 0  |         goto cleanup;  | 
479  | 0  |     }  | 
480  |  |  | 
481  |  |     /* 6.6.5 point 1. Fill bitmap with HDEFPIXEL */  | 
482  | 0  |     memset(image->data, params->HDEFPIXEL, image->stride * image->height);  | 
483  |  |  | 
484  |  |     /* 6.6.5 point 2. compute HSKIP according to 6.6.5.1 */  | 
485  | 0  |     if (params->HENABLESKIP == 1) { | 
486  | 0  |         HSKIP = jbig2_image_new(ctx, params->HGW, params->HGH);  | 
487  | 0  |         if (HSKIP == NULL)  | 
488  | 0  |             return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate skip image");  | 
489  |  |  | 
490  | 0  |         for (mg = 0; mg < params->HGH; ++mg) { | 
491  | 0  |             for (ng = 0; ng < params->HGW; ++ng) { | 
492  | 0  |                 int64_t x = ((int64_t) params->HGX + mg * params->HRY + ng * params->HRX) >> 8;  | 
493  | 0  |                 int64_t y = ((int64_t) params->HGY + mg * params->HRX - ng * params->HRY) >> 8;  | 
494  |  | 
  | 
495  | 0  |                 if (x + HPATS->HPW <= 0 || x >= image->width || y + HPATS->HPH <= 0 || y >= image->height) { | 
496  | 0  |                     jbig2_image_set_pixel(HSKIP, ng, mg, 1);  | 
497  | 0  |                 } else { | 
498  | 0  |                     jbig2_image_set_pixel(HSKIP, ng, mg, 0);  | 
499  | 0  |                 }  | 
500  | 0  |             }  | 
501  | 0  |         }  | 
502  | 0  |     }  | 
503  |  |  | 
504  |  |     /* 6.6.5 point 3. set HBPP to ceil(log2(HNUMPATS)): */  | 
505  | 0  |     HNUMPATS = HPATS->n_patterns;  | 
506  | 0  |     HBPP = 0;  | 
507  | 0  |     while (HNUMPATS > (1U << ++HBPP));  | 
508  | 0  |     if (HBPP > 16) { | 
509  | 0  |         code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "HBPP is larger than supported (%u)", HBPP);  | 
510  | 0  |         goto cleanup;  | 
511  | 0  |     }  | 
512  |  |  | 
513  |  |     /* 6.6.5 point 4. decode gray-scale image as mentioned in annex C */  | 
514  | 0  |     GI = jbig2_decode_gray_scale_image(ctx, segment, data, size,  | 
515  | 0  |                                        params->HMMR, params->HGW, params->HGH, HBPP, params->HENABLESKIP, HSKIP, params->HTEMPLATE, GB_stats);  | 
516  | 0  |     if (!GI) { | 
517  | 0  |         code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to acquire gray-scale image, skipping halftone image");  | 
518  | 0  |         goto cleanup;  | 
519  | 0  |     }  | 
520  |  |  | 
521  |  |     /* 6.6.5 point 5. place patterns with procedure mentioned in 6.6.5.2 */  | 
522  | 0  |     for (mg = 0; mg < params->HGH; ++mg) { | 
523  | 0  |         for (ng = 0; ng < params->HGW; ++ng) { | 
524  | 0  |             int64_t x = ((int64_t) params->HGX + mg * params->HRY + ng * params->HRX) >> 8;  | 
525  | 0  |             int64_t y = ((int64_t) params->HGY + mg * params->HRX - ng * params->HRY) >> 8;  | 
526  |  |  | 
527  |  |             /* prevent pattern index >= HNUMPATS */  | 
528  | 0  |             gray_val = GI[ng][mg];  | 
529  | 0  |             if (gray_val >= HNUMPATS) { | 
530  | 0  |                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "gray-scale index %d out of range, using largest index", gray_val);  | 
531  |  |                 /* use highest available pattern */  | 
532  | 0  |                 gray_val = HNUMPATS - 1;  | 
533  | 0  |             }  | 
534  | 0  |             code = jbig2_image_compose(ctx, image, HPATS->patterns[gray_val], x, y, params->HCOMBOP);  | 
535  | 0  |             if (code < 0) { | 
536  | 0  |                 code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose pattern with gray-scale image");  | 
537  | 0  |                 goto cleanup;  | 
538  | 0  |             }  | 
539  | 0  |         }  | 
540  | 0  |     }  | 
541  |  |  | 
542  | 0  | cleanup:  | 
543  | 0  |     if (GI) { | 
544  | 0  |         for (i = 0; i < params->HGW; ++i) { | 
545  | 0  |             jbig2_free(ctx->allocator, GI[i]);  | 
546  | 0  |         }  | 
547  | 0  |     }  | 
548  | 0  |     jbig2_free(ctx->allocator, GI);  | 
549  | 0  |     jbig2_image_release(ctx, HSKIP);  | 
550  |  | 
  | 
551  | 0  |     return code;  | 
552  | 0  | }  | 
553  |  |  | 
554  |  | /**  | 
555  |  |  * jbig2_halftone_region: read a halftone region segment header  | 
556  |  |  **/  | 
557  |  | int  | 
558  |  | jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)  | 
559  | 0  | { | 
560  | 0  |     int offset = 0;  | 
561  | 0  |     Jbig2RegionSegmentInfo region_info;  | 
562  | 0  |     Jbig2HalftoneRegionParams params;  | 
563  | 0  |     Jbig2Image *image = NULL;  | 
564  | 0  |     Jbig2ArithCx *GB_stats = NULL;  | 
565  | 0  |     int code = 0;  | 
566  |  |  | 
567  |  |     /* 7.4.5.1 */  | 
568  | 0  |     if (segment->data_length < 17)  | 
569  | 0  |         goto too_short;  | 
570  | 0  |     jbig2_get_region_segment_info(®ion_info, segment_data);  | 
571  | 0  |     offset += 17;  | 
572  |  | 
  | 
573  | 0  |     if (segment->data_length < 18)  | 
574  | 0  |         goto too_short;  | 
575  |  |  | 
576  |  |     /* 7.4.5.1.1 Figure 42 */  | 
577  | 0  |     params.flags = segment_data[offset];  | 
578  | 0  |     params.HMMR = params.flags & 1;  | 
579  | 0  |     params.HTEMPLATE = (params.flags & 6) >> 1;  | 
580  | 0  |     params.HENABLESKIP = (params.flags & 8) >> 3;  | 
581  | 0  |     params.HCOMBOP = (Jbig2ComposeOp)((params.flags & 0x70) >> 4);  | 
582  | 0  |     params.HDEFPIXEL = (params.flags & 0x80) >> 7;  | 
583  | 0  |     offset += 1;  | 
584  |  | 
  | 
585  | 0  |     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,  | 
586  | 0  |                 "halftone region: %u x %u @ (%u, %u), flags = %02x", region_info.width, region_info.height, region_info.x, region_info.y, params.flags);  | 
587  |  | 
  | 
588  | 0  |     if (params.HMMR && params.HTEMPLATE) { | 
589  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "HTEMPLATE is %d when HMMR is %d, contrary to spec", params.HTEMPLATE, params.HMMR);  | 
590  | 0  |     }  | 
591  | 0  |     if (params.HMMR && params.HENABLESKIP) { | 
592  | 0  |         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "HENABLESKIP is %d when HMMR is %d, contrary to spec", params.HENABLESKIP, params.HMMR);  | 
593  | 0  |     }  | 
594  |  |  | 
595  |  |     /* 7.4.5.1.2 Figure 43 */  | 
596  | 0  |     if (segment->data_length - offset < 16)  | 
597  | 0  |         goto too_short;  | 
598  | 0  |     params.HGW = jbig2_get_uint32(segment_data + offset);  | 
599  | 0  |     params.HGH = jbig2_get_uint32(segment_data + offset + 4);  | 
600  | 0  |     params.HGX = jbig2_get_int32(segment_data + offset + 8);  | 
601  | 0  |     params.HGY = jbig2_get_int32(segment_data + offset + 12);  | 
602  | 0  |     offset += 16;  | 
603  |  |  | 
604  |  |     /* 7.4.5.1.3 Figure 44 */  | 
605  | 0  |     if (segment->data_length - offset < 4)  | 
606  | 0  |         goto too_short;  | 
607  | 0  |     params.HRX = jbig2_get_uint16(segment_data + offset);  | 
608  | 0  |     params.HRY = jbig2_get_uint16(segment_data + offset + 2);  | 
609  | 0  |     offset += 4;  | 
610  |  | 
  | 
611  | 0  |     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,  | 
612  | 0  |                 "grid %d x %d @ (%d.%d,%d.%d) vector (%d.%d,%d.%d)",  | 
613  | 0  |                 params.HGW, params.HGH,  | 
614  | 0  |                 params.HGX >> 8, params.HGX & 0xff,  | 
615  | 0  |                 params.HGY >> 8, params.HGY & 0xff,  | 
616  | 0  |                 params.HRX >> 8, params.HRX & 0xff,  | 
617  | 0  |                 params.HRY >> 8, params.HRY & 0xff);  | 
618  |  |  | 
619  |  |     /* 7.4.5.2 */  | 
620  | 0  |     if (!params.HMMR) { | 
621  |  |         /* allocate and zero arithmetic coding stats */  | 
622  | 0  |         int stats_size = jbig2_generic_stats_size(ctx, params.HTEMPLATE);  | 
623  |  | 
  | 
624  | 0  |         GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);  | 
625  | 0  |         if (GB_stats == NULL) { | 
626  | 0  |             return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states in halftone region");  | 
627  | 0  |         }  | 
628  | 0  |         memset(GB_stats, 0, stats_size);  | 
629  | 0  |     }  | 
630  |  |  | 
631  | 0  |     image = jbig2_image_new(ctx, region_info.width, region_info.height);  | 
632  | 0  |     if (image == NULL) { | 
633  | 0  |         jbig2_free(ctx->allocator, GB_stats);  | 
634  | 0  |         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate halftone image");  | 
635  | 0  |     }  | 
636  |  |  | 
637  | 0  |     code = jbig2_decode_halftone_region(ctx, segment, ¶ms, segment_data + offset, segment->data_length - offset, image, GB_stats);  | 
638  | 0  |     if (code < 0) { | 
639  | 0  |         jbig2_image_release(ctx, image);  | 
640  | 0  |         jbig2_free(ctx->allocator, GB_stats);  | 
641  | 0  |         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode halftone region");  | 
642  | 0  |     }  | 
643  |  |  | 
644  |  |     /* todo: retain GB_stats? */  | 
645  | 0  |     if (!params.HMMR) { | 
646  | 0  |         jbig2_free(ctx->allocator, GB_stats);  | 
647  | 0  |     }  | 
648  |  | 
  | 
649  | 0  |     code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);  | 
650  | 0  |     if (code < 0) { | 
651  | 0  |         jbig2_image_release(ctx, image);  | 
652  | 0  |         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add halftone region to page");  | 
653  | 0  |     }  | 
654  |  |  | 
655  | 0  |     jbig2_image_release(ctx, image);  | 
656  |  | 
  | 
657  | 0  |     return code;  | 
658  |  |  | 
659  | 0  | too_short:  | 
660  | 0  |     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");  | 
661  | 0  | }  |