Browse code

Targa image decoder

Originally committed as revision 6640 to svn://svn.ffmpeg.org/ffmpeg/trunk

Kostya Shishkov authored on 2006/10/11 13:15:04
Showing 8 changed files
... ...
@@ -59,6 +59,7 @@ version <next>
59 59
 - VP5 video decoder
60 60
 - VP6 video decoder
61 61
 - WavPack lossless audio decoder
62
+- Targa (.TGA) picture decoder
62 63
 
63 64
 version 0.4.9-pre1:
64 65
 
... ...
@@ -155,6 +155,7 @@ Codecs:
155 155
   snow.c                                Michael Niedermayer, Loren Merritt
156 156
   sonic.c                               Alex Beregszaszi
157 157
   svq3.c                                Michael Niedermayer
158
+  targa.c                               Kostya Shishkov
158 159
   truemotion1*                          Mike Melanson
159 160
   truemotion2*                          Kostya Shishkov
160 161
   truespeech.c                          Kostya Shishkov
... ...
@@ -753,6 +753,7 @@ following image formats are supported:
753 753
 @item .Y.U.V       @tab X @tab X @tab one raw file per component
754 754
 @item animated GIF @tab X @tab X @tab Only uncompressed GIFs are generated.
755 755
 @item PNG          @tab X @tab X @tab 2 bit and 4 bit/pixel not supported yet.
756
+@item Targa        @tab   @tab X @tab Targa (.TGA) image format.
756 757
 @item SGI          @tab X @tab X @tab SGI RGB image format
757 758
 @end multitable
758 759
 
... ...
@@ -131,6 +131,7 @@ OBJS-$(CONFIG_SONIC_LS_DECODER)        += sonic.o
131 131
 OBJS-$(CONFIG_SVQ1_DECODER)            += svq1.o
132 132
 OBJS-$(CONFIG_SVQ1_ENCODER)            += svq1.o
133 133
 OBJS-$(CONFIG_SVQ3_DECODER)            += h264.o
134
+OBJS-$(CONFIG_TARGA_DECODER)           += targa.o
134 135
 OBJS-$(CONFIG_THEORA_DECODER)          += vp3.o
135 136
 OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
136 137
 OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
... ...
@@ -545,6 +545,9 @@ void avcodec_register_all(void)
545 545
 #ifdef CONFIG_WAVPACK_DECODER
546 546
     register_avcodec(&wavpack_decoder);
547 547
 #endif //CONFIG_WAVPACK_DECODER
548
+#ifdef CONFIG_TARGA_DECODER
549
+    register_avcodec(&targa_decoder);
550
+#endif //CONFIG_TARGA_DECODER
548 551
 
549 552
 #if defined(CONFIG_AMR_NB) || defined(CONFIG_AMR_NB_FIXED)
550 553
 #ifdef CONFIG_AMR_NB_DECODER
... ...
@@ -37,8 +37,8 @@ extern "C" {
37 37
 #define AV_STRINGIFY(s)         AV_TOSTRING(s)
38 38
 #define AV_TOSTRING(s) #s
39 39
 
40
-#define LIBAVCODEC_VERSION_INT  ((51<<16)+(16<<8)+0)
41
-#define LIBAVCODEC_VERSION      51.16.0
40
+#define LIBAVCODEC_VERSION_INT  ((51<<16)+(17<<8)+0)
41
+#define LIBAVCODEC_VERSION      51.17.0
42 42
 #define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT
43 43
 
44 44
 #define LIBAVCODEC_IDENT        "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
... ...
@@ -144,6 +144,7 @@ enum CodecID {
144 144
     CODEC_ID_VP5,
145 145
     CODEC_ID_VP6,
146 146
     CODEC_ID_VP6F,
147
+    CODEC_ID_TARGA,
147 148
 
148 149
     /* various pcm "codecs" */
149 150
     CODEC_ID_PCM_S16LE= 0x10000,
... ...
@@ -2292,6 +2293,7 @@ extern AVCodec flashsv_decoder;
2292 2292
 extern AVCodec cavs_decoder;
2293 2293
 extern AVCodec vmnc_decoder;
2294 2294
 extern AVCodec wavpack_decoder;
2295
+extern AVCodec targa_decoder;
2295 2296
 
2296 2297
 /* pcm codecs */
2297 2298
 #define PCM_CODEC(id, name) \
2298 2299
new file mode 100644
... ...
@@ -0,0 +1,244 @@
0
+/*
1
+ * Targa (.tga) image decoder
2
+ * Copyright (c) 2006 Konstantin Shishkov
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ *
20
+ */
21
+#include "avcodec.h"
22
+
23
+enum TargaCompr{
24
+    TGA_NODATA = 0, // no image data
25
+    TGA_PAL    = 1, // palettized
26
+    TGA_RGB    = 2, // true-color
27
+    TGA_BW     = 3, // black & white or grayscale
28
+    TGA_RLE    = 8, // flag pointing that data is RLE-coded
29
+};
30
+
31
+typedef struct TargaContext {
32
+    AVFrame picture;
33
+
34
+    int width, height;
35
+    int bpp;
36
+    int color_type;
37
+    int compression_type;
38
+} TargaContext;
39
+
40
+static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp)
41
+{
42
+    int i, x, y;
43
+    int depth = (bpp + 1) >> 3;
44
+    int type, count;
45
+    int diff;
46
+
47
+    diff = stride - w * depth;
48
+    x = y = 0;
49
+    while(y < h){
50
+        type = *src++;
51
+        count = (type & 0x7F) + 1;
52
+        type &= 0x80;
53
+        if((x + count > w) && (x + count + 1 > (h - y) * w)){
54
+            av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);
55
+            return;
56
+        }
57
+        for(i = 0; i < count; i++){
58
+            switch(depth){
59
+            case 1:
60
+                *dst = *src;
61
+                break;
62
+            case 2:
63
+                *((uint16_t*)dst) = LE_16(src);
64
+                break;
65
+            case 3:
66
+                dst[0] = src[0];
67
+                dst[1] = src[1];
68
+                dst[2] = src[2];
69
+                break;
70
+            }
71
+            dst += depth;
72
+            if(!type)
73
+                src += depth;
74
+
75
+            x++;
76
+            if(x == w){
77
+                x = 0;
78
+                y++;
79
+                dst += diff;
80
+            }
81
+        }
82
+        if(type)
83
+            src += depth;
84
+    }
85
+}
86
+
87
+static int decode_frame(AVCodecContext *avctx,
88
+                        void *data, int *data_size,
89
+                        uint8_t *buf, int buf_size)
90
+{
91
+    TargaContext * const s = avctx->priv_data;
92
+    AVFrame *picture = data;
93
+    AVFrame * const p= (AVFrame*)&s->picture;
94
+    uint8_t *dst;
95
+    int stride;
96
+    int idlen, pal, compr, x, y, w, h, bpp, flags;
97
+    int first_clr, colors, csize;
98
+
99
+    /* parse image header */
100
+    idlen = *buf++;
101
+    pal = *buf++;
102
+    compr = *buf++;
103
+    first_clr = LE_16(buf); buf += 2;
104
+    colors = LE_16(buf); buf += 2;
105
+    csize = *buf++;
106
+    x = LE_16(buf); buf += 2;
107
+    y = LE_16(buf); buf += 2;
108
+    w = LE_16(buf); buf += 2;
109
+    h = LE_16(buf); buf += 2;
110
+    bpp = *buf++;
111
+    flags = *buf++;
112
+    //skip identifier if any
113
+    buf += idlen;
114
+    s->bpp = bpp;
115
+    s->width = w;
116
+    s->height = h;
117
+    switch(s->bpp){
118
+    case 8:
119
+        avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? PIX_FMT_GRAY8 : PIX_FMT_PAL8;
120
+        break;
121
+    case 15:
122
+        avctx->pix_fmt = PIX_FMT_RGB555;
123
+        break;
124
+    case 16:
125
+        avctx->pix_fmt = PIX_FMT_RGB555;
126
+        break;
127
+    case 24:
128
+        avctx->pix_fmt = PIX_FMT_BGR24;
129
+        break;
130
+    default:
131
+        av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", avctx->bits_per_sample);
132
+        return -1;
133
+    }
134
+
135
+    if(s->picture.data[0])
136
+        avctx->release_buffer(avctx, &s->picture);
137
+
138
+    if(avcodec_check_dimensions(avctx, w, h))
139
+        return -1;
140
+    if(w != avctx->width || h != avctx->height)
141
+        avcodec_set_dimensions(avctx, w, h);
142
+    if(avctx->get_buffer(avctx, p) < 0){
143
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
144
+        return -1;
145
+    }
146
+    if(flags & 0x20){
147
+        dst = p->data[0];
148
+        stride = p->linesize[0];
149
+    }else{ //image is upside-down
150
+        dst = p->data[0] + p->linesize[0] * (h - 1);
151
+        stride = -p->linesize[0];
152
+    }
153
+
154
+    if(avctx->pix_fmt == PIX_FMT_PAL8 && avctx->palctrl){
155
+        memcpy(p->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
156
+        if(avctx->palctrl->palette_changed){
157
+            p->palette_has_changed = 1;
158
+            avctx->palctrl->palette_changed = 0;
159
+        }
160
+    }
161
+    if(colors){
162
+        if((colors + first_clr) > 256){
163
+            av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
164
+            return -1;
165
+        }
166
+        if(csize != 24){
167
+            av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
168
+            return -1;
169
+        }
170
+        if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway
171
+            buf += colors * ((csize + 1) >> 3);
172
+        else{
173
+            int r, g, b, t;
174
+            int32_t *pal = ((int32_t*)p->data[1]) + first_clr;
175
+            for(t = 0; t < colors; t++){
176
+                r = *buf++;
177
+                g = *buf++;
178
+                b = *buf++;
179
+                *pal++ = (b << 16) | (g << 8) | r;
180
+            }
181
+            p->palette_has_changed = 1;
182
+            avctx->palctrl->palette_changed = 0;
183
+        }
184
+    }
185
+    if((compr & (~TGA_RLE)) == TGA_NODATA)
186
+        memset(p->data[0], 0, p->linesize[0] * s->height);
187
+    else{
188
+        if(compr & TGA_RLE)
189
+            targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp);
190
+        else{
191
+            for(y = 0; y < s->height; y++){
192
+#ifdef WORDS_BIGENDIAN
193
+                if((s->bpp + 1) >> 3 == 2){
194
+                    uint16_t *dst16 = (uint16_t*)dst;
195
+                    for(x = 0; x < s->width; x++)
196
+                        dst16[x] = LE_16(buf + x * 2);
197
+                }else
198
+#endif
199
+                    memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3));
200
+
201
+                dst += stride;
202
+                buf += s->width * ((s->bpp + 1) >> 3);
203
+            }
204
+        }
205
+    }
206
+
207
+    *picture= *(AVFrame*)&s->picture;
208
+    *data_size = sizeof(AVPicture);
209
+
210
+    return buf_size;
211
+}
212
+
213
+static int targa_init(AVCodecContext *avctx){
214
+    TargaContext *s = avctx->priv_data;
215
+
216
+    avcodec_get_frame_defaults((AVFrame*)&s->picture);
217
+    avctx->coded_frame= (AVFrame*)&s->picture;
218
+    s->picture.data[0] = NULL;
219
+
220
+    return 0;
221
+}
222
+
223
+static int targa_end(AVCodecContext *avctx){
224
+    TargaContext *s = avctx->priv_data;
225
+
226
+    if(s->picture.data[0])
227
+        avctx->release_buffer(avctx, &s->picture);
228
+
229
+    return 0;
230
+}
231
+
232
+AVCodec targa_decoder = {
233
+    "targa",
234
+    CODEC_TYPE_VIDEO,
235
+    CODEC_ID_TARGA,
236
+    sizeof(TargaContext),
237
+    targa_init,
238
+    NULL,
239
+    targa_end,
240
+    decode_frame,
241
+    0,
242
+    NULL
243
+};
... ...
@@ -117,6 +117,7 @@ static const CodecTag mov_video_tags[] = {
117 117
     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
118 118
     { CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
119 119
     //{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
120
+    { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, /* Truevision Targa */
120 121
     { CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
121 122
     { CODEC_ID_NONE, 0 },
122 123
 };