changeset 31723:1f7d9777eecd

Share paletted -> gray/alpha conversion code, and keep a copy of the raw rle-decoded data. Should simplify implementing palette changes and the rle decoding code.
author reimar
date Sat, 24 Jul 2010 21:24:20 +0000
parents 92dd02d8ef2c
children 2e98a0ed97c8
files spudec.c
diffstat 1 files changed, 43 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/spudec.c	Sat Jul 24 20:48:32 2010 +0000
+++ b/spudec.c	Sat Jul 24 21:24:20 2010 +0000
@@ -98,6 +98,7 @@
   size_t image_size;		/* Size of the image buffer */
   unsigned char *image;		/* Grayscale value */
   unsigned char *aimage;	/* Alpha value */
+  unsigned char *pal_image;	/* palette entry value */
   unsigned int scaled_frame_width, scaled_frame_height;
   unsigned int scaled_start_col, scaled_start_row;
   unsigned int scaled_width, scaled_height, scaled_stride;
@@ -229,18 +230,42 @@
       free(this->image);
       this->image_size = 0;
     }
-    this->image = malloc(2 * this->stride * this->height);
+    this->image = malloc(3 * this->stride * this->height);
     if (this->image) {
       this->image_size = this->stride * this->height;
       this->aimage = this->image + this->image_size;
+      this->pal_image = this->aimage + this->image_size;
     }
   }
   return this->image != NULL;
 }
 
+/**
+ * \param pal palette in MPlayer-style gray-alpha values, i.e.
+ *            alpha == 0 means transparent, 1 fully opaque,
+ *            gray value <= 256 - alpha.
+ */
+static void pal2gray_alpha(const uint16_t *pal,
+                           const uint8_t *src, int src_stride,
+                           uint8_t *dst, uint8_t *dsta,
+                           int dst_stride, int w, int h)
+{
+  int x, y;
+  for (y = 0; y < h; y++) {
+    for (x = 0; x < w; x++) {
+      uint16_t pixel = pal[src[x]];
+      *dst++  = pixel;
+      *dsta++ = pixel >> 8;
+    }
+    for (; x < dst_stride; x++)
+      *dsta++ = *dst++ = 0;
+    src += src_stride;
+  }
+}
+
 static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
 {
-  unsigned int cmap[4], alpha[4];
+  uint16_t pal[4];
   unsigned int i, x, y;
 
   this->scaled_frame_width = 0;
@@ -253,30 +278,23 @@
   this->width = packet->width;
   this->stride = packet->stride;
   for (i = 0; i < 4; ++i) {
-    alpha[i] = packet->alpha[i];
+    int color;
+    int alpha = packet->alpha[i];
     // extend 4 -> 8 bit
-    alpha[i] |= alpha[i] << 4;
+    alpha |= alpha << 4;
     if (this->custom && (this->cuspal[i] >> 31) != 0)
-      alpha[i] = 0;
-    cmap[i] = this->custom ? this->cuspal[i] :
-              this->global_palette[packet->palette[i]];
-    cmap[i] = (cmap[i] >> 16) & 0xff;
-    // convert to MPlayer format
-    cmap[i] = FFMIN(cmap[i], alpha[i]);
-    alpha[i] = -alpha[i];
+      alpha = 0;
+    color = this->custom ? this->cuspal[i] :
+            this->global_palette[packet->palette[i]];
+    color = (color >> 16) & 0xff;
+    // convert to MPlayer-style gray/alpha palette
+    color = FFMIN(color, alpha);
+    pal[i] = (-alpha << 8) | color;
   }
 
   if (!spudec_alloc_image(this, this->stride, this->height))
     return;
 
-  /* Kludge: draw_alpha needs width multiple of 8. */
-  if (this->width < this->stride)
-    for (y = 0; y < this->height; ++y) {
-      memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width);
-      /* FIXME: Why is this one needed? */
-      memset(this->image + y * this->stride + this->width, 0, this->stride - this->width);
-    }
-
   i = packet->current_nibble[1];
   x = 0;
   y = 0;
@@ -301,9 +319,7 @@
     len = rle >> 2;
     if (len > this->width - x || len == 0)
       len = this->width - x;
-    /* FIXME have to use palette and alpha map*/
-    memset(this->image + y * this->stride + x, cmap[color], len);
-    memset(this->aimage + y * this->stride + x, alpha[color], len);
+    memset(this->pal_image + y * this->stride + x, color, len);
     x += len;
     if (x >= this->width) {
       next_line(packet);
@@ -311,6 +327,9 @@
       ++y;
     }
   }
+  pal2gray_alpha(pal, this->pal_image, this->stride,
+                 this->image, this->aimage, this->stride,
+                 this->width, this->height);
   spudec_cut_image(this);
 }
 
@@ -1302,16 +1321,8 @@
       gray = FFMIN(gray, alpha);
       g8a8_pal[i] = (-alpha << 8) | gray;
   }
-  for (y = 0; y < h; y++) {
-    for (x = 0; x < w; x++) {
-      uint16_t pixel = g8a8_pal[pal_img[x]];
-      *img++  = pixel;
-      *aimg++ = pixel >> 8;
-    }
-    for (; x < stride; x++)
-      *aimg++ = *img++ = 0;
-    pal_img += pal_stride;
-  }
+  pal2gray_alpha(g8a8_pal, pal_img, pal_stride,
+                 img, aimg, stride, w, h);
   packet->start_pts = 0;
   packet->end_pts = 0x7fffffff;
   if (pts != MP_NOPTS_VALUE)