Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/ipe_artfile_utils/trunk/ipe16_lzw_decoder.c
Revision: 2
Committed: Thu Nov 8 11:19:36 2018 UTC (16 months, 2 weeks ago) by daniel-marschall
Content type: text/x-csrc
File size: 5419 byte(s)
Log Message:
Initial release to SVN

File Contents

# Content
1 /**
2 * LZW Decoder for Imagination Pilots Entertainment 16-bit games (IPE16)
3 * - Blown Away - The Interactive Game by Imagination Pilots (BA)
4 * - Panic in the Park - The Interactive Game by Imagination Pilots (PiP)
5 * - Where's Waldo? At the Circus (Waldo1)
6 * ART file packer and unpacker by Daniel Marschall, ViaThinkSoft (C) 2014-2018
7 * Revision: 2018-02-15
8 *
9 * The code is based on "Cross platform GIF source code" (c) L. Patrick
10 * http://www.cs.usyd.edu.au/~graphapp/package/src/libgif/gif.c
11 * It was simplified and modified to encode IPE16-LZW instead of GIF-LZW.
12 * The game uses exactly the compressed stream as defined in the GIF standard,
13 * but the compressed stream is not divided into chunks.
14 **/
15
16 #include "ipe16_lzw_decoder.h"
17 #include "utils.h"
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdbool.h>
22
23 Ipe16LZWDecoder* new_ipe16lzw_decoder(void) {
24 return (Ipe16LZWDecoder*)app_zero_alloc(sizeof(Ipe16LZWDecoder));
25 }
26
27 void del_ipe16lzw_decoder(Ipe16LZWDecoder* decoder) {
28 free(decoder);
29 }
30
31 void ipe16lzw_init_decoder(Ipe16LZWDecoder* decoder) {
32 decoder->running_code = FIRST_CODE;
33 decoder->running_bits = LZ_MIN_BITS;
34 decoder->max_code_plus_one = 1 << decoder->running_bits;
35 decoder->shift_state = 0;
36 decoder->shift_data = 0;
37
38 int i;
39 for (i = 0; i <= LZ_MAX_CODE; i++) {
40 decoder->prefix[i] = NO_SUCH_CODE;
41 }
42 }
43
44 int ipe16lzw_read_code(FILE* inFile, Ipe16LZWDecoder* decoder) {
45 int code;
46 unsigned char next_byte;
47 static int code_masks[] = {
48 0x0000, 0x0001, 0x0003, 0x0007,
49 0x000f, 0x001f, 0x003f, 0x007f,
50 0x00ff, 0x01ff, 0x03ff, 0x07ff,
51 0x0fff
52 };
53
54 while (decoder->shift_state < decoder->running_bits) {
55 next_byte = read_byte(inFile);
56 decoder->shift_data |=
57 ((unsigned long) next_byte) << decoder->shift_state;
58 decoder->shift_state += 8;
59 }
60
61 code = decoder->shift_data & code_masks[decoder->running_bits];
62
63 decoder->shift_data >>= decoder->running_bits;
64 decoder->shift_state -= decoder->running_bits;
65
66 if (++decoder->running_code > decoder->max_code_plus_one
67 && decoder->running_bits < LZ_MAX_BITS) {
68 decoder->max_code_plus_one <<= 1;
69 decoder->running_bits++;
70 }
71
72 return code;
73 }
74
75 static int ipe16lzw_trace_prefix(unsigned int* prefix, int code, int clear_code) {
76 int i = 0;
77
78 while (code > clear_code && i++ <= LZ_MAX_CODE) {
79 code = prefix[code];
80 }
81 return code;
82 }
83
84 // We don't do unsigned, because we want to have <0 as error result
85 /*unsigned*/ int ipe16lzw_decode(FILE* inFile, Ipe16LZWDecoder* decoder, unsigned char* output, int outputLength) {
86 int i = 0, j;
87 int current_code;
88 int current_prefix;
89 int stack_ptr = 0;
90 int prev_code = NO_SUCH_CODE;
91 unsigned char* stack;
92 unsigned int* prefix;
93 unsigned int* suffix;
94 unsigned int bytes_written = 0;
95
96 ipe16lzw_init_decoder(decoder);
97
98 prefix = decoder->prefix;
99 suffix = decoder->suffix;
100 stack = decoder->stack;
101
102 /* Pop the stack */
103 while (stack_ptr != 0 && i < outputLength) {
104 output[i++] = stack[--stack_ptr];
105 //if (i > bytes_written) bytes_written = i;
106 ++bytes_written;
107 }
108
109 while (i < outputLength) {
110 current_code = ipe16lzw_read_code(inFile, decoder);
111
112 if (current_code == END_CODE) {
113 if (i != outputLength - 1) // || decoder->pixel_count != 0
114 return -1; /* unexpected eof */
115 i++;
116 } else if (current_code == CLEAR_CODE) {
117 for (j = 0; j <= LZ_MAX_CODE; j++) {
118 prefix[j] = NO_SUCH_CODE;
119 }
120 decoder->running_code = FIRST_CODE;
121 decoder->running_bits = LZ_MIN_BITS;
122 decoder->max_code_plus_one = 1 << decoder->running_bits;
123 prev_code = NO_SUCH_CODE;
124 } else {
125 if (current_code < CLEAR_CODE) {
126 output[i++] = current_code;
127 //if (i > bytes_written) bytes_written = i;
128 ++bytes_written;
129 } else {
130 if ((current_code < 0) || (current_code > LZ_MAX_CODE))
131 return -2; /* image defect */
132 if (prefix[current_code] == NO_SUCH_CODE) {
133 if (current_code == decoder->running_code - 2) {
134 current_prefix = prev_code;
135 suffix[decoder->running_code - 2]
136 = stack[stack_ptr++]
137 = ipe16lzw_trace_prefix(prefix, prev_code, CLEAR_CODE);
138 } else {
139 return -3; /* image defect */
140 }
141 } else {
142 current_prefix = current_code;
143 }
144 j = 0;
145 while (j++ <= LZ_MAX_CODE && current_prefix > CLEAR_CODE && current_prefix <= LZ_MAX_CODE) {
146 stack[stack_ptr++] = suffix[current_prefix];
147 current_prefix = prefix[current_prefix];
148 }
149 if (j >= LZ_MAX_CODE || current_prefix > LZ_MAX_CODE)
150 return -4; /* image defect */
151
152 stack[stack_ptr++] = current_prefix;
153
154 while (stack_ptr != 0 && i < outputLength) {
155 output[i++] = stack[--stack_ptr];
156 //if (i > bytes_written) bytes_written = i;
157 ++bytes_written;
158 }
159 }
160 if (prev_code != NO_SUCH_CODE) {
161 if ((decoder->running_code < 2) ||
162 (decoder->running_code > LZ_MAX_CODE+2))
163 return -5; /* image defect */
164 prefix[decoder->running_code - 2] = prev_code;
165
166 if (current_code == decoder->running_code - 2) {
167 suffix[decoder->running_code - 2]
168 = ipe16lzw_trace_prefix(prefix, prev_code, CLEAR_CODE);
169 } else {
170 suffix[decoder->running_code - 2]
171 = ipe16lzw_trace_prefix(prefix, current_code, CLEAR_CODE);
172 }
173 }
174 prev_code = current_code;
175 }
176 }
177
178 return bytes_written;
179 }

Properties

Name Value
svn:mime-type text/x-csrc