2 * Targa (.tga) image decoder
3 * Copyright (c) 2006 Konstantin Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/imgutils.h"
25 #include "bytestream.h"
29 typedef struct TargaContext
{
33 static uint8_t *advance_line(uint8_t *start
, uint8_t *line
,
34 int stride
, int *y
, int h
, int interleave
)
39 return line
+ interleave
* stride
;
41 *y
= (*y
+ 1) & (interleave
- 1);
43 return start
+ *y
* stride
;
50 static int targa_decode_rle(AVCodecContext
*avctx
, TargaContext
*s
,
51 uint8_t *start
, int w
, int h
, int stride
,
52 int bpp
, int interleave
)
55 int depth
= (bpp
+ 1) >> 3;
57 uint8_t *line
= start
;
62 if (bytestream2_get_bytes_left(&s
->gb
) <= 0) {
63 av_log(avctx
, AV_LOG_ERROR
,
64 "Ran ouf of data before end-of-image\n");
65 return AVERROR_INVALIDDATA
;
67 type
= bytestream2_get_byteu(&s
->gb
);
68 count
= (type
& 0x7F) + 1;
72 int n
= FFMIN(count
, w
- x
);
73 bytestream2_get_buffer(&s
->gb
, dst
, n
* depth
);
79 dst
= line
= advance_line(start
, line
, stride
, &y
, h
, interleave
);
81 } while (dst
&& count
> 0);
84 bytestream2_get_buffer(&s
->gb
, tmp
, depth
);
86 int n
= FFMIN(count
, w
- x
);
90 memcpy(dst
, tmp
, depth
);
95 dst
= line
= advance_line(start
, line
, stride
, &y
, h
, interleave
);
97 } while (dst
&& count
> 0);
102 av_log(avctx
, AV_LOG_ERROR
, "Packet went out of bounds\n");
103 return AVERROR_INVALIDDATA
;
109 static int decode_frame(AVCodecContext
*avctx
,
110 void *data
, int *got_frame
,
113 TargaContext
* const s
= avctx
->priv_data
;
114 AVFrame
* const p
= data
;
117 int idlen
, pal
, compr
, y
, w
, h
, bpp
, flags
, ret
;
118 int first_clr
, colors
, csize
;
121 bytestream2_init(&s
->gb
, avpkt
->data
, avpkt
->size
);
123 /* parse image header */
124 idlen
= bytestream2_get_byte(&s
->gb
);
125 pal
= bytestream2_get_byte(&s
->gb
);
126 compr
= bytestream2_get_byte(&s
->gb
);
127 first_clr
= bytestream2_get_le16(&s
->gb
);
128 colors
= bytestream2_get_le16(&s
->gb
);
129 csize
= bytestream2_get_byte(&s
->gb
);
130 bytestream2_skip(&s
->gb
, 4); /* 2: x, 2: y */
131 w
= bytestream2_get_le16(&s
->gb
);
132 h
= bytestream2_get_le16(&s
->gb
);
133 bpp
= bytestream2_get_byte(&s
->gb
);
135 if (bytestream2_get_bytes_left(&s
->gb
) <= idlen
) {
136 av_log(avctx
, AV_LOG_ERROR
,
137 "Not enough data to read header\n");
138 return AVERROR_INVALIDDATA
;
141 flags
= bytestream2_get_byte(&s
->gb
);
143 if (!pal
&& (first_clr
|| colors
|| csize
)) {
144 av_log(avctx
, AV_LOG_WARNING
, "File without colormap has colormap information set.\n");
145 // specification says we should ignore those value in this case
146 first_clr
= colors
= csize
= 0;
149 // skip identifier if any
150 bytestream2_skip(&s
->gb
, idlen
);
154 avctx
->pix_fmt
= ((compr
& (~TGA_RLE
)) == TGA_BW
) ? AV_PIX_FMT_GRAY8
: AV_PIX_FMT_PAL8
;
158 avctx
->pix_fmt
= AV_PIX_FMT_RGB555LE
;
161 avctx
->pix_fmt
= AV_PIX_FMT_BGR24
;
164 avctx
->pix_fmt
= AV_PIX_FMT_BGRA
;
167 av_log(avctx
, AV_LOG_ERROR
, "Bit depth %i is not supported\n", bpp
);
168 return AVERROR_INVALIDDATA
;
171 if (colors
&& (colors
+ first_clr
) > 256) {
172 av_log(avctx
, AV_LOG_ERROR
, "Incorrect palette: %i colors with offset %i\n", colors
, first_clr
);
173 return AVERROR_INVALIDDATA
;
176 if ((ret
= ff_set_dimensions(avctx
, w
, h
)) < 0)
179 if ((ret
= ff_get_buffer(avctx
, p
, 0)) < 0)
181 p
->pict_type
= AV_PICTURE_TYPE_I
;
183 if (flags
& TGA_TOPTOBOTTOM
) {
185 stride
= p
->linesize
[0];
186 } else { //image is upside-down
187 dst
= p
->data
[0] + p
->linesize
[0] * (h
- 1);
188 stride
= -p
->linesize
[0];
191 interleave
= flags
& TGA_INTERLEAVE2
? 2 :
192 flags
& TGA_INTERLEAVE4
? 4 : 1;
195 int pal_size
, pal_sample_size
;
198 case 32: pal_sample_size
= 4; break;
199 case 24: pal_sample_size
= 3; break;
201 case 15: pal_sample_size
= 2; break;
203 av_log(avctx
, AV_LOG_ERROR
, "Palette entry size %i bits is not supported\n", csize
);
204 return AVERROR_INVALIDDATA
;
206 pal_size
= colors
* pal_sample_size
;
207 if (avctx
->pix_fmt
!= AV_PIX_FMT_PAL8
) //should not occur but skip palette anyway
208 bytestream2_skip(&s
->gb
, pal_size
);
211 uint32_t *pal
= ((uint32_t *)p
->data
[1]) + first_clr
;
213 if (bytestream2_get_bytes_left(&s
->gb
) < pal_size
) {
214 av_log(avctx
, AV_LOG_ERROR
,
215 "Not enough data to read palette\n");
216 return AVERROR_INVALIDDATA
;
218 switch (pal_sample_size
) {
220 for (t
= 0; t
< colors
; t
++)
221 *pal
++ = bytestream2_get_le32u(&s
->gb
);
225 for (t
= 0; t
< colors
; t
++)
226 *pal
++ = (0xffU
<<24) | bytestream2_get_le24u(&s
->gb
);
230 for (t
= 0; t
< colors
; t
++) {
231 uint32_t v
= bytestream2_get_le16u(&s
->gb
);
232 v
= ((v
& 0x7C00) << 9) |
233 ((v
& 0x03E0) << 6) |
235 /* left bit replication */
236 v
|= (v
& 0xE0E0E0U
) >> 5;
237 *pal
++ = (0xffU
<<24) | v
;
241 p
->palette_has_changed
= 1;
245 if ((compr
& (~TGA_RLE
)) == TGA_NODATA
) {
246 memset(p
->data
[0], 0, p
->linesize
[0] * h
);
248 if (compr
& TGA_RLE
) {
249 int res
= targa_decode_rle(avctx
, s
, dst
, w
, h
, stride
, bpp
, interleave
);
253 size_t img_size
= w
* ((bpp
+ 1) >> 3);
255 if (bytestream2_get_bytes_left(&s
->gb
) < img_size
* h
) {
256 av_log(avctx
, AV_LOG_ERROR
,
257 "Not enough data available for image\n");
258 return AVERROR_INVALIDDATA
;
264 bytestream2_get_buffer(&s
->gb
, line
, img_size
);
265 line
= advance_line(dst
, line
, stride
, &y
, h
, interleave
);
270 if (flags
& TGA_RIGHTTOLEFT
) { // right-to-left, needs horizontal flip
272 for (y
= 0; y
< h
; y
++) {
273 void *line
= &p
->data
[0][y
* p
->linesize
[0]];
274 for (x
= 0; x
< w
>> 1; x
++) {
277 FFSWAP(uint32_t, ((uint32_t *)line
)[x
], ((uint32_t *)line
)[w
- x
- 1]);
280 FFSWAP(uint8_t, ((uint8_t *)line
)[3 * x
], ((uint8_t *)line
)[3 * w
- 3 * x
- 3]);
281 FFSWAP(uint8_t, ((uint8_t *)line
)[3 * x
+ 1], ((uint8_t *)line
)[3 * w
- 3 * x
- 2]);
282 FFSWAP(uint8_t, ((uint8_t *)line
)[3 * x
+ 2], ((uint8_t *)line
)[3 * w
- 3 * x
- 1]);
285 FFSWAP(uint16_t, ((uint16_t *)line
)[x
], ((uint16_t *)line
)[w
- x
- 1]);
288 FFSWAP(uint8_t, ((uint8_t *)line
)[x
], ((uint8_t *)line
)[w
- x
- 1]);
299 AVCodec ff_targa_decoder
= {
301 .long_name
= NULL_IF_CONFIG_SMALL("Truevision Targa image"),
302 .type
= AVMEDIA_TYPE_VIDEO
,
303 .id
= AV_CODEC_ID_TARGA
,
304 .priv_data_size
= sizeof(TargaContext
),
305 .decode
= decode_frame
,
306 .capabilities
= CODEC_CAP_DR1
,