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>
6 * This file is part of FFmpeg.
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.
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.
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
25 * IFF ACBM/DEEP/ILBM/PBM bitmap decoder
28 #include "libavutil/imgutils.h"
29 #include "bytestream.h"
38 MASK_HAS_TRANSPARENT_COLOR,
46 uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation
47 uint32_t *ham_palbuf; ///< HAM decode table
48 uint32_t *mask_buf; ///< temporary buffer for palette indices
49 uint32_t *mask_palbuf; ///< masking palette table
50 unsigned compression; ///< delta compression method used
51 unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
52 unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
53 unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
54 unsigned transparency; ///< TODO: transparency color index in palette
55 unsigned masking; ///< TODO: masking method used
56 int init; // 1 if buffer and palette data already initialized, 0 otherwise
57 int16_t tvdc[16]; ///< TVDC lookup table
60 #define LUT8_PART(plane, v) \
61 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
62 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
63 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
64 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
65 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
66 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
67 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
68 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
69 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
70 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
71 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
72 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
73 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
74 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
75 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
76 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
78 #define LUT8(plane) { \
79 LUT8_PART(plane, 0x0000000), \
80 LUT8_PART(plane, 0x1000000), \
81 LUT8_PART(plane, 0x0010000), \
82 LUT8_PART(plane, 0x1010000), \
83 LUT8_PART(plane, 0x0000100), \
84 LUT8_PART(plane, 0x1000100), \
85 LUT8_PART(plane, 0x0010100), \
86 LUT8_PART(plane, 0x1010100), \
87 LUT8_PART(plane, 0x0000001), \
88 LUT8_PART(plane, 0x1000001), \
89 LUT8_PART(plane, 0x0010001), \
90 LUT8_PART(plane, 0x1010001), \
91 LUT8_PART(plane, 0x0000101), \
92 LUT8_PART(plane, 0x1000101), \
93 LUT8_PART(plane, 0x0010101), \
94 LUT8_PART(plane, 0x1010101), \
97 // 8 planes * 8-bit mask
98 static const uint64_t plane8_lut[8][256] = {
99 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
100 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
103 #define LUT32(plane) { \
105 0, 0, 0, 1 << plane, \
106 0, 0, 1 << plane, 0, \
107 0, 0, 1 << plane, 1 << plane, \
108 0, 1 << plane, 0, 0, \
109 0, 1 << plane, 0, 1 << plane, \
110 0, 1 << plane, 1 << plane, 0, \
111 0, 1 << plane, 1 << plane, 1 << plane, \
112 1 << plane, 0, 0, 0, \
113 1 << plane, 0, 0, 1 << plane, \
114 1 << plane, 0, 1 << plane, 0, \
115 1 << plane, 0, 1 << plane, 1 << plane, \
116 1 << plane, 1 << plane, 0, 0, \
117 1 << plane, 1 << plane, 0, 1 << plane, \
118 1 << plane, 1 << plane, 1 << plane, 0, \
119 1 << plane, 1 << plane, 1 << plane, 1 << plane, \
122 // 32 planes * 4-bit mask * 4 lookup tables each
123 static const uint32_t plane32_lut[32][16*4] = {
124 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
125 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
126 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
127 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
128 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
129 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
130 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
131 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
134 // Gray to RGB, required for palette table of grayscale images with bpp < 8
135 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
136 return x << 16 | x << 8 | x;
140 * Convert CMAP buffer (stored in extradata) to lavc palette format
142 static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
144 IffContext *s = avctx->priv_data;
146 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
147 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
149 if (avctx->bits_per_coded_sample > 8) {
150 av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n");
151 return AVERROR_INVALIDDATA;
154 count = 1 << avctx->bits_per_coded_sample;
155 // If extradata is smaller than actually needed, fill the remaining with black.
156 count = FFMIN(palette_size / 3, count);
158 for (i=0; i < count; i++) {
159 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
161 if (s->flags && count >= 32) { // EHB
162 for (i = 0; i < 32; i++)
163 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1;
164 count = FFMAX(count, 64);
166 } else { // Create gray-scale color palette for bps < 8
167 count = 1 << avctx->bits_per_coded_sample;
169 for (i=0; i < count; i++) {
170 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
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++)
177 } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR &&
178 s->transparency < 1 << avctx->bits_per_coded_sample)
179 pal[s->transparency] &= 0xFFFFFF;
184 * Extracts the IFF extra context and updates internal
185 * decoder structures.
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
191 static int extract_header(AVCodecContext *const avctx,
192 const AVPacket *const avpkt) {
195 IffContext *s = avctx->priv_data;
198 if (avctx->extradata_size < 2) {
199 av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
200 return AVERROR_INVALIDDATA;
202 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
207 return AVERROR_INVALIDDATA;
208 image_size = avpkt->size - AV_RB16(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;
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;
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);
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);
245 return AVERROR(ENOMEM);
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);
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);
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;
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;
270 av_freep(&s->ham_buf);
271 av_freep(&s->ham_palbuf);
274 int i, count = FFMIN(palette_size / 3, 1 << s->ham);
276 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
278 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
280 return AVERROR(ENOMEM);
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);
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);
296 } else { // HAM with grayscale color palette
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));
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;
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;
323 static av_cold int decode_init(AVCodecContext *avctx)
325 IffContext *s = avctx->priv_data;
328 if (avctx->bits_per_coded_sample <= 8) {
331 if (avctx->extradata_size >= 2)
332 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
335 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
336 (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8;
337 } else if (avctx->bits_per_coded_sample <= 32) {
338 if (avctx->codec_tag == MKTAG('R','G','B','8')) {
339 avctx->pix_fmt = AV_PIX_FMT_RGB32;
340 } else if (avctx->codec_tag == MKTAG('R','G','B','N')) {
341 avctx->pix_fmt = AV_PIX_FMT_RGB444;
342 } else if (avctx->codec_tag != MKTAG('D','E','E','P')) {
343 if (avctx->bits_per_coded_sample == 24) {
344 avctx->pix_fmt = AV_PIX_FMT_0BGR32;
345 } else if (avctx->bits_per_coded_sample == 32) {
346 avctx->pix_fmt = AV_PIX_FMT_BGR32;
348 avpriv_request_sample(avctx, "unknown bits_per_coded_sample");
349 return AVERROR_PATCHWELCOME;
353 return AVERROR_INVALIDDATA;
356 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
358 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
359 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
361 return AVERROR(ENOMEM);
363 s->bpp = avctx->bits_per_coded_sample;
364 s->frame = av_frame_alloc();
366 return AVERROR(ENOMEM);
368 if ((err = extract_header(avctx, NULL)) < 0)
375 * Decode interleaved plane buffer up to 8bpp
376 * @param dst Destination buffer
377 * @param buf Source buffer
379 * @param plane plane number to decode as
381 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
383 const uint64_t *lut = plane8_lut[plane];
385 av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n");
389 uint64_t v = AV_RN64A(dst) | lut[*buf++];
392 } while (--buf_size);
396 * Decode interleaved plane buffer up to 24bpp
397 * @param dst Destination buffer
398 * @param buf Source buffer
400 * @param plane plane number to decode as
402 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
404 const uint32_t *lut = plane32_lut[plane];
406 unsigned mask = (*buf >> 2) & ~3;
407 dst[0] |= lut[mask++];
408 dst[1] |= lut[mask++];
409 dst[2] |= lut[mask++];
411 mask = (*buf++ << 2) & 0x3F;
412 dst[4] |= lut[mask++];
413 dst[5] |= lut[mask++];
414 dst[6] |= lut[mask++];
417 } while (--buf_size);
420 #define DECODE_HAM_PLANE32(x) \
421 first = buf[x] << 1; \
422 second = buf[(x)+1] << 1; \
423 delta &= pal[first++]; \
424 delta |= pal[first]; \
426 delta &= pal[second++]; \
427 delta |= pal[second]; \
431 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
433 * @param dst the destination 24bpp buffer
434 * @param buf the source 8bpp chunky buffer
435 * @param pal the HAM decode table
436 * @param buf_size the plane size in bytes
438 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
439 const uint32_t *const pal, unsigned buf_size)
441 uint32_t delta = pal[1]; /* first palette entry */
443 uint32_t first, second;
444 DECODE_HAM_PLANE32(0);
445 DECODE_HAM_PLANE32(2);
446 DECODE_HAM_PLANE32(4);
447 DECODE_HAM_PLANE32(6);
450 } while (--buf_size);
453 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
454 const uint32_t *const pal, unsigned width)
457 *dst++ = pal[*buf++];
462 * Decode one complete byterun1 encoded line.
464 * @param dst the destination buffer where to store decompressed bitstream
465 * @param dst_size the destination plane size in bytes
466 * @param buf the source byterun1 compressed bitstream
467 * @param buf_end the EOF of source byterun1 compressed bitstream
468 * @return number of consumed bytes in byterun1 compressed bitstream
470 static int decode_byterun(uint8_t *dst, int dst_size,
471 const uint8_t *buf, const uint8_t *const buf_end) {
472 const uint8_t *const buf_start = buf;
474 for (x = 0; x < dst_size && buf < buf_end;) {
476 const int8_t value = *buf++;
479 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
481 } else if (value > -128) {
483 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
489 return buf - buf_start;
492 #define DECODE_RGBX_COMMON(type) \
494 length = bytestream2_get_byte(gb); \
496 length = bytestream2_get_be16(gb); \
501 for (i = 0; i < length; i++) { \
502 *(type *)(dst + y*linesize + x * sizeof(type)) = pixel; \
514 * @param[out] dst Destination buffer
515 * @param width Width of destination buffer (pixels)
516 * @param height Height of destination buffer (pixels)
517 * @param linesize Line size of destination buffer (bytes)
519 static void decode_rgb8(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize)
521 int x = 0, y = 0, i, length;
522 while (bytestream2_get_bytes_left(gb) >= 4) {
523 uint32_t pixel = 0xFF000000 | bytestream2_get_be24(gb);
524 length = bytestream2_get_byte(gb) & 0x7F;
525 DECODE_RGBX_COMMON(uint32_t)
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)
536 static void decode_rgbn(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize)
538 int x = 0, y = 0, i, length;
539 while (bytestream2_get_bytes_left(gb) >= 2) {
540 uint32_t pixel = bytestream2_get_be16u(gb);
541 length = pixel & 0x7;
543 DECODE_RGBX_COMMON(uint16_t)
548 * Decode DEEP RLE 32-bit buffer
549 * @param[out] dst Destination buffer
550 * @param[in] src Source buffer
551 * @param src_size Source buffer size (bytes)
552 * @param width Width of destination buffer (pixels)
553 * @param height Height of destination buffer (pixels)
554 * @param linesize Line size of destination buffer (bytes)
556 static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize)
558 const uint8_t *src_end = src + src_size;
560 while (src + 5 <= src_end) {
562 opcode = *(int8_t *)src++;
564 int size = opcode + 1;
565 for (i = 0; i < size; i++) {
566 int length = FFMIN(size - i, width);
567 memcpy(dst + y*linesize + x * 4, src, length * 4);
579 int size = -opcode + 1;
580 uint32_t pixel = AV_RN32(src);
581 for (i = 0; i < size; i++) {
582 *(uint32_t *)(dst + y*linesize + x * 4) = pixel;
597 * Decode DEEP TVDC 32-bit buffer
598 * @param[out] dst Destination buffer
599 * @param[in] src Source buffer
600 * @param src_size Source buffer size (bytes)
601 * @param width Width of destination buffer (pixels)
602 * @param height Height of destination buffer (pixels)
603 * @param linesize Line size of destination buffer (bytes)
604 * @param[int] tvdc TVDC lookup table
606 static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize, const int16_t *tvdc)
608 int x = 0, y = 0, plane = 0;
612 for (i = 0; i < src_size * 2;) {
613 #define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4))
614 int d = tvdc[GETNIBBLE];
618 dst[y * linesize + x*4 + plane] = pixel;
621 if (i >= src_size * 2)
625 d = FFMIN(d, width - x);
626 for (j = 0; j < d; j++) {
627 dst[y * linesize + x*4 + plane] = pixel;
646 static int unsupported(AVCodecContext *avctx)
648 IffContext *s = avctx->priv_data;
649 avpriv_request_sample(avctx, "bitmap (compression %i, bpp %i, ham %i)", s->compression, s->bpp, s->ham);
650 return AVERROR_INVALIDDATA;
653 static int decode_frame(AVCodecContext *avctx,
654 void *data, int *got_frame,
657 IffContext *s = avctx->priv_data;
658 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
659 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
660 const uint8_t *buf_end = buf+buf_size;
664 if ((res = extract_header(avctx, avpkt)) < 0)
666 if ((res = ff_reget_buffer(avctx, s->frame)) < 0)
668 if (!s->init && avctx->bits_per_coded_sample <= 8 &&
669 avctx->pix_fmt == AV_PIX_FMT_PAL8) {
670 if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame->data[1])) < 0)
672 } else if (!s->init && avctx->bits_per_coded_sample <= 8 &&
673 avctx->pix_fmt == AV_PIX_FMT_RGB32) {
674 if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0)
679 switch (s->compression) {
681 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
682 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
683 memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
684 for (plane = 0; plane < s->bpp; plane++) {
685 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
686 uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
687 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
691 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
692 memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
693 for(y = 0; y < avctx->height; y++) {
694 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
695 memset(s->ham_buf, 0, s->planesize * 8);
696 for (plane = 0; plane < s->bpp; plane++) {
697 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
698 if (start >= buf_end)
700 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
702 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
705 return unsupported(avctx);
706 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
707 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
708 int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
710 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
711 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
712 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
714 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
715 for(x = 0; x < avctx->width; x++)
716 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
719 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
720 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
721 for(y = 0; y < avctx->height; y++ ) {
722 uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
723 memset(row, 0, avctx->width);
724 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
725 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
729 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
730 for (y = 0; y < avctx->height; y++) {
731 uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
732 memset(s->ham_buf, 0, s->planesize * 8);
733 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
734 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
737 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
739 } else { // AV_PIX_FMT_BGR32
740 for(y = 0; y < avctx->height; y++ ) {
741 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
742 memset(row, 0, avctx->width << 2);
743 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
744 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
749 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
750 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
751 for(y = 0; y < avctx->height && buf_end > buf; y++ ) {
752 uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
753 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
754 buf += avctx->width + (avctx->width % 2); // padding if odd
756 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
757 for (y = 0; y < avctx->height && buf_end > buf; y++) {
758 uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
759 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
760 buf += avctx->width + (avctx->width & 1); // padding if odd
761 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
764 return unsupported(avctx);
768 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
769 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
770 for(y = 0; y < avctx->height ; y++ ) {
771 uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
772 memset(row, 0, avctx->width);
773 for (plane = 0; plane < s->bpp; plane++) {
774 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
775 decodeplane8(row, s->planebuf, s->planesize, plane);
778 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
779 for (y = 0; y < avctx->height ; y++ ) {
780 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
781 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
782 for (plane = 0; plane < s->bpp; plane++) {
783 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
784 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
786 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
788 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
789 for (y = 0; y < avctx->height ; y++) {
790 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
791 memset(s->ham_buf, 0, s->planesize * 8);
792 for (plane = 0; plane < s->bpp; plane++) {
793 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
794 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
796 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
798 } else { //AV_PIX_FMT_BGR32
799 for(y = 0; y < avctx->height ; y++ ) {
800 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
801 memset(row, 0, avctx->width << 2);
802 for (plane = 0; plane < s->bpp; plane++) {
803 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
804 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
808 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
809 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
810 for(y = 0; y < avctx->height ; y++ ) {
811 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
812 buf += decode_byterun(row, avctx->width, buf, buf_end);
814 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
815 for (y = 0; y < avctx->height ; y++) {
816 uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
817 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
818 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
821 return unsupported(avctx);
822 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP
823 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
824 if (av_get_bits_per_pixel(desc) == 32)
825 decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]);
827 return unsupported(avctx);
831 bytestream2_init(&gb, buf, buf_size);
832 if (avctx->codec_tag == MKTAG('R','G','B','8'))
833 decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
834 else if (avctx->codec_tag == MKTAG('R','G','B','N'))
835 decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
837 return unsupported(avctx);
840 if (avctx->codec_tag == MKTAG('D','E','E','P')) {
841 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
842 if (av_get_bits_per_pixel(desc) == 32)
843 decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc);
845 return unsupported(avctx);
847 return unsupported(avctx);
850 return unsupported(avctx);
853 if ((res = av_frame_ref(data, s->frame)) < 0)
861 static av_cold int decode_end(AVCodecContext *avctx)
863 IffContext *s = avctx->priv_data;
864 av_frame_free(&s->frame);
865 av_freep(&s->planebuf);
866 av_freep(&s->ham_buf);
867 av_freep(&s->ham_palbuf);
871 #if CONFIG_IFF_ILBM_DECODER
872 AVCodec ff_iff_ilbm_decoder = {
874 .type = AVMEDIA_TYPE_VIDEO,
875 .id = AV_CODEC_ID_IFF_ILBM,
876 .priv_data_size = sizeof(IffContext),
879 .decode = decode_frame,
880 .capabilities = CODEC_CAP_DR1,
881 .long_name = NULL_IF_CONFIG_SMALL("IFF"),
884 #if CONFIG_IFF_BYTERUN1_DECODER
885 AVCodec ff_iff_byterun1_decoder = {
887 .type = AVMEDIA_TYPE_VIDEO,
888 .id = AV_CODEC_ID_IFF_BYTERUN1,
889 .priv_data_size = sizeof(IffContext),
892 .decode = decode_frame,
893 .capabilities = CODEC_CAP_DR1,
894 .long_name = NULL_IF_CONFIG_SMALL("IFF"),