1/* 2 * IFF ACBM/DEEP/ILBM/PBM bitmap decoder 3 * Copyright (c) 2010 Peter Ross <pross@xvid.org> 4 * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23/** 24 * @file 25 * IFF ACBM/DEEP/ILBM/PBM bitmap decoder 26 */ 27 28#include <stdint.h> 29 30#include "libavutil/imgutils.h" 31#include "bytestream.h" 32#include "avcodec.h" 33#include "get_bits.h" 34#include "internal.h" 35 36// TODO: masking bits 37typedef enum { 38 MASK_NONE, 39 MASK_HAS_MASK, 40 MASK_HAS_TRANSPARENT_COLOR, 41 MASK_LASSO 42} mask_type; 43 44typedef struct { 45 AVFrame *frame; 46 int planesize; 47 uint8_t * planebuf; 48 uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation 49 uint32_t *ham_palbuf; ///< HAM decode table 50 uint32_t *mask_buf; ///< temporary buffer for palette indices 51 uint32_t *mask_palbuf; ///< masking palette table 52 unsigned compression; ///< delta compression method used 53 unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) 54 unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) 55 unsigned flags; ///< 1 for EHB, 0 is no extra half darkening 56 unsigned transparency; ///< TODO: transparency color index in palette 57 unsigned masking; ///< TODO: masking method used 58 int init; // 1 if buffer and palette data already initialized, 0 otherwise 59 int16_t tvdc[16]; ///< TVDC lookup table 60} IffContext; 61 62#define LUT8_PART(plane, v) \ 63 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \ 64 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \ 65 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \ 66 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \ 67 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \ 68 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \ 69 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \ 70 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \ 71 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \ 72 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \ 73 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \ 74 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \ 75 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \ 76 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \ 77 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \ 78 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane 79 80#define LUT8(plane) { \ 81 LUT8_PART(plane, 0x0000000), \ 82 LUT8_PART(plane, 0x1000000), \ 83 LUT8_PART(plane, 0x0010000), \ 84 LUT8_PART(plane, 0x1010000), \ 85 LUT8_PART(plane, 0x0000100), \ 86 LUT8_PART(plane, 0x1000100), \ 87 LUT8_PART(plane, 0x0010100), \ 88 LUT8_PART(plane, 0x1010100), \ 89 LUT8_PART(plane, 0x0000001), \ 90 LUT8_PART(plane, 0x1000001), \ 91 LUT8_PART(plane, 0x0010001), \ 92 LUT8_PART(plane, 0x1010001), \ 93 LUT8_PART(plane, 0x0000101), \ 94 LUT8_PART(plane, 0x1000101), \ 95 LUT8_PART(plane, 0x0010101), \ 96 LUT8_PART(plane, 0x1010101), \ 97} 98 99// 8 planes * 8-bit mask 100static const uint64_t plane8_lut[8][256] = { 101 LUT8(0), LUT8(1), LUT8(2), LUT8(3), 102 LUT8(4), LUT8(5), LUT8(6), LUT8(7), 103}; 104 105#define LUT32(plane) { \ 106 0, 0, 0, 0, \ 107 0, 0, 0, 1 << plane, \ 108 0, 0, 1 << plane, 0, \ 109 0, 0, 1 << plane, 1 << plane, \ 110 0, 1 << plane, 0, 0, \ 111 0, 1 << plane, 0, 1 << plane, \ 112 0, 1 << plane, 1 << plane, 0, \ 113 0, 1 << plane, 1 << plane, 1 << plane, \ 114 1 << plane, 0, 0, 0, \ 115 1 << plane, 0, 0, 1 << plane, \ 116 1 << plane, 0, 1 << plane, 0, \ 117 1 << plane, 0, 1 << plane, 1 << plane, \ 118 1 << plane, 1 << plane, 0, 0, \ 119 1 << plane, 1 << plane, 0, 1 << plane, \ 120 1 << plane, 1 << plane, 1 << plane, 0, \ 121 1 << plane, 1 << plane, 1 << plane, 1 << plane, \ 122} 123 124// 32 planes * 4-bit mask * 4 lookup tables each 125static const uint32_t plane32_lut[32][16*4] = { 126 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3), 127 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7), 128 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11), 129 LUT32(12), LUT32(13), LUT32(14), LUT32(15), 130 LUT32(16), LUT32(17), LUT32(18), LUT32(19), 131 LUT32(20), LUT32(21), LUT32(22), LUT32(23), 132 LUT32(24), LUT32(25), LUT32(26), LUT32(27), 133 LUT32(28), LUT32(29), LUT32(30), LUT32(31), 134}; 135 136// Gray to RGB, required for palette table of grayscale images with bpp < 8 137static av_always_inline uint32_t gray2rgb(const uint32_t x) { 138 return x << 16 | x << 8 | x; 139} 140 141/** 142 * Convert CMAP buffer (stored in extradata) to lavc palette format 143 */ 144static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) 145{ 146 IffContext *s = avctx->priv_data; 147 int count, i; 148 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); 149 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 150 151 if (avctx->bits_per_coded_sample > 8) { 152 av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n"); 153 return AVERROR_INVALIDDATA; 154 } 155 156 count = 1 << avctx->bits_per_coded_sample; 157 // If extradata is smaller than actually needed, fill the remaining with black. 158 count = FFMIN(palette_size / 3, count); 159 if (count) { 160 for (i = 0; i < count; i++) 161 pal[i] = 0xFF000000 | AV_RB24(palette + i*3); 162 if (s->flags && count >= 32) { // EHB 163 for (i = 0; i < 32; i++) 164 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1; 165 count = FFMAX(count, 64); 166 } 167 } else { // Create gray-scale color palette for bps < 8 168 count = 1 << avctx->bits_per_coded_sample; 169 170 for (i = 0; i < count; i++) 171 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample); 172 } 173 if (s->masking == MASK_HAS_MASK) { 174 memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4); 175 for (i = 0; i < count; i++) 176 pal[i] &= 0xFFFFFF; 177 } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR && 178 s->transparency < 1 << avctx->bits_per_coded_sample) 179 pal[s->transparency] &= 0xFFFFFF; 180 return 0; 181} 182 183/** 184 * Extracts the IFF extra context and updates internal 185 * decoder structures. 186 * 187 * @param avctx the AVCodecContext where to extract extra context to 188 * @param avpkt the AVPacket to extract extra context from or NULL to use avctx 189 * @return >= 0 in case of success, a negative error code otherwise 190 */ 191static int extract_header(AVCodecContext *const avctx, 192 const AVPacket *const avpkt) { 193 const uint8_t *buf; 194 unsigned buf_size; 195 IffContext *s = avctx->priv_data; 196 int i, palette_size; 197 198 if (avctx->extradata_size < 2) { 199 av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); 200 return AVERROR_INVALIDDATA; 201 } 202 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 203 204 if (avpkt) { 205 int image_size; 206 if (avpkt->size < 2) 207 return AVERROR_INVALIDDATA; 208 image_size = avpkt->size - AV_RB16(avpkt->data); 209 buf = avpkt->data; 210 buf_size = bytestream_get_be16(&buf); 211 if (buf_size <= 1 || image_size <= 1) { 212 av_log(avctx, AV_LOG_ERROR, 213 "Invalid image size received: %u -> image data offset: %d\n", 214 buf_size, image_size); 215 return AVERROR_INVALIDDATA; 216 } 217 } else { 218 buf = avctx->extradata; 219 buf_size = bytestream_get_be16(&buf); 220 if (buf_size <= 1 || palette_size < 0) { 221 av_log(avctx, AV_LOG_ERROR, 222 "Invalid palette size received: %u -> palette data offset: %d\n", 223 buf_size, palette_size); 224 return AVERROR_INVALIDDATA; 225 } 226 } 227 228 if (buf_size >= 41) { 229 s->compression = bytestream_get_byte(&buf); 230 s->bpp = bytestream_get_byte(&buf); 231 s->ham = bytestream_get_byte(&buf); 232 s->flags = bytestream_get_byte(&buf); 233 s->transparency = bytestream_get_be16(&buf); 234 s->masking = bytestream_get_byte(&buf); 235 for (i = 0; i < 16; i++) 236 s->tvdc[i] = bytestream_get_be16(&buf); 237 238 if (s->masking == MASK_HAS_MASK) { 239 if (s->bpp >= 8 && !s->ham) { 240 avctx->pix_fmt = AV_PIX_FMT_RGB32; 241 av_freep(&s->mask_buf); 242 av_freep(&s->mask_palbuf); 243 s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE); 244 if (!s->mask_buf) 245 return AVERROR(ENOMEM); 246 if (s->bpp > 16) { 247 av_log(avctx, AV_LOG_ERROR, "bpp %d too large for palette\n", s->bpp); 248 av_freep(&s->mask_buf); 249 return AVERROR(ENOMEM); 250 } 251 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE); 252 if (!s->mask_palbuf) { 253 av_freep(&s->mask_buf); 254 return AVERROR(ENOMEM); 255 } 256 } 257 s->bpp++; 258 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) { 259 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n"); 260 return AVERROR_PATCHWELCOME; 261 } 262 if (!s->bpp || s->bpp > 32) { 263 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp); 264 return AVERROR_INVALIDDATA; 265 } else if (s->ham >= 8) { 266 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham); 267 return AVERROR_INVALIDDATA; 268 } 269 270 av_freep(&s->ham_buf); 271 av_freep(&s->ham_palbuf); 272 273 if (s->ham) { 274 int i, count = FFMIN(palette_size / 3, 1 << s->ham); 275 int ham_count; 276 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); 277 278 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE); 279 if (!s->ham_buf) 280 return AVERROR(ENOMEM); 281 282 ham_count = 8 * (1 << s->ham); 283 s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE); 284 if (!s->ham_palbuf) { 285 av_freep(&s->ham_buf); 286 return AVERROR(ENOMEM); 287 } 288 289 if (count) { // HAM with color palette attached 290 // prefill with black and palette and set HAM take direct value mask to zero 291 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t)); 292 for (i=0; i < count; i++) { 293 s->ham_palbuf[i*2+1] = 0xFF000000 | AV_RL24(palette + i*3); 294 } 295 count = 1 << s->ham; 296 } else { // HAM with grayscale color palette 297 count = 1 << s->ham; 298 for (i=0; i < count; i++) { 299 s->ham_palbuf[i*2] = 0xFF000000; // take direct color value from palette 300 s->ham_palbuf[i*2+1] = 0xFF000000 | av_le2ne32(gray2rgb((i * 255) >> s->ham)); 301 } 302 } 303 for (i=0; i < count; i++) { 304 uint32_t tmp = i << (8 - s->ham); 305 tmp |= tmp >> s->ham; 306 s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; // just modify blue color component 307 s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; // just modify red color component 308 s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; // just modify green color component 309 s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16; 310 s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp; 311 s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8; 312 } 313 if (s->masking == MASK_HAS_MASK) { 314 for (i = 0; i < ham_count; i++) 315 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000; 316 } 317 } 318 } 319 320 return 0; 321} 322 323static av_cold int decode_end(AVCodecContext *avctx) 324{ 325 IffContext *s = avctx->priv_data; 326 av_frame_free(&s->frame); 327 av_freep(&s->planebuf); 328 av_freep(&s->ham_buf); 329 av_freep(&s->ham_palbuf); 330 return 0; 331} 332 333static av_cold int decode_init(AVCodecContext *avctx) 334{ 335 IffContext *s = avctx->priv_data; 336 int err; 337 338 if (avctx->bits_per_coded_sample <= 8) { 339 int palette_size; 340 341 if (avctx->extradata_size >= 2) 342 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); 343 else 344 palette_size = 0; 345 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) || 346 (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; 347 } else if (avctx->bits_per_coded_sample <= 32) { 348 if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8')) { 349 avctx->pix_fmt = AV_PIX_FMT_RGB32; 350 } else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N')) { 351 avctx->pix_fmt = AV_PIX_FMT_RGB444; 352 } else if (avctx->codec_tag != MKTAG('D', 'E', 'E', 'P')) { 353 if (avctx->bits_per_coded_sample == 24) { 354 avctx->pix_fmt = AV_PIX_FMT_0BGR32; 355 } else if (avctx->bits_per_coded_sample == 32) { 356 avctx->pix_fmt = AV_PIX_FMT_BGR32; 357 } else { 358 avpriv_request_sample(avctx, "unknown bits_per_coded_sample"); 359 return AVERROR_PATCHWELCOME; 360 } 361 } 362 } else { 363 return AVERROR_INVALIDDATA; 364 } 365 366 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx))) 367 return err; 368 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary 369 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE); 370 if (!s->planebuf) 371 return AVERROR(ENOMEM); 372 373 s->bpp = avctx->bits_per_coded_sample; 374 s->frame = av_frame_alloc(); 375 if (!s->frame) { 376 decode_end(avctx); 377 return AVERROR(ENOMEM); 378 } 379 380 if ((err = extract_header(avctx, NULL)) < 0) 381 return err; 382 383 return 0; 384} 385 386/** 387 * Decode interleaved plane buffer up to 8bpp 388 * @param dst Destination buffer 389 * @param buf Source buffer 390 * @param buf_size 391 * @param plane plane number to decode as 392 */ 393static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane) 394{ 395 const uint64_t *lut = plane8_lut[plane]; 396 if (plane >= 8) { 397 av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n"); 398 return; 399 } 400 do { 401 uint64_t v = AV_RN64A(dst) | lut[*buf++]; 402 AV_WN64A(dst, v); 403 dst += 8; 404 } while (--buf_size); 405} 406 407/** 408 * Decode interleaved plane buffer up to 24bpp 409 * @param dst Destination buffer 410 * @param buf Source buffer 411 * @param buf_size 412 * @param plane plane number to decode as 413 */ 414static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane) 415{ 416 const uint32_t *lut = plane32_lut[plane]; 417 do { 418 unsigned mask = (*buf >> 2) & ~3; 419 dst[0] |= lut[mask++]; 420 dst[1] |= lut[mask++]; 421 dst[2] |= lut[mask++]; 422 dst[3] |= lut[mask]; 423 mask = (*buf++ << 2) & 0x3F; 424 dst[4] |= lut[mask++]; 425 dst[5] |= lut[mask++]; 426 dst[6] |= lut[mask++]; 427 dst[7] |= lut[mask]; 428 dst += 8; 429 } while (--buf_size); 430} 431 432#define DECODE_HAM_PLANE32(x) \ 433 first = buf[x] << 1; \ 434 second = buf[(x)+1] << 1; \ 435 delta &= pal[first++]; \ 436 delta |= pal[first]; \ 437 dst[x] = delta; \ 438 delta &= pal[second++]; \ 439 delta |= pal[second]; \ 440 dst[(x)+1] = delta 441 442/** 443 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp. 444 * 445 * @param dst the destination 24bpp buffer 446 * @param buf the source 8bpp chunky buffer 447 * @param pal the HAM decode table 448 * @param buf_size the plane size in bytes 449 */ 450static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf, 451 const uint32_t *const pal, unsigned buf_size) 452{ 453 uint32_t delta = pal[1]; /* first palette entry */ 454 do { 455 uint32_t first, second; 456 DECODE_HAM_PLANE32(0); 457 DECODE_HAM_PLANE32(2); 458 DECODE_HAM_PLANE32(4); 459 DECODE_HAM_PLANE32(6); 460 buf += 8; 461 dst += 8; 462 } while (--buf_size); 463} 464 465static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf, 466 const uint32_t *const pal, unsigned width) 467{ 468 do { 469 *dst++ = pal[*buf++]; 470 } while (--width); 471} 472 473/** 474 * Decode one complete byterun1 encoded line. 475 * 476 * @param dst the destination buffer where to store decompressed bitstream 477 * @param dst_size the destination plane size in bytes 478 * @param buf the source byterun1 compressed bitstream 479 * @param buf_end the EOF of source byterun1 compressed bitstream 480 * @return number of consumed bytes in byterun1 compressed bitstream 481 */ 482static int decode_byterun(uint8_t *dst, int dst_size, 483 const uint8_t *buf, const uint8_t *const buf_end) 484{ 485 const uint8_t *const buf_start = buf; 486 unsigned x; 487 for (x = 0; x < dst_size && buf < buf_end;) { 488 unsigned length; 489 const int8_t value = *buf++; 490 if (value >= 0) { 491 length = FFMIN3(value + 1, dst_size - x, buf_end - buf); 492 memcpy(dst + x, buf, length); 493 buf += length; 494 } else if (value > -128) { 495 length = FFMIN(-value + 1, dst_size - x); 496 memset(dst + x, *buf++, length); 497 } else { // noop 498 continue; 499 } 500 x += length; 501 } 502 if (x < dst_size) { 503 av_log(NULL, AV_LOG_WARNING, "decode_byterun ended before plane size\n"); 504 memset(dst+x, 0, dst_size - x); 505 } 506 return buf - buf_start; 507} 508 509#define DECODE_RGBX_COMMON(type) \ 510 if (!length) { \ 511 length = bytestream2_get_byte(gb); \ 512 if (!length) { \ 513 length = bytestream2_get_be16(gb); \ 514 if (!length) \ 515 return; \ 516 } \ 517 } \ 518 for (i = 0; i < length; i++) { \ 519 *(type *)(dst + y*linesize + x * sizeof(type)) = pixel; \ 520 x += 1; \ 521 if (x >= width) { \ 522 y += 1; \ 523 if (y >= height) \ 524 return; \ 525 x = 0; \ 526 } \ 527 } 528 529/** 530 * Decode RGB8 buffer 531 * @param[out] dst Destination buffer 532 * @param width Width of destination buffer (pixels) 533 * @param height Height of destination buffer (pixels) 534 * @param linesize Line size of destination buffer (bytes) 535 */ 536static void decode_rgb8(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) 537{ 538 int x = 0, y = 0, i, length; 539 while (bytestream2_get_bytes_left(gb) >= 4) { 540 uint32_t pixel = 0xFF000000 | bytestream2_get_be24(gb); 541 length = bytestream2_get_byte(gb) & 0x7F; 542 DECODE_RGBX_COMMON(uint32_t) 543 } 544} 545 546/** 547 * Decode RGBN buffer 548 * @param[out] dst Destination buffer 549 * @param width Width of destination buffer (pixels) 550 * @param height Height of destination buffer (pixels) 551 * @param linesize Line size of destination buffer (bytes) 552 */ 553static void decode_rgbn(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) 554{ 555 int x = 0, y = 0, i, length; 556 while (bytestream2_get_bytes_left(gb) >= 2) { 557 uint32_t pixel = bytestream2_get_be16u(gb); 558 length = pixel & 0x7; 559 pixel >>= 4; 560 DECODE_RGBX_COMMON(uint16_t) 561 } 562} 563 564/** 565 * Decode DEEP RLE 32-bit buffer 566 * @param[out] dst Destination buffer 567 * @param[in] src Source buffer 568 * @param src_size Source buffer size (bytes) 569 * @param width Width of destination buffer (pixels) 570 * @param height Height of destination buffer (pixels) 571 * @param linesize Line size of destination buffer (bytes) 572 */ 573static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) 574{ 575 const uint8_t *src_end = src + src_size; 576 int x = 0, y = 0, i; 577 while (src + 5 <= src_end) { 578 int opcode; 579 opcode = *(int8_t *)src++; 580 if (opcode >= 0) { 581 int size = opcode + 1; 582 for (i = 0; i < size; i++) { 583 int length = FFMIN(size - i, width); 584 memcpy(dst + y*linesize + x * 4, src, length * 4); 585 src += length * 4; 586 x += length; 587 i += length; 588 if (x >= width) { 589 x = 0; 590 y += 1; 591 if (y >= height) 592 return; 593 } 594 } 595 } else { 596 int size = -opcode + 1; 597 uint32_t pixel = AV_RN32(src); 598 for (i = 0; i < size; i++) { 599 *(uint32_t *)(dst + y*linesize + x * 4) = pixel; 600 x += 1; 601 if (x >= width) { 602 x = 0; 603 y += 1; 604 if (y >= height) 605 return; 606 } 607 } 608 src += 4; 609 } 610 } 611} 612 613/** 614 * Decode DEEP TVDC 32-bit buffer 615 * @param[out] dst Destination buffer 616 * @param[in] src Source buffer 617 * @param src_size Source buffer size (bytes) 618 * @param width Width of destination buffer (pixels) 619 * @param height Height of destination buffer (pixels) 620 * @param linesize Line size of destination buffer (bytes) 621 * @param[int] tvdc TVDC lookup table 622 */ 623static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize, const int16_t *tvdc) 624{ 625 int x = 0, y = 0, plane = 0; 626 int8_t pixel = 0; 627 int i, j; 628 629 for (i = 0; i < src_size * 2;) { 630#define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4)) 631 int d = tvdc[GETNIBBLE]; 632 i++; 633 if (d) { 634 pixel += d; 635 dst[y * linesize + x*4 + plane] = pixel; 636 x++; 637 } else { 638 if (i >= src_size * 2) 639 return; 640 d = GETNIBBLE + 1; 641 i++; 642 d = FFMIN(d, width - x); 643 for (j = 0; j < d; j++) { 644 dst[y * linesize + x*4 + plane] = pixel; 645 x++; 646 } 647 } 648 if (x >= width) { 649 plane++; 650 if (plane >= 4) { 651 y++; 652 if (y >= height) 653 return; 654 plane = 0; 655 } 656 x = 0; 657 pixel = 0; 658 i = (i + 1) & ~1; 659 } 660 } 661} 662 663static int unsupported(AVCodecContext *avctx) 664{ 665 IffContext *s = avctx->priv_data; 666 avpriv_request_sample(avctx, "bitmap (compression %i, bpp %i, ham %i)", s->compression, s->bpp, s->ham); 667 return AVERROR_INVALIDDATA; 668} 669 670static int decode_frame(AVCodecContext *avctx, 671 void *data, int *got_frame, 672 AVPacket *avpkt) 673{ 674 IffContext *s = avctx->priv_data; 675 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL; 676 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0; 677 const uint8_t *buf_end = buf + buf_size; 678 int y, plane, res; 679 GetByteContext gb; 680 const AVPixFmtDescriptor *desc; 681 682 if ((res = extract_header(avctx, avpkt)) < 0) 683 return res; 684 if ((res = ff_reget_buffer(avctx, s->frame)) < 0) 685 return res; 686 687 desc = av_pix_fmt_desc_get(avctx->pix_fmt); 688 689 if (!s->init && avctx->bits_per_coded_sample <= 8 && 690 avctx->pix_fmt == AV_PIX_FMT_PAL8) { 691 if ((res = cmap_read_palette(avctx, (uint32_t *)s->frame->data[1])) < 0) 692 return res; 693 } else if (!s->init && avctx->bits_per_coded_sample <= 8 && 694 avctx->pix_fmt == AV_PIX_FMT_RGB32) { 695 if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0) 696 return res; 697 } 698 s->init = 1; 699 700 switch (s->compression) { 701 case 0: 702 if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) { 703 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 704 memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); 705 for (plane = 0; plane < s->bpp; plane++) { 706 for (y = 0; y < avctx->height && buf < buf_end; y++) { 707 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 708 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); 709 buf += s->planesize; 710 } 711 } 712 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 713 memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); 714 for (y = 0; y < avctx->height; y++) { 715 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 716 memset(s->ham_buf, 0, s->planesize * 8); 717 for (plane = 0; plane < s->bpp; plane++) { 718 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize; 719 if (start >= buf_end) 720 break; 721 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane); 722 } 723 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 724 } 725 } else 726 return unsupported(avctx); 727 } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { 728 int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3); 729 int x; 730 for (y = 0; y < avctx->height && buf < buf_end; y++) { 731 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 732 memcpy(row, buf, FFMIN(raw_width, buf_end - buf)); 733 buf += raw_width; 734 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) { 735 for (x = 0; x < avctx->width; x++) 736 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4); 737 } 738 } 739 } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved 740 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 741 for (y = 0; y < avctx->height; y++) { 742 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 743 memset(row, 0, avctx->width); 744 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 745 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); 746 buf += s->planesize; 747 } 748 } 749 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 750 for (y = 0; y < avctx->height; y++) { 751 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 752 memset(s->ham_buf, 0, s->planesize * 8); 753 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 754 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane); 755 buf += s->planesize; 756 } 757 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 758 } 759 } else { // AV_PIX_FMT_BGR32 760 for (y = 0; y < avctx->height; y++) { 761 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 762 memset(row, 0, avctx->width << 2); 763 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { 764 decodeplane32((uint32_t *)row, buf, 765 FFMIN(s->planesize, buf_end - buf), plane); 766 buf += s->planesize; 767 } 768 } 769 } 770 } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM 771 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 772 for (y = 0; y < avctx->height && buf_end > buf; y++) { 773 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 774 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf)); 775 buf += avctx->width + (avctx->width % 2); // padding if odd 776 } 777 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 778 for (y = 0; y < avctx->height && buf_end > buf; y++) { 779 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 780 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf)); 781 buf += avctx->width + (avctx->width & 1); // padding if odd 782 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 783 } 784 } else 785 return unsupported(avctx); 786 } 787 break; 788 case 1: 789 if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved 790 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 791 for (y = 0; y < avctx->height; y++) { 792 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 793 memset(row, 0, avctx->width); 794 for (plane = 0; plane < s->bpp; plane++) { 795 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); 796 decodeplane8(row, s->planebuf, s->planesize, plane); 797 } 798 } 799 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32 800 for (y = 0; y < avctx->height; y++) { 801 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 802 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t)); 803 for (plane = 0; plane < s->bpp; plane++) { 804 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); 805 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane); 806 } 807 lookup_pal_indicies((uint32_t *)row, s->mask_buf, s->mask_palbuf, avctx->width); 808 } 809 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 810 for (y = 0; y < avctx->height; y++) { 811 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 812 memset(s->ham_buf, 0, s->planesize * 8); 813 for (plane = 0; plane < s->bpp; plane++) { 814 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); 815 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane); 816 } 817 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 818 } 819 } else { // AV_PIX_FMT_BGR32 820 for (y = 0; y < avctx->height; y++) { 821 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 822 memset(row, 0, avctx->width << 2); 823 for (plane = 0; plane < s->bpp; plane++) { 824 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); 825 decodeplane32((uint32_t *)row, s->planebuf, s->planesize, plane); 826 } 827 } 828 } 829 } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM 830 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { 831 for (y = 0; y < avctx->height; y++) { 832 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 833 buf += decode_byterun(row, avctx->width, buf, buf_end); 834 } 835 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 836 for (y = 0; y < avctx->height; y++) { 837 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; 838 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end); 839 decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize); 840 } 841 } else 842 return unsupported(avctx); 843 } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { // IFF-DEEP 844 if (av_get_bits_per_pixel(desc) == 32) 845 decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]); 846 else 847 return unsupported(avctx); 848 } 849 break; 850 case 4: 851 bytestream2_init(&gb, buf, buf_size); 852 if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32) 853 decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); 854 else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N') && avctx->pix_fmt == AV_PIX_FMT_RGB444) 855 decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); 856 else 857 return unsupported(avctx); 858 break; 859 case 5: 860 if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { 861 if (av_get_bits_per_pixel(desc) == 32) 862 decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc); 863 else 864 return unsupported(avctx); 865 } else 866 return unsupported(avctx); 867 break; 868 default: 869 return unsupported(avctx); 870 } 871 872 if ((res = av_frame_ref(data, s->frame)) < 0) 873 return res; 874 875 *got_frame = 1; 876 877 return buf_size; 878} 879 880#if CONFIG_IFF_ILBM_DECODER 881AVCodec ff_iff_ilbm_decoder = { 882 .name = "iff", 883 .long_name = NULL_IF_CONFIG_SMALL("IFF"), 884 .type = AVMEDIA_TYPE_VIDEO, 885 .id = AV_CODEC_ID_IFF_ILBM, 886 .priv_data_size = sizeof(IffContext), 887 .init = decode_init, 888 .close = decode_end, 889 .decode = decode_frame, 890 .capabilities = CODEC_CAP_DR1, 891}; 892#endif 893#if CONFIG_IFF_BYTERUN1_DECODER 894AVCodec ff_iff_byterun1_decoder = { 895 .name = "iff", 896 .long_name = NULL_IF_CONFIG_SMALL("IFF"), 897 .type = AVMEDIA_TYPE_VIDEO, 898 .id = AV_CODEC_ID_IFF_BYTERUN1, 899 .priv_data_size = sizeof(IffContext), 900 .init = decode_init, 901 .close = decode_end, 902 .decode = decode_frame, 903 .capabilities = CODEC_CAP_DR1, 904}; 905#endif 906