1/* 2 * Targa (.tga) image decoder 3 * Copyright (c) 2006 Konstantin Shishkov 4 * 5 * This file is part of FFmpeg. 6 * 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. 11 * 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. 16 * 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 20 */ 21 22#include "libavutil/intreadwrite.h" 23#include "libavutil/imgutils.h" 24#include "avcodec.h" 25#include "bytestream.h" 26#include "internal.h" 27#include "targa.h" 28 29typedef struct TargaContext { 30 GetByteContext gb; 31} TargaContext; 32 33static uint8_t *advance_line(uint8_t *start, uint8_t *line, 34 int stride, int *y, int h, int interleave) 35{ 36 *y += interleave; 37 38 if (*y < h) { 39 return line + interleave * stride; 40 } else { 41 *y = (*y + 1) & (interleave - 1); 42 if (*y && *y < h) { 43 return start + *y * stride; 44 } else { 45 return NULL; 46 } 47 } 48} 49 50static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, 51 uint8_t *start, int w, int h, int stride, 52 int bpp, int interleave) 53{ 54 int x, y; 55 int depth = (bpp + 1) >> 3; 56 int type, count; 57 uint8_t *line = start; 58 uint8_t *dst = line; 59 60 x = y = count = 0; 61 while (dst) { 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; 66 } 67 type = bytestream2_get_byteu(&s->gb); 68 count = (type & 0x7F) + 1; 69 type &= 0x80; 70 if (!type) { 71 do { 72 int n = FFMIN(count, w - x); 73 bytestream2_get_buffer(&s->gb, dst, n * depth); 74 count -= n; 75 dst += n * depth; 76 x += n; 77 if (x == w) { 78 x = 0; 79 dst = line = advance_line(start, line, stride, &y, h, interleave); 80 } 81 } while (dst && count > 0); 82 } else { 83 uint8_t tmp[4]; 84 bytestream2_get_buffer(&s->gb, tmp, depth); 85 do { 86 int n = FFMIN(count, w - x); 87 count -= n; 88 x += n; 89 do { 90 memcpy(dst, tmp, depth); 91 dst += depth; 92 } while (--n); 93 if (x == w) { 94 x = 0; 95 dst = line = advance_line(start, line, stride, &y, h, interleave); 96 } 97 } while (dst && count > 0); 98 } 99 } 100 101 if (count) { 102 av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds\n"); 103 return AVERROR_INVALIDDATA; 104 } 105 106 return 0; 107} 108 109static int decode_frame(AVCodecContext *avctx, 110 void *data, int *got_frame, 111 AVPacket *avpkt) 112{ 113 TargaContext * const s = avctx->priv_data; 114 AVFrame * const p = data; 115 uint8_t *dst; 116 int stride; 117 int idlen, pal, compr, y, w, h, bpp, flags, ret; 118 int first_clr, colors, csize; 119 int interleave; 120 121 bytestream2_init(&s->gb, avpkt->data, avpkt->size); 122 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); 134 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; 139 } 140 141 flags = bytestream2_get_byte(&s->gb); 142 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; 147 } 148 149 // skip identifier if any 150 bytestream2_skip(&s->gb, idlen); 151 152 switch (bpp) { 153 case 8: 154 avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_PAL8; 155 break; 156 case 15: 157 case 16: 158 avctx->pix_fmt = AV_PIX_FMT_RGB555LE; 159 break; 160 case 24: 161 avctx->pix_fmt = AV_PIX_FMT_BGR24; 162 break; 163 case 32: 164 avctx->pix_fmt = AV_PIX_FMT_BGRA; 165 break; 166 default: 167 av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", bpp); 168 return AVERROR_INVALIDDATA; 169 } 170 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; 174 } 175 176 if ((ret = ff_set_dimensions(avctx, w, h)) < 0) 177 return ret; 178 179 if ((ret = ff_get_buffer(avctx, p, 0)) < 0) 180 return ret; 181 p->pict_type = AV_PICTURE_TYPE_I; 182 183 if (flags & TGA_TOPTOBOTTOM) { 184 dst = p->data[0]; 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]; 189 } 190 191 interleave = flags & TGA_INTERLEAVE2 ? 2 : 192 flags & TGA_INTERLEAVE4 ? 4 : 1; 193 194 if (colors) { 195 int pal_size, pal_sample_size; 196 197 switch (csize) { 198 case 32: pal_sample_size = 4; break; 199 case 24: pal_sample_size = 3; break; 200 case 16: 201 case 15: pal_sample_size = 2; break; 202 default: 203 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize); 204 return AVERROR_INVALIDDATA; 205 } 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); 209 else { 210 int t; 211 uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr; 212 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; 217 } 218 switch (pal_sample_size) { 219 case 4: 220 for (t = 0; t < colors; t++) 221 *pal++ = bytestream2_get_le32u(&s->gb); 222 break; 223 case 3: 224 /* RGB24 */ 225 for (t = 0; t < colors; t++) 226 *pal++ = (0xffU<<24) | bytestream2_get_le24u(&s->gb); 227 break; 228 case 2: 229 /* RGB555 */ 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) | 234 ((v & 0x001F) << 3); 235 /* left bit replication */ 236 v |= (v & 0xE0E0E0U) >> 5; 237 *pal++ = (0xffU<<24) | v; 238 } 239 break; 240 } 241 p->palette_has_changed = 1; 242 } 243 } 244 245 if ((compr & (~TGA_RLE)) == TGA_NODATA) { 246 memset(p->data[0], 0, p->linesize[0] * h); 247 } else { 248 if (compr & TGA_RLE) { 249 int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp, interleave); 250 if (res < 0) 251 return res; 252 } else { 253 size_t img_size = w * ((bpp + 1) >> 3); 254 uint8_t *line; 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; 259 } 260 261 line = dst; 262 y = 0; 263 do { 264 bytestream2_get_buffer(&s->gb, line, img_size); 265 line = advance_line(dst, line, stride, &y, h, interleave); 266 } while (line); 267 } 268 } 269 270 if (flags & TGA_RIGHTTOLEFT) { // right-to-left, needs horizontal flip 271 int x; 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++) { 275 switch (bpp) { 276 case 32: 277 FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[w - x - 1]); 278 break; 279 case 24: 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]); 283 break; 284 case 16: 285 FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[w - x - 1]); 286 break; 287 case 8: 288 FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[w - x - 1]); 289 } 290 } 291 } 292 } 293 294 *got_frame = 1; 295 296 return avpkt->size; 297} 298 299AVCodec ff_targa_decoder = { 300 .name = "targa", 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, 307}; 308