1 /* Copyright (C) 2001-2020 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 <stdlib.h>
26 
27 #ifdef OUTPUT_PBM
28 #include <stdio.h>
29 #endif
30 
31 #include "jbig2.h"
32 #include "jbig2_priv.h"
33 #include "jbig2_image.h"
34 #include "jbig2_page.h"
35 #include "jbig2_segment.h"
36 
37 /* dump the page struct info */
38 static void
dump_page_info(Jbig2Ctx * ctx,Jbig2Segment * segment,Jbig2Page * page)39 dump_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, Jbig2Page *page)
40 {
41     if (page->x_resolution == 0) {
42         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "page %d image is %dx%d (unknown res)", page->number, page->width, page->height);
43     } else if (page->x_resolution == page->y_resolution) {
44         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "page %d image is %dx%d (%d ppm)", page->number, page->width, page->height, page->x_resolution);
45     } else {
46         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
47                     "page %d image is %dx%d (%dx%d ppm)", page->number, page->width, page->height, page->x_resolution, page->y_resolution);
48     }
49     if (page->striped) {
50         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "\tmaximum stripe size: %d", page->stripe_size);
51     }
52 }
53 
54 /**
55  * jbig2_page_info: parse page info segment
56  *
57  * Parse the page info segment data and fill out a corresponding
58  * Jbig2Page struct and ready it for subsequent rendered data,
59  * including allocating an image buffer for the page (or the first stripe)
60  **/
61 int
jbig2_page_info(Jbig2Ctx * ctx,Jbig2Segment * segment,const uint8_t * segment_data)62 jbig2_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
63 {
64     Jbig2Page *page, *pages;
65 
66     /* a new page info segment implies the previous page is finished */
67     page = &(ctx->pages[ctx->current_page]);
68     if (page->number != 0 && (page->state == JBIG2_PAGE_NEW || page->state == JBIG2_PAGE_FREE)) {
69         page->state = JBIG2_PAGE_COMPLETE;
70         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unexpected page info segment, marking previous page finished");
71     }
72 
73     /* find a free page */
74     {
75         size_t index, j;
76 
77         index = ctx->current_page;
78         while (ctx->pages[index].state != JBIG2_PAGE_FREE) {
79             index++;
80             if (index >= ctx->max_page_index) {
81                 /* grow the list */
82 
83                 if (ctx->max_page_index == UINT32_MAX) {
84                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "too many pages in jbig2 image");
85                 }
86                 else if (ctx->max_page_index > (UINT32_MAX >> 2)) {
87                     ctx->max_page_index = UINT32_MAX;
88                 }
89 
90                 pages = jbig2_renew(ctx, ctx->pages, Jbig2Page, (ctx->max_page_index <<= 2));
91                 if (pages == NULL) {
92                     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to reallocate pages");
93                 }
94                 ctx->pages = pages;
95                 for (j = index; j < ctx->max_page_index; j++) {
96                     ctx->pages[j].state = JBIG2_PAGE_FREE;
97                     ctx->pages[j].number = 0;
98                     ctx->pages[j].image = NULL;
99                 }
100             }
101         }
102         page = &(ctx->pages[index]);
103         ctx->current_page = index;
104         page->state = JBIG2_PAGE_NEW;
105         page->number = segment->page_association;
106     }
107 
108     /* FIXME: would be nice if we tried to work around this */
109     if (segment->data_length < 19) {
110         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
111     }
112 
113     /* 7.4.8.x */
114     page->width = jbig2_get_uint32(segment_data);
115     page->height = jbig2_get_uint32(segment_data + 4);
116 
117     page->x_resolution = jbig2_get_uint32(segment_data + 8);
118     page->y_resolution = jbig2_get_uint32(segment_data + 12);
119     page->flags = segment_data[16];
120     /* Check for T.88 amendment 3 */
121     if (page->flags & 0x80)
122         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "page segment indicates use of color segments (NYI)");
123 
124     /* 7.4.8.6 */
125     {
126         int16_t striping = jbig2_get_int16(segment_data + 17);
127 
128         if (striping & 0x8000) {
129             page->striped = TRUE;
130             page->stripe_size = striping & 0x7FFF;
131         } else {
132             page->striped = FALSE;
133             page->stripe_size = 0;      /* would page->height be better? */
134         }
135     }
136     if (page->height == 0xFFFFFFFF && page->striped == FALSE) {
137         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "height is unspecified but page is not marked as striped, assuming striped with maximum strip size");
138         page->striped = TRUE;
139         page->stripe_size = 0x7FFF;
140     }
141     page->end_row = 0;
142 
143     if (segment->data_length > 19) {
144         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "extra data in segment");
145     }
146 
147     dump_page_info(ctx, segment, page);
148 
149     /* allocate an appropriate page image buffer */
150     /* 7.4.8.2 */
151     if (page->height == 0xFFFFFFFF) {
152         page->image = jbig2_image_new(ctx, page->width, page->stripe_size);
153     } else {
154         page->image = jbig2_image_new(ctx, page->width, page->height);
155     }
156     if (page->image == NULL) {
157         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate buffer for page image");
158     } else {
159         /* 8.2 (3) fill the page with the default pixel value */
160         jbig2_image_clear(ctx, page->image, (page->flags & 4));
161         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
162                     "allocated %dx%d page image (%d bytes)", page->image->width, page->image->height, page->image->stride * page->image->height);
163     }
164 
165     return 0;
166 }
167 
168 /**
169  * jbig2_end_of_stripe: parse and implement an end of stripe segment
170  **/
171 int
jbig2_end_of_stripe(Jbig2Ctx * ctx,Jbig2Segment * segment,const uint8_t * segment_data)172 jbig2_end_of_stripe(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
173 {
174     Jbig2Page *page = &ctx->pages[ctx->current_page];
175     uint32_t end_row;
176 
177     if (segment->data_length < 4)
178         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
179     end_row = jbig2_get_uint32(segment_data);
180     if (end_row < page->end_row) {
181         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
182                     "end of stripe segment with non-positive end row advance (new end row %d vs current end row %d)", end_row, page->end_row);
183     } else {
184         jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of stripe: advancing end row from %u to %u", page->end_row, end_row);
185     }
186 
187     page->end_row = end_row;
188 
189     return 0;
190 }
191 
192 /**
193  * jbig2_complete_page: complete a page image
194  *
195  * called upon seeing an 'end of page' segment, this routine
196  * marks a page as completed so it can be returned.
197  * compositing will have already happened in the previous
198  * segment handlers.
199  **/
200 int
jbig2_complete_page(Jbig2Ctx * ctx)201 jbig2_complete_page(Jbig2Ctx *ctx)
202 {
203     int code;
204 
205     /* check for unfinished segments */
206     if (ctx->segment_index != ctx->n_segments) {
207         Jbig2Segment *segment = ctx->segments[ctx->segment_index];
208 
209         /* Some versions of Xerox Workcentre generate PDF files
210            with the segment data length field of the last segment
211            set to -1. Try to cope with this here. */
212         if ((segment->data_length & 0xffffffff) == 0xffffffff) {
213             jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "file has an invalid segment data length; trying to decode using the available data");
214             segment->data_length = ctx->buf_wr_ix - ctx->buf_rd_ix;
215             code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
216             ctx->buf_rd_ix += segment->data_length;
217             ctx->segment_index++;
218             if (code < 0) {
219                 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to parse segment");
220             }
221         }
222     }
223 
224     /* ensure image exists before marking page as complete */
225     if (ctx->pages[ctx->current_page].image == NULL) {
226         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "page has no image, cannot be completed");
227     }
228 
229     ctx->pages[ctx->current_page].state = JBIG2_PAGE_COMPLETE;
230     return 0;
231 }
232 
233 /**
234  * jbig2_end_of_page: parse and implement an end of page segment
235  **/
236 int
jbig2_end_of_page(Jbig2Ctx * ctx,Jbig2Segment * segment,const uint8_t * segment_data)237 jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
238 {
239     uint32_t page_number = ctx->pages[ctx->current_page].number;
240     int code;
241 
242     if (segment->page_association != page_number) {
243         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
244                     "end of page marker for page %d doesn't match current page number %d", segment->page_association, page_number);
245     }
246 
247     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number, "end of page %d", page_number);
248 
249     code = jbig2_complete_page(ctx);
250     if (code < 0)
251         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to complete page");
252 
253 #ifdef OUTPUT_PBM
254     code = jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
255     if (code < 0)
256         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to write page image");
257 #endif
258 
259     return 0;
260 }
261 
262 /**
263  * jbig2_add_page_result: composite a decoding result onto a page
264  *
265  * this is called to add the results of segment decode (when it
266  * is an image) to a page image buffer
267  **/
268 int
jbig2_page_add_result(Jbig2Ctx * ctx,Jbig2Page * page,Jbig2Image * image,uint32_t x,uint32_t y,Jbig2ComposeOp op)269 jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image, uint32_t x, uint32_t y, Jbig2ComposeOp op)
270 {
271     int code;
272 
273     if (x > INT32_MAX || y > INT32_MAX)
274         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "unsupported image coordinates");
275 
276     /* ensure image exists first */
277     if (page->image == NULL)
278         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "page info possibly missing, no image defined");
279 
280     /* grow the page to accommodate a new stripe if necessary */
281     if (page->striped && page->height == 0xFFFFFFFF) {
282         uint32_t new_height;
283 
284         if (y > UINT32_MAX - image->height)
285                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "adding image at coordinate would grow page out of bounds");
286         new_height = y + image->height;
287 
288         if (page->image->height < new_height) {
289             Jbig2Image *resized_image = NULL;
290 
291             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "growing page buffer to %u rows to accommodate new stripe", new_height);
292             resized_image = jbig2_image_resize(ctx, page->image, page->image->width, new_height, page->flags & 4);
293             if (resized_image == NULL) {
294                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, JBIG2_UNKNOWN_SEGMENT_NUMBER, "unable to resize image to accommodate new stripe");
295             }
296             page->image = resized_image;
297         }
298     }
299 
300     code = jbig2_image_compose(ctx, page->image, image, x, y, op);
301     if (code < 0)
302         return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to compose image with page");
303 
304     return 0;
305 }
306 
307 /**
308  * jbig2_get_page: return the next available page image buffer
309  *
310  * the client can call this at any time to check if any pages
311  * have been decoded. If so, it returns the first available
312  * one. The client should then call jbig2_release_page() when
313  * it no longer needs to refer to the image buffer.
314  *
315  * since this is a public routine for the library clients, we
316  * return an image structure pointer, even though the function
317  * name refers to a page; the page structure is private.
318  **/
319 Jbig2Image *
jbig2_page_out(Jbig2Ctx * ctx)320 jbig2_page_out(Jbig2Ctx *ctx)
321 {
322     uint32_t index;
323 
324     /* search for a completed page */
325     for (index = 0; index < ctx->max_page_index; index++) {
326         if (ctx->pages[index].state == JBIG2_PAGE_COMPLETE) {
327             Jbig2Image *img = ctx->pages[index].image;
328             uint32_t page_number = ctx->pages[index].number;
329 
330             if (img == NULL) {
331                 jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "page %d returned with no associated image", page_number);
332                 continue;
333             }
334 
335             ctx->pages[index].state = JBIG2_PAGE_RETURNED;
336             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "page %d returned to the client", page_number);
337             return jbig2_image_reference(ctx, img);
338         }
339     }
340 
341     /* no pages available */
342     return NULL;
343 }
344 
345 /**
346  * jbig2_release_page: tell the library a page can be freed
347  **/
348 void
jbig2_release_page(Jbig2Ctx * ctx,Jbig2Image * image)349 jbig2_release_page(Jbig2Ctx *ctx, Jbig2Image *image)
350 {
351     uint32_t index;
352 
353     if (image == NULL)
354         return;
355 
356     /* find the matching page struct and mark it released */
357     for (index = 0; index < ctx->max_page_index; index++) {
358         if (ctx->pages[index].image == image) {
359             jbig2_image_release(ctx, image);
360             ctx->pages[index].state = JBIG2_PAGE_RELEASED;
361             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "page %d released by the client", ctx->pages[index].number);
362             return;
363         }
364     }
365 
366     /* no matching pages */
367     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, JBIG2_UNKNOWN_SEGMENT_NUMBER, "failed to release unknown page");
368 }
369