Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8436 maxcodehac 1
/*
2
    jbig2dec
3
 
4
    Copyright (C) 2001-2005 Artifex Software, Inc.
5
 
6
    This software is distributed under license and may not
7
    be copied, modified or distributed except as expressly
8
    authorized under the terms of the license contained in
9
    the file LICENSE in this distribution.
10
 
11
    For further licensing information refer to http://artifex.com/ or
12
    contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
13
    San Rafael, CA  94903, U.S.A., +1(415)492-9861.
14
*/
15
 
16
#ifdef HAVE_CONFIG_H
17
#include "config.h"
18
#endif
19
#include "os_types.h"
20
 
21
#include 
22
 
23
#include "jbig2.h"
24
#include "jbig2_priv.h"
25
 
26
#ifdef OUTPUT_PBM
27
#include 
28
#include "jbig2_image.h"
29
#endif
30
 
31
/* dump the page struct info */
32
static void
33
dump_page_info(Jbig2Ctx *ctx, Jbig2Segment *segment, Jbig2Page *page)
34
{
35
    if (page->x_resolution == 0) {
36
        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
37
            "page %d image is %dx%d (unknown res)", page->number,
38
            page->width, page->height);
39
    } else if (page->x_resolution == page->y_resolution) {
40
        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
41
            "page %d image is %dx%d (%d ppm)", page->number,
42
            page->width, page->height,
43
            page->x_resolution);
44
    } else {
45
        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
46
            "page %d image is %dx%d (%dx%d ppm)", page->number,
47
            page->width, page->height,
48
            page->x_resolution, page->y_resolution);
49
    }
50
    if (page->striped) {
51
        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
52
            "\tmaximum stripe size: %d", page->stripe_size);
53
    }
54
}
55
 
56
/**
57
 * jbig2_page_info: parse page info segment
58
 *
59
 * Parse the page info segment data and fill out a corresponding
60
 * Jbig2Page struct and ready it for subsequent rendered data,
61
 * including allocating an image buffer for the page (or the first stripe)
62
 **/
63
int
64
jbig2_page_info (Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
65
{
66
    Jbig2Page *page;
67
 
68
    /* a new page info segment implies the previous page is finished */
69
    page = &(ctx->pages[ctx->current_page]);
70
    if ((page->number != 0) &&
71
            ((page->state == JBIG2_PAGE_NEW) || (page->state == JBIG2_PAGE_FREE))) {
72
        page->state = JBIG2_PAGE_COMPLETE;
73
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
74
            "unexpected page info segment, marking previous page finished");
75
    }
76
 
77
    /* find a free page */
78
    {
79
        int index, j;
80
        index = ctx->current_page;
81
        while (ctx->pages[index].state != JBIG2_PAGE_FREE) {
82
            index++;
83
            if (index >= ctx->max_page_index) {
84
                /* grow the list */
85
		ctx->pages = jbig2_realloc(ctx->allocator, ctx->pages,
86
			(ctx->max_page_index <<= 2) * sizeof(Jbig2Page));
87
                for (j=index; j < ctx->max_page_index; j++) {
88
                    ctx->pages[j].state = JBIG2_PAGE_FREE;
89
                    ctx->pages[j].number = 0;
90
                    ctx->pages[j].image = NULL;
91
 
92
                }
93
            }
94
        }
95
        page = &(ctx->pages[index]);
96
        ctx->current_page = index;
97
        page->state = JBIG2_PAGE_NEW;
98
        page->number = segment->page_association;
99
    }
100
 
101
    /* FIXME: would be nice if we tried to work around this */
102
    if (segment->data_length < 19) {
103
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
104
            "segment too short");
105
    }
106
 
107
    /* 7.4.8.x */
108
    page->width = jbig2_get_int32(segment_data);
109
    page->height = jbig2_get_int32(segment_data + 4);
110
 
111
    page->x_resolution = jbig2_get_int32(segment_data + 8);
112
    page->y_resolution = jbig2_get_int32(segment_data + 12);
113
    page->flags = segment_data[16];
114
 
115
    /* 7.4.8.6 */
116
    {
117
        int16_t striping = jbig2_get_int16(segment_data +17);
118
        if (striping & 0x8000) {
119
            page->striped = TRUE;
120
            page->stripe_size = striping & 0x7FFF;
121
        } else {
122
            page->striped = FALSE;
123
            page->stripe_size = 0;	/* would page->height be better? */
124
        }
125
    }
126
    if (page->height == 0xFFFFFFFF && page->striped == FALSE) {
127
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
128
            "height is unspecified but page is not markes as striped");
129
        page->striped = TRUE;
130
    }
131
    page->end_row = 0;
132
 
133
    if (segment->data_length > 19) {
134
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
135
            "extra data in segment");
136
    }
137
 
138
    dump_page_info(ctx, segment, page);
139
 
140
    /* allocate an approprate page image buffer */
141
    /* 7.4.8.2 */
142
    if (page->height == 0xFFFFFFFF) {
143
        page->image = jbig2_image_new(ctx, page->width, page->stripe_size);
144
    } else {
145
        page->image = jbig2_image_new(ctx, page->width, page->height);
146
    }
147
    if (page->image == NULL) {
148
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
149
            "failed to allocate buffer for page image");
150
    } else {
151
	/* 8.2 (3) fill the page with the default pixel value */
152
	jbig2_image_clear(ctx, page->image, (page->flags & 4));
153
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
154
            "allocated %dx%d page image (%d bytes)",
155
            page->image->width, page->image->height,
156
            page->image->stride*page->image->height);
157
    }
