Isle
Loading...
Searching...
No Matches
flic.cpp
Go to the documentation of this file.
1#include "flic.h"
2
6
7void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, short p_column, short p_row, byte p_pixel);
8void WritePixels(
9 LPBITMAPINFOHEADER p_bitmapHeader,
10 BYTE* p_pixelData,
11 short p_column,
12 short p_row,
13 BYTE* p_data,
14 short p_count
15);
16int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count);
17void WritePixelRun(
18 LPBITMAPINFOHEADER p_bitmapHeader,
19 BYTE* p_pixelData,
20 short p_column,
21 short p_row,
22 byte p_pixel,
23 short p_count
24);
26 LPBITMAPINFOHEADER p_bitmapHeader,
27 BYTE* p_pixelData,
28 short p_column,
29 short p_row,
30 WORD p_pixel,
31 short p_count
32);
33short DecodeChunks(
34 LPBITMAPINFOHEADER p_bitmapHeader,
35 BYTE* p_pixelData,
36 FLIC_HEADER* p_flcHeader,
37 FLIC_FRAME* p_flcFrame,
38 BYTE* p_flcSubchunks,
39 BYTE* p_decodedColorMap
40);
41void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data);
42void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data);
43void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short p_index, short p_count);
44void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data);
45void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
46void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
47void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
48void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
49void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
50
51// FUNCTION: LEGO1 0x100bd530
52// FUNCTION: BETA10 0x1013dd80
53void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, short p_column, short p_row, byte p_pixel)
54{
55 if (p_column < 0 || p_row < 0 || p_column >= p_bitmapHeader->biWidth || p_row >= p_bitmapHeader->biHeight) {
56 return;
57 }
58
59 *(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel;
60}
61
62// FUNCTION: LEGO1 0x100bd580
63// FUNCTION: BETA10 0x1013ddef
65 LPBITMAPINFOHEADER p_bitmapHeader,
66 BYTE* p_pixelData,
67 short p_column,
68 short p_row,
69 BYTE* p_data,
70 short p_count
71)
72{
73 // ClampLine could modify p_column. Save the original value.
74 short zcol = p_column;
75
76 if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) {
77 return;
78 }
79
80 short offset = p_column - zcol;
81 if (offset) {
82 p_data += offset;
83 }
84
85 BYTE* dest = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData;
86 memcpy(dest, p_data, p_count);
87}
88
89// FUNCTION: LEGO1 0x100bd600
90// FUNCTION: BETA10 0x1013de84
91int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count)
92{
93 short column = p_column;
94 short a_row = p_row;
95 short f_count = p_count;
96 short end = column + f_count;
97
98 if (a_row < 0 || p_bitmapHeader->biHeight <= a_row || end < 0 || p_bitmapHeader->biWidth <= column) {
99 return 0;
100 }
101
102 if (column < 0) {
103 f_count += column;
104 p_count = f_count;
105 p_column = 0;
106 }
107
108 if (p_bitmapHeader->biWidth < end) {
109 f_count -= end - (short) p_bitmapHeader->biWidth;
110 p_count = f_count;
111 }
112
113 if (f_count < 0) {
114 return 0;
115 }
116
117 return 1;
118}
119
120// FUNCTION: LEGO1 0x100bd680
121// FUNCTION: BETA10 0x1013df77
123 LPBITMAPINFOHEADER p_bitmapHeader,
124 BYTE* p_pixelData,
125 short p_column,
126 short p_row,
127 byte p_pixel,
128 short p_count
129)
130{
131 if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) {
132 return;
133 }
134
135 BYTE* dst = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData;
136
137 while (--p_count >= 0) {
138 *dst++ = p_pixel;
139 }
140}
141
142// FUNCTION: LEGO1 0x100bd6e0
143// FUNCTION: BETA10 0x1013dfee
145 LPBITMAPINFOHEADER p_bitmapHeader,
146 BYTE* p_pixelData,
147 short p_column,
148 short p_row,
149 WORD p_pixel,
150 short p_count
151)
152{
153 p_count <<= 1;
154
155 if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) {
156 return;
157 }
158
159 short is_odd = p_count & 1;
160 p_count >>= 1;
161
162 WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData);
163 while (--p_count >= 0) {
164 *dst++ = p_pixel;
165 }
166
167 if (is_odd) {
168 BYTE* dst_byte = (BYTE*) dst;
169 *dst_byte = p_pixel;
170 }
171}
172
173// FUNCTION: LEGO1 0x100bd760
174// FUNCTION: BETA10 0x1013e097
176 LPBITMAPINFOHEADER p_bitmapHeader,
177 BYTE* p_pixelData,
178 FLIC_HEADER* p_flcHeader,
179 FLIC_FRAME* p_flcFrame,
180 BYTE* p_flcSubchunks,
181 BYTE* p_decodedColorMap
182)
183{
184 *p_decodedColorMap = FALSE;
185
186 for (short subchunk = 0; subchunk < (short) p_flcFrame->chunks; subchunk++) {
187 FLIC_CHUNK* chunk = (FLIC_CHUNK*) p_flcSubchunks;
188 p_flcSubchunks += chunk->size;
189
190 switch (chunk->type) {
192 DecodeColors256(p_bitmapHeader, (BYTE*) (chunk + 1));
193 *p_decodedColorMap = TRUE;
194 break;
195 case FLI_CHUNK_SS2:
196 DecodeSS2(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
197 break;
199 DecodeColors64(p_bitmapHeader, (BYTE*) (chunk + 1));
200 *p_decodedColorMap = TRUE;
201 break;
202 case FLI_CHUNK_LC:
203 DecodeLC(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
204 break;
205 case FLI_CHUNK_BLACK:
206 DecodeBlack(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
207 break;
208 case FLI_CHUNK_BRUN:
209 DecodeBrun(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
210 break;
211 case FLI_CHUNK_COPY:
212 DecodeCopy(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
213 break;
214 default:
215 break;
216 }
217 }
218
219 return 0;
220}
221
222// FUNCTION: LEGO1 0x100bd880
223// FUNCTION: BETA10 0x1013e22c
224void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
225{
226 DecodeColorPackets(p_bitmapHeader, p_data);
227}
228
229// FUNCTION: LEGO1 0x100bd8a0
230// FUNCTION: BETA10 0x1013e24c
231void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
232{
233 short colorIndex = 0;
234 BYTE* colors = p_data;
235 short* pPackets = (short*) colors;
236 short packets = *pPackets;
237 colors += 2;
238
239 while (--packets >= 0) {
240 colorIndex += *colors++;
241 short colorCount = *colors++;
242
243 if (colorCount == 0) {
244 colorCount = 256;
245 }
246
247 DecodeColorPacket(p_bitmapHeader, colors, colorIndex, colorCount);
248 colors += colorCount * 3;
249 colorIndex += colorCount;
250 }
251}
252
253// FUNCTION: LEGO1 0x100bd8f0
254// FUNCTION: BETA10 0x1013e2f8
255void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short index, short p_count)
256{
257 RGBQUAD* palette = (RGBQUAD*) ((BYTE*) p_bitmapHeader + p_bitmapHeader->biSize) + index;
258
259 while (p_count--) {
260 palette->rgbRed = p_data[0];
261 palette->rgbGreen = p_data[1];
262 palette->rgbBlue = p_data[2];
263
264 palette++;
265 p_data += 3;
266 }
267}
268
269// FUNCTION: LEGO1 0x100bd940
270// FUNCTION: BETA10 0x1013e364
271void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
272{
273 DecodeColorPackets(p_bitmapHeader, p_data);
274}
275
276// FUNCTION: LEGO1 0x100bd960
277// FUNCTION: BETA10 0x1013e384
278void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
279{
280 short width = p_flcHeader->width;
281 short height = p_flcHeader->height;
282 BYTE* data = p_data;
283 BYTE* offset = ((p_bitmapHeader->biWidth + 3) & -4) * (height - 1) + p_pixelData;
284
285 short line = height;
286 short width2 = width;
287
288 while (--line >= 0) {
289 short column = 0;
290 data++;
291 char count = 0;
292 while ((column += count) < width2) {
293 count = *data++;
294
295 short i;
296 if (count >= 0) {
297 for (i = 0; i < count; i++) {
298 *offset++ = *data;
299 }
300
301 data++;
302 }
303 else {
304 count = -count;
305 for (i = 0; i < count; i++) {
306 *offset++ = *data++;
307 }
308 }
309 }
310
311 offset -= (((p_bitmapHeader->biWidth + 3) & -4) + width);
312 }
313}
314
315// FUNCTION: LEGO1 0x100bda10
316// FUNCTION: BETA10 0x1013e4ca
317void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
318{
319 short xofs = 0;
320 short yofs = 0;
321 short* word_data = (short*) p_data;
322 BYTE* data = (BYTE*) word_data + 4;
323 short row = p_flcHeader->height - (*word_data + yofs) - 1;
324
325 word_data++;
326 short lines = *word_data;
327
328 while (--lines >= 0) {
329 short column = xofs;
330 BYTE packets = *data++;
331
332 while (packets > 0) {
333 column += *data++; // skip byte
334 char type = *((char*) data++);
335
336 if (type < 0) {
337 type = -type;
338 WritePixelRun(p_bitmapHeader, p_pixelData, column, row, *data++, type);
339 column += type;
340 packets = packets - 1;
341 }
342 else {
343 WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type);
344 data += type;
345 column += type;
346 packets = packets - 1;
347 }
348 }
349
350 row--;
351 }
352}
353
354// FUNCTION: LEGO1 0x100bdac0
355// FUNCTION: BETA10 0x1013e61d
356void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
357{
358 short width = (short) p_flcHeader->width - 1;
359 short row = (short) p_flcHeader->height - 1;
360 short lines = *((short*) p_data);
361 BYTE* data = p_data + 2;
362
363 while (--lines > 0) {
364 short token;
365
366 while (TRUE) {
367 token = *((short*) data);
368 data += 2;
369
370 if (token < 0) {
371 if (token & 0x4000) {
372 row += token;
373 }
374 else {
375 WritePixel(p_bitmapHeader, p_pixelData, width, row, token);
376 token = *((WORD*) data);
377 data += 2;
378
379 if (!token) {
380 row--;
381 if (--lines <= 0) {
382 return;
383 }
384 }
385 else {
386 break;
387 }
388 }
389 }
390 else {
391 break;
392 }
393 }
394
395 short column = 0;
396 do {
397 column += *(data++);
398 short type = *((char*) data++);
399 type += type;
400
401 if (type >= 0) {
402 WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type);
403 column += type;
404 data += type;
405 }
406 else {
407 type = -type;
408 short p_pixel = *((WORD*) data);
409 data += 2;
410 WritePixelPairs(p_bitmapHeader, p_pixelData, column, row, p_pixel, type >> 1);
411 column += type;
412 }
413 } while (--token);
414
415 row--;
416 }
417}
418
419// FUNCTION: LEGO1 0x100bdc00
420// FUNCTION: BETA10 0x1013e85a
421void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
422{
423 short height = p_flcHeader->height;
424 short width = p_flcHeader->width;
425 short t_col = 0;
426 short t_row = 0;
427
428 BYTE pixel[2];
429 pixel[0] = pixel[1] = 0;
430
431 for (short i = height - 1; i >= 0; i--) {
432 WritePixelPairs(p_bitmapHeader, p_pixelData, t_col, t_row + i, *(WORD*) pixel, width / 2);
433
434 if (width & 1) {
435 WritePixel(p_bitmapHeader, p_pixelData, t_col + width - 1, t_row + i, 0);
436 }
437 }
438}
439
440// FUNCTION: LEGO1 0x100bdc90
441// FUNCTION: BETA10 0x1013e91f
442void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
443{
444 short height = p_flcHeader->height;
445 short width = p_flcHeader->width;
446 short t_col = 0;
447 short t_row = 0;
448
449 for (short i = height - 1; i >= 0; i--) {
450 WritePixels(p_bitmapHeader, p_pixelData, t_col, t_row + i, p_data, width);
451 p_data += width;
452 }
453}
454
455// FUNCTION: LEGO1 0x100bdce0
456// FUNCTION: BETA10 0x1013e9a5
458 LPBITMAPINFOHEADER p_bitmapHeader,
459 BYTE* p_pixelData,
460 FLIC_HEADER* p_flcHeader,
461 FLIC_FRAME* p_flcFrame,
462 BYTE* p_decodedColorMap
463)
464{
465 FLIC_FRAME* frame = p_flcFrame;
466 if (frame->type != FLI_CHUNK_FRAME) {
467 return;
468 }
469
470 if (DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, frame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap)) {
471 return;
472 }
473}
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, BYTE *p_data, FLIC_HEADER *p_flcHeader)
Definition: flic.cpp:317
void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, BYTE *p_data, FLIC_HEADER *p_flcHeader)
Definition: flic.cpp:421
short DecodeChunks(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, FLIC_HEADER *p_flcHeader, FLIC_FRAME *p_flcFrame, BYTE *p_flcSubchunks, BYTE *p_decodedColorMap)
Definition: flic.cpp:175
void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_data, short p_index, short p_count)
Definition: flic.cpp:255
void WritePixelRun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, short p_column, short p_row, byte p_pixel, short p_count)
Definition: flic.cpp:122
void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, BYTE *p_data, FLIC_HEADER *p_flcHeader)
Definition: flic.cpp:356
void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_data)
Definition: flic.cpp:231
void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_data)
Definition: flic.cpp:224
void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, short p_column, short p_row, byte p_pixel)
Definition: flic.cpp:53
void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_data)
Definition: flic.cpp:271
int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short &p_column, short &p_row, short &p_count)
Definition: flic.cpp:91
void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, BYTE *p_data, FLIC_HEADER *p_flcHeader)
Definition: flic.cpp:442
void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, BYTE *p_data, FLIC_HEADER *p_flcHeader)
Definition: flic.cpp:278
void DecodeFLCFrame(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, FLIC_HEADER *p_flcHeader, FLIC_FRAME *p_flcFrame, BYTE *p_decodedColorMap)
[AI] Decodes a single FLIC (FLI/FLC) animation frame and updates the pixel data and palette.
Definition: flic.cpp:457
void WritePixels(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, short p_column, short p_row, BYTE *p_data, short p_count)
Definition: flic.cpp:64
void WritePixelPairs(LPBITMAPINFOHEADER p_bitmapHeader, BYTE *p_pixelData, short p_column, short p_row, WORD p_pixel, short p_count)
Definition: flic.cpp:144
@ FLI_CHUNK_FRAME
Marks the start of a FLIC animation frame. [AI].
Definition: flic.h:22
@ FLI_CHUNK_COPY
No compression; raw pixel data for the frame. [AI].
Definition: flic.h:20
@ FLI_CHUNK_COLOR64
64-level color palette info. Updates only 64 palette entries. [AI]
Definition: flic.h:16
@ FLI_CHUNK_BLACK
Entire frame is filled with color index 0 (black). [AI].
Definition: flic.h:18
@ FLI_CHUNK_LC
Byte-oriented delta compression. Encodes lines with byte-level difference encoding....
Definition: flic.h:17
@ FLI_CHUNK_SS2
Word-oriented delta compression. Efficient for lines with word-aligned runs or minimal pixel changes....
Definition: flic.h:15
@ FLI_CHUNK_BRUN
Byte run-length compression. Lossless RLE for frame data. [AI].
Definition: flic.h:19
@ FLI_CHUNK_COLOR256
256-level color palette info. Updates the color lookup table with 256 entries. [AI]
Definition: flic.h:14
[AI] Represents a generic chunk header in a FLIC animation file.
Definition: flic.h:31
DWORD size
[AI] Total size of the chunk in bytes, including the header and payload/subchunks.
Definition: flic.h:32
WORD type
[AI] Chunk type identifier (see FLI_CHUNK_TYPE).
Definition: flic.h:33
[AI] Structure describing the header of a FLIC animation frame, used to organize frame subchunks and ...
Definition: flic.h:58
WORD chunks
[AI] Number of subchunks that compose this animation frame (palette/image/compression chunks)....
Definition: flic.h:59
[AI] Structure for the main header of a FLIC animation file.
Definition: flic.h:42
WORD width
[AI] Image width in pixels for the animation. [AI]
Definition: flic.h:44
WORD height
[AI] Image height in pixels for the animation. [AI]
Definition: flic.h:45