summaryrefslogtreecommitdiff
path: root/libavcodec/qtrle.c
diff options
context:
space:
mode:
authorRoberto Togni <r_togni@tiscali.it>2004-05-31 20:18:08 +0000
committerRoberto Togni <r_togni@tiscali.it>2004-05-31 20:18:08 +0000
commit8b408dbf0ff556b6ed40c496ef3ea3821bb339ac (patch)
treeefdc3d73e99a71247053e930dae20328add2b1d4 /libavcodec/qtrle.c
parente05655fbbdc87e53bfb530306165a781ebb0b96f (diff)
Add support for qtrle4 (16 colors/gray levels)
Originally committed as revision 3183 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/qtrle.c')
-rw-r--r--libavcodec/qtrle.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index 55fa98663d..1fedaccf16 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -74,6 +74,92 @@ static void qtrle_decode_2bpp(QtrleContext *s)
static void qtrle_decode_4bpp(QtrleContext *s)
{
+ int stream_ptr;
+ int header;
+ int start_line;
+ int lines_to_change;
+ int rle_code;
+ int row_ptr, pixel_ptr;
+ int row_inc = s->frame.linesize[0];
+ unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8; /* 8 palette indices */
+ unsigned char *rgb = s->frame.data[0];
+ int pixel_limit = s->frame.linesize[0] * s->avctx->height;
+
+ /* check if this frame is even supposed to change */
+ if (s->size < 8)
+ return;
+
+ /* start after the chunk size */
+ stream_ptr = 4;
+
+ /* fetch the header */
+ CHECK_STREAM_PTR(2);
+ header = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 2;
+
+ /* if a header is present, fetch additional decoding parameters */
+ if (header & 0x0008) {
+ CHECK_STREAM_PTR(8);
+ start_line = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ lines_to_change = BE_16(&s->buf[stream_ptr]);
+ stream_ptr += 4;
+ } else {
+ start_line = 0;
+ lines_to_change = s->avctx->height;
+ }
+
+ row_ptr = row_inc * start_line;
+ while (lines_to_change--) {
+ CHECK_STREAM_PTR(2);
+ pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1));
+
+ while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+ if (rle_code == 0) {
+ /* there's another skip code in the stream */
+ CHECK_STREAM_PTR(1);
+ pixel_ptr += (8 * (s->buf[stream_ptr++] - 1));
+ } else if (rle_code < 0) {
+ /* decode the run length code */
+ rle_code = -rle_code;
+ /* get the next 4 bytes from the stream, treat them as palette
+ * indices, and output them rle_code times */
+ CHECK_STREAM_PTR(4);
+ pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi2 = (s->buf[stream_ptr++]) & 0x0f;
+ pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi4 = (s->buf[stream_ptr++]) & 0x0f;
+ pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi6 = (s->buf[stream_ptr++]) & 0x0f;
+ pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ pi8 = (s->buf[stream_ptr++]) & 0x0f;
+
+ CHECK_PIXEL_PTR(rle_code * 8);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = pi1;
+ rgb[pixel_ptr++] = pi2;
+ rgb[pixel_ptr++] = pi3;
+ rgb[pixel_ptr++] = pi4;
+ rgb[pixel_ptr++] = pi5;
+ rgb[pixel_ptr++] = pi6;
+ rgb[pixel_ptr++] = pi7;
+ rgb[pixel_ptr++] = pi8;
+ }
+ } else {
+ /* copy the same pixel directly to output 4 times */
+ rle_code *= 4;
+ CHECK_STREAM_PTR(rle_code);
+ CHECK_PIXEL_PTR(rle_code*2);
+
+ while (rle_code--) {
+ rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
+ rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
+ }
+ }
+ }
+ row_ptr += row_inc;
+ }
}
static void qtrle_decode_8bpp(QtrleContext *s)
@@ -473,6 +559,12 @@ static int qtrle_decode_frame(AVCodecContext *avctx,
case 4:
case 36:
qtrle_decode_4bpp(s);
+ /* make the palette available on the way out */
+ memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+ if (s->avctx->palctrl->palette_changed) {
+ s->frame.palette_has_changed = 1;
+ s->avctx->palctrl->palette_changed = 0;
+ }
break;
case 8: