]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/targa.c
Simplify RGB32 png encoding.
[ffmpeg] / libavcodec / targa.c
index f60524dc84366195a4e07d5d83718cc9c17f1f00..57a4fee22bacdd92a257d14a2809efdefececf58 100644 (file)
@@ -178,24 +178,45 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     if(colors){
-        size_t pal_size;
+        int pal_size, pal_sample_size;
         if((colors + first_clr) > 256){
             av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
             return -1;
         }
-        if(csize != 24){
+        switch (csize) {
+        case 24: pal_sample_size = 3; break;
+        case 16:
+        case 15: pal_sample_size = 2; break;
+        default:
             av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
             return -1;
         }
-        pal_size = colors * ((csize + 1) >> 3);
+        pal_size = colors * pal_sample_size;
         CHECK_BUFFER_SIZE(buf, buf_end, pal_size, "color table");
         if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway
             buf += pal_size;
         else{
             int t;
-            int32_t *pal = ((int32_t*)p->data[1]) + first_clr;
-            for(t = 0; t < colors; t++){
-                *pal++ = (0xff<<24) | bytestream_get_le24(&buf);
+            uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr;
+
+            switch (pal_sample_size) {
+            case 3:
+                /* RGB24 */
+                for (t = 0; t < colors; t++)
+                    *pal++ = (0xffU<<24) | bytestream_get_le24(&buf);
+                break;
+            case 2:
+                /* RGB555 */
+                for (t = 0; t < colors; t++) {
+                    uint32_t v = bytestream_get_le16(&buf);
+                    v = ((v & 0x7C00) <<  9) |
+                        ((v & 0x03E0) <<  6) |
+                        ((v & 0x001F) <<  3);
+                    /* left bit replication */
+                    v |= (v & 0xE0E0E0U) >> 5;
+                    *pal++ = (0xffU<<24) | v;
+                }
+                break;
             }
             p->palette_has_changed = 1;
         }
@@ -238,18 +259,18 @@ static int decode_frame(AVCodecContext *avctx,
             for(x = 0; x < s->width >> 1; x++){
                 switch(s->bpp){
                 case 32:
-                    FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[s->width - x]);
+                    FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[s->width - x - 1]);
                     break;
                 case 24:
-                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x    ], ((uint8_t *)line)[3 * s->width - 3 * x    ]);
-                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 1], ((uint8_t *)line)[3 * s->width - 3 * x + 1]);
-                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 2], ((uint8_t *)line)[3 * s->width - 3 * x + 2]);
+                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x    ], ((uint8_t *)line)[3 * s->width - 3 * x - 3]);
+                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 1], ((uint8_t *)line)[3 * s->width - 3 * x - 2]);
+                    FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 2], ((uint8_t *)line)[3 * s->width - 3 * x - 1]);
                     break;
                 case 16:
-                    FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[s->width - x]);
+                    FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[s->width - x - 1]);
                     break;
                 case 8:
-                    FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[s->width - x]);
+                    FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[s->width - x - 1]);
                 }
             }
         }