1 | #include "mupdf/fitz.h" |
2 | |
3 | /* 4bit greyscale Thunderscan decoding */ |
4 | |
5 | typedef struct fz_thunder_s fz_thunder; |
6 | |
7 | struct fz_thunder_s |
8 | { |
9 | fz_stream *chain; |
10 | int lastpixel; |
11 | int run; |
12 | int pixel; |
13 | |
14 | int len; |
15 | unsigned char *buffer; |
16 | }; |
17 | |
18 | static int |
19 | next_thunder(fz_context *ctx, fz_stream *stm, size_t max) |
20 | { |
21 | fz_thunder *state = stm->state; |
22 | unsigned char *p = state->buffer; |
23 | unsigned char *ep; |
24 | int c, v, i, pixels, index; |
25 | |
26 | if (max > (size_t)state->len) |
27 | max = (size_t)state->len; |
28 | |
29 | ep = p + max; |
30 | |
31 | c = 0; |
32 | while (p < ep && c >= 0) |
33 | { |
34 | pixels = 0; |
35 | v = 0; |
36 | |
37 | while (pixels < 2) |
38 | { |
39 | if (state->run > 0) |
40 | { |
41 | v <<= 4; |
42 | v |= state->pixel & 0xf; |
43 | state->pixel >>= 4; |
44 | state->run--; |
45 | pixels++; |
46 | |
47 | if (state->run > 2) |
48 | state->pixel |= ((state->pixel >> 4) & 0xf) << 8; |
49 | } |
50 | else |
51 | { |
52 | c = fz_read_byte(ctx, state->chain); |
53 | if (c < 0) |
54 | break; |
55 | |
56 | switch ((c >> 6) & 0x3) |
57 | { |
58 | case 0x0: /* run of pixels identical to last pixel */ |
59 | state->run = c; |
60 | state->pixel = (state->lastpixel << 8) | (state->lastpixel << 4) | (state->lastpixel << 0); |
61 | break; |
62 | |
63 | case 0x1: /* three pixels with 2bit deltas to last pixel */ |
64 | for (i = 0; i < 3; i++) |
65 | { |
66 | static const int deltas[] = { 0, 1, 0, -1 }; |
67 | index = (c >> (4 - i * 2)) & 0x3; |
68 | if (index == 2) |
69 | continue; |
70 | |
71 | state->lastpixel = (state->lastpixel + deltas[index]) & 0xf; |
72 | state->pixel <<= 4; |
73 | state->pixel |= state->lastpixel; |
74 | state->run++; |
75 | } |
76 | break; |
77 | |
78 | case 0x2: /* two pixels with 3bit deltas to last pixel */ |
79 | for (i = 0; i < 2; i++) |
80 | { |
81 | static const int deltas[] = { 0, 1, 2, 3, 0, -3, -2, -1 }; |
82 | index = (c >> (3 - i * 3)) & 0x7; |
83 | if (index == 4) |
84 | continue; |
85 | |
86 | state->lastpixel = (state->lastpixel + deltas[index]) & 0xf; |
87 | state->pixel <<= 4; |
88 | state->pixel |= state->lastpixel; |
89 | state->run++; |
90 | } |
91 | break; |
92 | |
93 | case 0x3: /* a single raw 4bit pixel */ |
94 | state->run = 1; |
95 | state->pixel = c & 0xf; |
96 | state->lastpixel = state->pixel & 0xf; |
97 | break; |
98 | } |
99 | } |
100 | } |
101 | |
102 | if (pixels) |
103 | *p++ = v; |
104 | } |
105 | |
106 | stm->rp = state->buffer; |
107 | stm->wp = p; |
108 | stm->pos += p - state->buffer; |
109 | |
110 | if (stm->rp != p) |
111 | return *stm->rp++; |
112 | return EOF; |
113 | } |
114 | |
115 | static void |
116 | close_thunder(fz_context *ctx, void *state_) |
117 | { |
118 | fz_thunder *state = (fz_thunder *)state_; |
119 | fz_drop_stream(ctx, state->chain); |
120 | fz_free(ctx, state->buffer); |
121 | fz_free(ctx, state); |
122 | } |
123 | |
124 | fz_stream * |
125 | fz_open_thunder(fz_context *ctx, fz_stream *chain, int w) |
126 | { |
127 | fz_thunder *state = fz_malloc_struct(ctx, fz_thunder); |
128 | fz_try(ctx) |
129 | { |
130 | state->run = 0; |
131 | state->pixel = 0; |
132 | state->lastpixel = 0; |
133 | state->len = w / 2; |
134 | state->buffer = fz_malloc(ctx, state->len); |
135 | state->chain = fz_keep_stream(ctx, chain); |
136 | } |
137 | fz_catch(ctx) |
138 | { |
139 | fz_free(ctx, state); |
140 | fz_rethrow(ctx); |
141 | } |
142 | return fz_new_stream(ctx, state, next_thunder, close_thunder); |
143 | } |
144 | |