1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#include "fitz-internal.h"
#include <jbig2.h>
typedef struct fz_jbig2d_s fz_jbig2d;
struct fz_jbig2d_s
{
fz_stream *chain;
Jbig2Ctx *ctx;
Jbig2GlobalCtx *gctx;
Jbig2Image *page;
int idx;
};
static void
close_jbig2d(fz_context *ctx, void *state_)
{
fz_jbig2d *state = (fz_jbig2d *)state_;
if (state->page)
jbig2_release_page(state->ctx, state->page);
if (state->gctx)
jbig2_global_ctx_free(state->gctx);
jbig2_ctx_free(state->ctx);
fz_close(state->chain);
fz_free(ctx, state);
}
static int
read_jbig2d(fz_stream *stm, unsigned char *buf, int len)
{
fz_jbig2d *state = stm->state;
unsigned char tmp[4096];
unsigned char *p = buf;
unsigned char *ep = buf + len;
unsigned char *s;
int x, w, n;
if (!state->page)
{
while (1)
{
n = fz_read(state->chain, tmp, sizeof tmp);
if (n == 0)
break;
jbig2_data_in(state->ctx, tmp, n);
}
jbig2_complete_page(state->ctx);
state->page = jbig2_page_out(state->ctx);
if (!state->page)
fz_throw(stm->ctx, "jbig2_page_out failed");
}
s = state->page->data;
w = state->page->height * state->page->stride;
x = state->idx;
while (p < ep && x < w)
*p++ = s[x++] ^ 0xff;
state->idx = x;
return p - buf;
}
fz_stream *
fz_open_jbig2d(fz_stream *chain, fz_buffer *globals)
{
fz_jbig2d *state = NULL;
fz_context *ctx = chain->ctx;
fz_var(state);
fz_try(ctx)
{
state = fz_malloc_struct(chain->ctx, fz_jbig2d);
state->ctx = NULL;
state->gctx = NULL;
state->chain = chain;
state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, NULL, NULL);
state->page = NULL;
state->idx = 0;
if (globals)
{
jbig2_data_in(state->ctx, globals->data, globals->len);
state->gctx = jbig2_make_global_ctx(state->ctx);
state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, state->gctx, NULL, NULL);
}
}
fz_catch(ctx)
{
if (state)
{
if (state->gctx)
jbig2_global_ctx_free(state->gctx);
if (state->ctx)
jbig2_ctx_free(state->ctx);
}
fz_drop_buffer(ctx, globals);
fz_free(ctx, state);
fz_close(chain);
fz_rethrow(ctx);
}
fz_drop_buffer(ctx, globals);
return fz_new_stream(ctx, state, read_jbig2d, close_jbig2d);
}
|