Mercurial > mplayer.hg
changeset 3155:9200edf69d1d
initial commit
author | melanson |
---|---|
date | Tue, 27 Nov 2001 05:43:03 +0000 |
parents | b2e24fec97bc |
children | 7d725c118ccf |
files | fli.c |
diffstat | 1 files changed, 273 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fli.c Tue Nov 27 05:43:03 2001 +0000 @@ -0,0 +1,273 @@ +/* + FLI Decoder for MPlayer + + (C) 2001 Mike Melanson +*/ + +#define LE_16(x) *(unsigned short *)(x) +#define LE_32(x) *(unsigned int *)(x) + +#define FLI_256_COLOR 4 +#define FLI_DELTA 7 +#define FLI_COLOR 11 +#define FLI_LC 12 +#define FLI_BLACK 13 +#define FLI_BRUN 15 +#define FLI_COPY 16 +#define FLI_MINI 18 + +// 256 RGB entries; 25% of these bytes will be unused, but it's faster +// to index 4-byte entries +static unsigned char palette[256 * 4]; + +void AVI_Decode_Fli( + unsigned char *encoded, + int encoded_size, + unsigned char *decoded, + int width, + int height, + int bytes_per_pixel) +{ + int stream_ptr = 0; + int pixel_ptr; + int palette_ptr1; + int palette_ptr2; + + unsigned int frame_size; + int num_chunks; + + unsigned int chunk_size; + int chunk_type; + + int i, j; + + int color_packets; + int color_changes; + int color_scale; + + int lines; + int compressed_lines; + int starting_line; + signed short line_packets; + int y_ptr; + int line_inc; + signed char byte_run; + + frame_size = LE_32(&encoded[stream_ptr]); + stream_ptr += 6; // skip the magic number + num_chunks = LE_16(&encoded[stream_ptr]); + stream_ptr += 10; // skip padding + + // iterate through the chunks + frame_size -= 16; + while ((frame_size > 0) && (num_chunks > 0)) + { + chunk_size = LE_32(&encoded[stream_ptr]); + stream_ptr += 4; + chunk_type = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + + switch (chunk_type) + { + case FLI_256_COLOR: + case FLI_COLOR: + if (chunk_type == FLI_COLOR) + color_scale = 4; + else + color_scale = 1; + // set up the palette + color_packets = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + palette_ptr1 = 0; + for (i = 0; i < color_packets; i++) + { + // first byte is how many colors to skip + palette_ptr1 += (encoded[stream_ptr++] * 4); + // next byte indicates how many entries to change + color_changes = encoded[stream_ptr++]; + // if there are 0 color changes, there are actually 256 + if (color_changes == 0) + color_changes = 256; + for (j = 0; j < color_changes; j++) + { + palette[palette_ptr1++] = encoded[stream_ptr + 2] * color_scale; + palette[palette_ptr1++] = encoded[stream_ptr + 1] * color_scale; + palette[palette_ptr1++] = encoded[stream_ptr + 0] * color_scale; + palette_ptr1++; + stream_ptr += 3; + } + } + break; + + case FLI_DELTA: + line_inc = width * bytes_per_pixel; + y_ptr = 0; + compressed_lines = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + while (compressed_lines > 0) + { + line_packets = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + if (line_packets < 0) + { + line_packets = -line_packets; + y_ptr += (line_packets * line_inc); + } + else + { + pixel_ptr = y_ptr; + for (i = 0; i < line_packets; i++) + { + // account for the skip bytes + pixel_ptr += encoded[stream_ptr++] * 3; + byte_run = encoded[stream_ptr++]; + if (byte_run < 0) + { + byte_run = -byte_run; + palette_ptr1 = encoded[stream_ptr++] * 4; + palette_ptr2 = encoded[stream_ptr++] * 4; + for (j = 0; j < byte_run; j++) + { + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + + decoded[pixel_ptr++] = palette[palette_ptr2 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr2 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr2 + 2]; + } + } + else + { + for (j = 0; j < byte_run * 2; j++) + { + palette_ptr1 = encoded[stream_ptr++] * 4; + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + } + } + } + y_ptr += line_inc; + compressed_lines--; + } + } + break; + + case FLI_LC: + // line compressed + line_inc = width * bytes_per_pixel; + starting_line = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + y_ptr = starting_line * line_inc; + + compressed_lines = LE_16(&encoded[stream_ptr]); + stream_ptr += 2; + while (compressed_lines > 0) + { + pixel_ptr = y_ptr; + line_packets = encoded[stream_ptr++]; + if (line_packets > 0) + { + for (i = 0; i < line_packets; i++) + { + // account for the skip bytes + pixel_ptr += encoded[stream_ptr++] * 3; + byte_run = encoded[stream_ptr++]; + if (byte_run > 0) + { + for (j = 0; j < byte_run; j++) + { + palette_ptr1 = encoded[stream_ptr++] * 4; + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + } + } + else + { + byte_run = -byte_run; + palette_ptr1 = encoded[stream_ptr++] * 4; + for (j = 0; j < byte_run; j++) + { + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + } + } + } + } + + y_ptr += line_inc; + compressed_lines--; + } + break; + + case FLI_BLACK: + // set the whole frame to color 0 (which is usually black) + for (pixel_ptr = 0; pixel_ptr < (width * height * 3); pixel_ptr++) + { + decoded[pixel_ptr++] = palette[0]; + decoded[pixel_ptr++] = palette[1]; + decoded[pixel_ptr++] = palette[2]; + } + break; + + case FLI_BRUN: + // byte run compression + line_inc = width * bytes_per_pixel; + y_ptr = 0; + for (lines = 0; lines < height; lines++) + { + pixel_ptr = y_ptr; + line_packets = encoded[stream_ptr++]; + for (i = 0; i < line_packets; i++) + { + byte_run = encoded[stream_ptr++]; + if (byte_run > 0) + { + palette_ptr1 = encoded[stream_ptr++] * 4; + for (j = 0; j < byte_run; j++) + { + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + } + } + else // copy bytes if byte_run < 0 + { + byte_run = -byte_run; + for (j = 0; j < byte_run; j++) + { + palette_ptr1 = encoded[stream_ptr++] * 4; + decoded[pixel_ptr++] = palette[palette_ptr1 + 0]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 1]; + decoded[pixel_ptr++] = palette[palette_ptr1 + 2]; + } + } + } + + y_ptr += line_inc; + } + break; + + case FLI_COPY: +// currently unimplemented +printf ("FLI_COPY chunk (currently unimplemented)\n"); +stream_ptr += chunk_size - 6; + break; + + case FLI_MINI: + // sort of a thumbnail? disregard this chunk... + stream_ptr += chunk_size - 6; + break; + + default: + printf ("FLI: Unrecognized chunk type: %d\n", chunk_type); + break; + } + + frame_size -= chunk_size; + num_chunks--; + } +}