| 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 | |