comparison fli.c @ 3155:9200edf69d1d

initial commit
author melanson
date Tue, 27 Nov 2001 05:43:03 +0000
parents
children a1205b22a5f4
comparison
equal deleted inserted replaced
3154:b2e24fec97bc 3155:9200edf69d1d
1 /*
2 FLI Decoder for MPlayer
3
4 (C) 2001 Mike Melanson
5 */
6
7 #define LE_16(x) *(unsigned short *)(x)
8 #define LE_32(x) *(unsigned int *)(x)
9
10 #define FLI_256_COLOR 4
11 #define FLI_DELTA 7
12 #define FLI_COLOR 11
13 #define FLI_LC 12
14 #define FLI_BLACK 13
15 #define FLI_BRUN 15
16 #define FLI_COPY 16
17 #define FLI_MINI 18
18
19 // 256 RGB entries; 25% of these bytes will be unused, but it's faster
20 // to index 4-byte entries
21 static unsigned char palette[256 * 4];
22
23 void AVI_Decode_Fli(
24 unsigned char *encoded,
25 int encoded_size,
26 unsigned char *decoded,
27 int width,
28 int height,
29 int bytes_per_pixel)
30 {
31 int stream_ptr = 0;
32 int pixel_ptr;
33 int palette_ptr1;
34 int palette_ptr2;
35
36 unsigned int frame_size;
37 int num_chunks;
38
39 unsigned int chunk_size;
40 int chunk_type;
41
42 int i, j;
43
44 int color_packets;
45 int color_changes;
46 int color_scale;
47
48 int lines;
49 int compressed_lines;
50 int starting_line;
51 signed short line_packets;
52 int y_ptr;
53 int line_inc;
54 signed char byte_run;
55
56 frame_size = LE_32(&encoded[stream_ptr]);
57 stream_ptr += 6; // skip the magic number
58 num_chunks = LE_16(&encoded[stream_ptr]);
59 stream_ptr += 10; // skip padding
60
61 // iterate through the chunks
62 frame_size -= 16;
63 while ((frame_size > 0) && (num_chunks > 0))
64 {
65 chunk_size = LE_32(&encoded[stream_ptr]);
66 stream_ptr += 4;
67 chunk_type = LE_16(&encoded[stream_ptr]);
68 stream_ptr += 2;
69
70 switch (chunk_type)
71 {
72 case FLI_256_COLOR:
73 case FLI_COLOR:
74 if (chunk_type == FLI_COLOR)
75 color_scale = 4;
76 else
77 color_scale = 1;
78 // set up the palette
79 color_packets = LE_16(&encoded[stream_ptr]);
80 stream_ptr += 2;
81 palette_ptr1 = 0;
82 for (i = 0; i < color_packets; i++)
83 {
84 // first byte is how many colors to skip
85 palette_ptr1 += (encoded[stream_ptr++] * 4);
86 // next byte indicates how many entries to change
87 color_changes = encoded[stream_ptr++];
88 // if there are 0 color changes, there are actually 256
89 if (color_changes == 0)
90 color_changes = 256;
91 for (j = 0; j < color_changes; j++)
92 {
93 palette[palette_ptr1++] = encoded[stream_ptr + 2] * color_scale;
94 palette[palette_ptr1++] = encoded[stream_ptr + 1] * color_scale;
95 palette[palette_ptr1++] = encoded[stream_ptr + 0] * color_scale;
96 palette_ptr1++;
97 stream_ptr += 3;
98 }
99 }
100 break;
101
102 case FLI_DELTA:
103 line_inc = width * bytes_per_pixel;
104 y_ptr = 0;
105 compressed_lines = LE_16(&encoded[stream_ptr]);
106 stream_ptr += 2;
107 while (compressed_lines > 0)
108 {
109 line_packets = LE_16(&encoded[stream_ptr]);
110 stream_ptr += 2;
111 if (line_packets < 0)
112 {
113 line_packets = -line_packets;
114 y_ptr += (line_packets * line_inc);
115 }
116 else
117 {
118 pixel_ptr = y_ptr;
119 for (i = 0; i < line_packets; i++)
120 {
121 // account for the skip bytes
122 pixel_ptr += encoded[stream_ptr++] * 3;
123 byte_run = encoded[stream_ptr++];
124 if (byte_run < 0)
125 {
126 byte_run = -byte_run;
127 palette_ptr1 = encoded[stream_ptr++] * 4;
128 palette_ptr2 = encoded[stream_ptr++] * 4;
129 for (j = 0; j < byte_run; j++)
130 {
131 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
132 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
133 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
134
135 decoded[pixel_ptr++] = palette[palette_ptr2 + 0];
136 decoded[pixel_ptr++] = palette[palette_ptr2 + 1];
137 decoded[pixel_ptr++] = palette[palette_ptr2 + 2];
138 }
139 }
140 else
141 {
142 for (j = 0; j < byte_run * 2; j++)
143 {
144 palette_ptr1 = encoded[stream_ptr++] * 4;
145 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
146 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
147 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
148 }
149 }
150 }
151 y_ptr += line_inc;
152 compressed_lines--;
153 }
154 }
155 break;
156
157 case FLI_LC:
158 // line compressed
159 line_inc = width * bytes_per_pixel;
160 starting_line = LE_16(&encoded[stream_ptr]);
161 stream_ptr += 2;
162 y_ptr = starting_line * line_inc;
163
164 compressed_lines = LE_16(&encoded[stream_ptr]);
165 stream_ptr += 2;
166 while (compressed_lines > 0)
167 {
168 pixel_ptr = y_ptr;
169 line_packets = encoded[stream_ptr++];
170 if (line_packets > 0)
171 {
172 for (i = 0; i < line_packets; i++)
173 {
174 // account for the skip bytes
175 pixel_ptr += encoded[stream_ptr++] * 3;
176 byte_run = encoded[stream_ptr++];
177 if (byte_run > 0)
178 {
179 for (j = 0; j < byte_run; j++)
180 {
181 palette_ptr1 = encoded[stream_ptr++] * 4;
182 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
183 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
184 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
185 }
186 }
187 else
188 {
189 byte_run = -byte_run;
190 palette_ptr1 = encoded[stream_ptr++] * 4;
191 for (j = 0; j < byte_run; j++)
192 {
193 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
194 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
195 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
196 }
197 }
198 }
199 }
200
201 y_ptr += line_inc;
202 compressed_lines--;
203 }
204 break;
205
206 case FLI_BLACK:
207 // set the whole frame to color 0 (which is usually black)
208 for (pixel_ptr = 0; pixel_ptr < (width * height * 3); pixel_ptr++)
209 {
210 decoded[pixel_ptr++] = palette[0];
211 decoded[pixel_ptr++] = palette[1];
212 decoded[pixel_ptr++] = palette[2];
213 }
214 break;
215
216 case FLI_BRUN:
217 // byte run compression
218 line_inc = width * bytes_per_pixel;
219 y_ptr = 0;
220 for (lines = 0; lines < height; lines++)
221 {
222 pixel_ptr = y_ptr;
223 line_packets = encoded[stream_ptr++];
224 for (i = 0; i < line_packets; i++)
225 {
226 byte_run = encoded[stream_ptr++];
227 if (byte_run > 0)
228 {
229 palette_ptr1 = encoded[stream_ptr++] * 4;
230 for (j = 0; j < byte_run; j++)
231 {
232 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
233 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
234 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
235 }
236 }
237 else // copy bytes if byte_run < 0
238 {
239 byte_run = -byte_run;
240 for (j = 0; j < byte_run; j++)
241 {
242 palette_ptr1 = encoded[stream_ptr++] * 4;
243 decoded[pixel_ptr++] = palette[palette_ptr1 + 0];
244 decoded[pixel_ptr++] = palette[palette_ptr1 + 1];
245 decoded[pixel_ptr++] = palette[palette_ptr1 + 2];
246 }
247 }
248 }
249
250 y_ptr += line_inc;
251 }
252 break;
253
254 case FLI_COPY:
255 // currently unimplemented
256 printf ("FLI_COPY chunk (currently unimplemented)\n");
257 stream_ptr += chunk_size - 6;
258 break;
259
260 case FLI_MINI:
261 // sort of a thumbnail? disregard this chunk...
262 stream_ptr += chunk_size - 6;
263 break;
264
265 default:
266 printf ("FLI: Unrecognized chunk type: %d\n", chunk_type);
267 break;
268 }
269
270 frame_size -= chunk_size;
271 num_chunks--;
272 }
273 }