X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Ftarga.c;h=57a4fee22bacdd92a257d14a2809efdefececf58;hb=107f55cb01d2333541b8887194c487a6c6bc1ba1;hp=884bae6cc948034bf75a19ae1bfe072896866dc5;hpb=4dcd1a3145dd93602b86a44ebc07d98ca2a30ab6;p=ffmpeg diff --git a/libavcodec/targa.c b/libavcodec/targa.c index 884bae6cc94..57a4fee22ba 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -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; } @@ -231,6 +252,29 @@ static int decode_frame(AVCodecContext *avctx, } } } + if(flags & 0x10){ // right-to-left, needs horizontal flip + int x; + for(y = 0; y < s->height; y++){ + void *line = &p->data[0][y * p->linesize[0]]; + 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 - 1]); + break; + case 24: + 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 - 1]); + break; + case 8: + FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[s->width - x - 1]); + } + } + } + } *picture= *(AVFrame*)&s->picture; *data_size = sizeof(AVPicture);