diff options
Diffstat (limited to 'libmpcodecs')
-rw-r--r-- | libmpcodecs/native/qtrle.c | 100 | ||||
-rw-r--r-- | libmpcodecs/vd_qtrle.c | 5 |
2 files changed, 104 insertions, 1 deletions
diff --git a/libmpcodecs/native/qtrle.c b/libmpcodecs/native/qtrle.c index 23d761c038..e6a44f8009 100644 --- a/libmpcodecs/native/qtrle.c +++ b/libmpcodecs/native/qtrle.c @@ -3,6 +3,7 @@ (C) 2001 Mike Melanson 8 and 16bpp support by Alex Beregszaszi + 32 bpp support by Roberto Togni */ #include "config.h" @@ -258,6 +259,96 @@ void qt_decode_rle24( } } +void qt_decode_rle32( + unsigned char *encoded, + int encoded_size, + unsigned char *decoded, + int width, + int height, + int bytes_per_pixel) +{ + int stream_ptr; + int header; + int start_line; + int lines_to_change; + signed char rle_code; + int row_ptr, pixel_ptr; + int row_inc = bytes_per_pixel * width; + unsigned char r, g, b; + + // check if this frame is even supposed to change + if (encoded_size < 8) + return; + + // start after the chunk size + stream_ptr = 4; + + // fetch the header + header = BE_16(&encoded[stream_ptr]); + stream_ptr += 2; + + // if a header is present, fetch additional decoding parameters + if (header & 0x0008) + { + start_line = BE_16(&encoded[stream_ptr]); + stream_ptr += 4; + lines_to_change = BE_16(&encoded[stream_ptr]); + stream_ptr += 4; + } + else + { + start_line = 0; + lines_to_change = height; + } + + row_ptr = row_inc * start_line; + while (lines_to_change--) + { + pixel_ptr = row_ptr + ((encoded[stream_ptr++] - 1) * bytes_per_pixel); + + while (stream_ptr < encoded_size && + (rle_code = (signed char)encoded[stream_ptr++]) != -1) + { + if (rle_code == 0) + // there's another skip code in the stream + pixel_ptr += ((encoded[stream_ptr++] - 1) * bytes_per_pixel); + else if (rle_code < 0) + { + // decode the run length code + rle_code = -rle_code; + stream_ptr++; // Ignore alpha channel + r = encoded[stream_ptr++]; + g = encoded[stream_ptr++]; + b = encoded[stream_ptr++]; + while (rle_code--) + { + decoded[pixel_ptr++] = b; + decoded[pixel_ptr++] = g; + decoded[pixel_ptr++] = r; + if (bytes_per_pixel == 4) + pixel_ptr++; + } + } + else + { + // copy pixels directly to output + while (rle_code--) + { + stream_ptr++; // Ignore alpha channel + decoded[pixel_ptr++] = encoded[stream_ptr + 2]; + decoded[pixel_ptr++] = encoded[stream_ptr + 1]; + decoded[pixel_ptr++] = encoded[stream_ptr + 0]; + stream_ptr += 3; + if (bytes_per_pixel == 4) + pixel_ptr++; + } + } + } + + row_ptr += row_inc; + } +} + void qt_decode_rle( unsigned char *encoded, int encoded_size, @@ -296,5 +387,14 @@ void qt_decode_rle( height, bytes_per_pixel); break; + case 32: + qt_decode_rle32( + encoded, + encoded_size, + decoded, + width, + height, + bytes_per_pixel); + break; } } diff --git a/libmpcodecs/vd_qtrle.c b/libmpcodecs/vd_qtrle.c index de6356dd48..5f43257327 100644 --- a/libmpcodecs/vd_qtrle.c +++ b/libmpcodecs/vd_qtrle.c @@ -32,7 +32,8 @@ static int control(sh_video_t *sh,int cmd,void* arg,...){ /* qtrle24 supports 32bit output too */ if ((req_format == (IMGFMT_BGR|ctx->depth)) || - ((IMGFMT_BGR_DEPTH(req_format) == 32) && (ctx->depth == 24))) + ((IMGFMT_BGR_DEPTH(req_format) == 32) && (ctx->depth == 24)) || + ((IMGFMT_BGR_DEPTH(req_format) == 24) && (ctx->depth == 32))) return(CONTROL_TRUE); else return(CONTROL_FALSE); @@ -68,6 +69,8 @@ static int init(sh_video_t *sh){ case 16: ctx->depth--; /* this is the trick ;) */ break; + case 32: + mp_msg(MSGT_DECVIDEO,MSGL_INFO,"[qtrle] 32 bpp file, alpha channel will be ignored.\n"); case 24: break; default: |