158
 
159
    return 0;
160
}
161
 
162
/**
163
 * jbig2_end_of_stripe: parse and implement an end of stripe segment
164
 **/
165
int
166
jbig2_end_of_stripe(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
167
{
168
    Jbig2Page page = ctx->pages[ctx->current_page];
169
    int end_row;
170
 
171
    end_row = jbig2_get_int32(segment_data);
172
    if (end_row < page.end_row) {
173
	jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
174
	    "end of stripe segment with non-positive end row advance"
175
	    " (new end row %d vs current end row %d)",
176
	    end_row, page.end_row);
177
    } else {
178
	jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
179
	    "end of stripe: advancing end row to %d", end_row);
180
    }
181
 
182
    page.end_row = end_row;
183
 
184
    return 0;
185
}
186
 
187
/**
188
 * jbig2_complete_page: complete a page image
189
 *
190
 * called upon seeing an 'end of page' segment, this routine
191
 * marks a page as completed so it can be returned.
192
 * compositing will have already happened in the previous
193
 * segment handlers.
194
 **/
195
int
196
jbig2_complete_page (Jbig2Ctx *ctx)
197
{
198
 
199
    /* check for unfinished segments */
200
    if (ctx->segment_index != ctx->n_segments) {
201
      Jbig2Segment *segment = ctx->segments[ctx->segment_index];
202
      int code = 0;
203
      /* Some versions of Xerox Workcentre generate PDF files
204
         with the segment data length field of the last segment
205
         set to -1. Try to cope with this here. */
206
      if ((segment->data_length & 0xffffffff) == 0xffffffff) {
207
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
208
          "File has an invalid segment data length!"
209
          " Trying to decode using the available data.");
210
        segment->data_length = ctx->buf_wr_ix - ctx->buf_rd_ix;
211
        code = jbig2_parse_segment(ctx, segment, ctx->buf + ctx->buf_rd_ix);
212
        ctx->buf_rd_ix += segment->data_length;
213
        ctx->segment_index++;
214
      }
215
    }
216
    ctx->pages[ctx->current_page].state = JBIG2_PAGE_COMPLETE;
217
 
218
    return 0;
219
}
220
 
221
/**
222
 * jbig2_end_of_page: parse and implement an end of page segment
223
 **/
224
int
225
jbig2_end_of_page(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
226
{
227
    uint32_t page_number = ctx->pages[ctx->current_page].number;
228
 
229
    if (segment->page_association != page_number) {
230
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
231
            "end of page marker for page %d doesn't match current page number %d",
232
            segment->page_association, page_number);
233
    }
234
 
235
    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
236
        "end of page %d", page_number);
237
 
238
    jbig2_complete_page(ctx);
239
 
240
#ifdef OUTPUT_PBM
241
    jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
242
#endif
243
 
244
    return 0;
245
}
246
 
247
/**
248
 * jbig2_add_page_result: composite a decoding result onto a page
249
 *
250
 * this is called to add the results of segment decode (when it
251
 * is an image) to a page image buffer
252
 **/
253
int
254
jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image,
255
		      int x, int y, Jbig2ComposeOp op)
256
{
257
    /* grow the page to accomodate a new stripe if necessary */
258
    if (page->striped) {
259
	int new_height = y + image->height + page->end_row;
260
	if (page->image->height < new_height) {
261
	    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
262
		"growing page buffer to %d rows "
263
		"to accomodate new stripe", new_height);
264
	    jbig2_image_resize(ctx, page->image,
265
		page->image->width, new_height);
266
	}
267
    }
268
 
269
    jbig2_image_compose(ctx, page->image, image,
270
                        x, y + page->end_row, JBIG2_COMPOSE_OR);
271
 
272
    return 0;
273
}
274
 
275
/**
276
 * jbig2_get_page: return the next available page image buffer
277
 *
278
 * the client can call this at any time to check if any pages
279
 * have been decoded. If so, it returns the first available
280
 * one. The client should then call jbig2_release_page() when
281
 * it no longer needs to refer to the image buffer.
282
 *
283
 * since this is a public routine for the library clients, we
284
 * return an image structure pointer, even though the function
285
 * name refers to a page; the page structure is private.
286
 **/
287
Jbig2Image *jbig2_page_out(Jbig2Ctx *ctx)
288
{
289
    int index;
290
 
291
    /* search for a completed page */
292
    for (index=0; index < ctx->max_page_index; index++) {
293
        if (ctx->pages[index].state == JBIG2_PAGE_COMPLETE) {
294
            ctx->pages[index].state = JBIG2_PAGE_RETURNED;
295
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
296
                "page %d returned to the client", ctx->pages[index].number);
297
            return jbig2_image_clone(ctx, ctx->pages[index].image);
298
        }
299
    }
300
 
301
    /* no pages available */
302
    return NULL;
303
}
304
 
305
/**
306
 * jbig2_release_page: tell the library a page can be freed
307
 **/
308
int jbig2_release_page(Jbig2Ctx *ctx, Jbig2Image *image)
309
{
310
    int index;
311
 
312
    /* find the matching page struct and mark it released */
313
    for (index = 0; index < ctx->max_page_index; index++) {
314
        if (ctx->pages[index].image == image) {
315
            jbig2_image_release(ctx, image);
316
            ctx->pages[index].state = JBIG2_PAGE_RELEASED;
317
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
318
                "page %d released by the client", ctx->pages[index].number);
319
            return 0;
320
        }
321
    }
322
 
323
    /* no matching pages */
324
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
325
        "jbig2_release_page called on unknown page");
326
    return 1;
327
}