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 ff_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('D','E','E','P')) {
339 if (avctx->bits_per_coded_sample == 24) {
340 avctx->pix_fmt = AV_PIX_FMT_RGB0;
341 } else if (avctx->bits_per_coded_sample == 32) {
342 avctx->pix_fmt = AV_PIX_FMT_BGR32;
344 av_log_ask_for_sample(avctx, "unknown bits_per_coded_sample\n");
345 return AVERROR_PATCHWELCOME;
349 return AVERROR_INVALIDDATA;
352 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
354 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
355 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
357 return AVERROR(ENOMEM);
359 s->bpp = avctx->bits_per_coded_sample;
360 avcodec_get_frame_defaults(&s->frame);
362 if ((err = extract_header(avctx, NULL)) < 0)
364 s->frame.reference = 3;
370 * Decode interleaved plane buffer up to 8bpp
371 * @param dst Destination buffer
372 * @param buf Source buffer
374 * @param plane plane number to decode as
376 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
378 const uint64_t *lut = plane8_lut[plane];
380 av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n");
384 uint64_t v = AV_RN64A(dst) | lut[*buf++];
387 } while (--buf_size);
391 * Decode interleaved plane buffer up to 24bpp
392 * @param dst Destination buffer
393 * @param buf Source buffer
395 * @param plane plane number to decode as
397 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
399 const uint32_t *lut = plane32_lut[plane];
401 unsigned mask = (*buf >> 2) & ~3;
402 dst[0] |= lut[mask++];
403 dst[1] |= lut[mask++];
404 dst[2] |= lut[mask++];
406 mask = (*buf++ << 2) & 0x3F;
407 dst[4] |= lut[mask++];
408 dst[5] |= lut[mask++];
409 dst[6] |= lut[mask++];
412 } while (--buf_size);
415 #define DECODE_HAM_PLANE32(x) \
416 first = buf[x] << 1; \
417 second = buf[(x)+1] << 1; \
418 delta &= pal[first++]; \
419 delta |= pal[first]; \
421 delta &= pal[second++]; \
422 delta |= pal[second]; \
426 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
428 * @param dst the destination 24bpp buffer
429 * @param buf the source 8bpp chunky buffer
430 * @param pal the HAM decode table
431 * @param buf_size the plane size in bytes
433 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
434 const uint32_t *const pal, unsigned buf_size)
436 uint32_t delta = pal[1]; /* first palette entry */
438 uint32_t first, second;
439 DECODE_HAM_PLANE32(0);
440 DECODE_HAM_PLANE32(2);
441 DECODE_HAM_PLANE32(4);
442 DECODE_HAM_PLANE32(6);
445 } while (--buf_size);
448 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
449 const uint32_t *const pal, unsigned width)
452 *dst++ = pal[*buf++];
457 * Decode one complete byterun1 encoded line.
459 * @param dst the destination buffer where to store decompressed bitstream
460 * @param dst_size the destination plane size in bytes
461 * @param buf the source byterun1 compressed bitstream
462 * @param buf_end the EOF of source byterun1 compressed bitstream
463 * @return number of consumed bytes in byterun1 compressed bitstream
465 static int decode_byterun(uint8_t *dst, int dst_size,
466 const uint8_t *buf, const uint8_t *const buf_end) {
467 const uint8_t *const buf_start = buf;
469 for (x = 0; x < dst_size && buf < buf_end;) {
471 const int8_t value = *buf++;
474 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
476 } else if (value > -128) {
478 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
484 return buf - buf_start;
488 * Decode DEEP RLE 32-bit buffer
489 * @param[out] dst Destination buffer
490 * @param[in] src Source buffer
491 * @param src_size Source buffer size (bytes)
492 * @param width Width of destination buffer (pixels)
493 * @param height Height of destination buffer (pixels)
494 * @param linesize Line size of destination buffer (bytes)
496 static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize)
498 const uint8_t *src_end = src + src_size;
500 while (src + 5 <= src_end) {
502 opcode = *(int8_t *)src++;
504 int size = opcode + 1;
505 for (i = 0; i < size; i++) {
506 int length = FFMIN(size - i, width);
507 memcpy(dst + y*linesize + x * 4, src, length * 4);
519 int size = -opcode + 1;
520 uint32_t pixel = AV_RL32(src);
521 for (i = 0; i < size; i++) {
522 *(uint32_t *)(dst + y*linesize + x * 4) = pixel;
537 * Decode DEEP TVDC 32-bit buffer
538 * @param[out] dst Destination buffer
539 * @param[in] src Source buffer
540 * @param src_size Source buffer size (bytes)
541 * @param width Width of destination buffer (pixels)
542 * @param height Height of destination buffer (pixels)
543 * @param linesize Line size of destination buffer (bytes)
544 * @param[int] tvdc TVDC lookup table
546 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)
548 int x = 0, y = 0, plane = 0;
552 for (i = 0; i < src_size * 2;) {
553 #define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4))
554 int d = tvdc[GETNIBBLE];
558 dst[y * linesize + x*4 + plane] = pixel;
561 if (i >= src_size * 2)
565 d = FFMIN(d, width - x);
566 for (j = 0; j < d; j++) {
567 dst[y * linesize + x*4 + plane] = pixel;
586 static int unsupported(AVCodecContext *avctx)
588 IffContext *s = avctx->priv_data;
589 av_log_ask_for_sample(avctx, "unsupported bitmap (compression %i, bpp %i, ham %i)\n", s->compression, s->bpp, s->ham);
590 return AVERROR_INVALIDDATA;
593 static int decode_frame(AVCodecContext *avctx,
594 void *data, int *got_frame,
597 IffContext *s = avctx->priv_data;
598 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
599 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
600 const uint8_t *buf_end = buf+buf_size;
603 if ((res = extract_header(avctx, avpkt)) < 0)
606 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
607 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
610 } else if ((res = ff_get_buffer(avctx, &s->frame)) < 0) {
611 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
613 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
614 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
616 } else if (avctx->pix_fmt == AV_PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
617 if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
622 switch (s->compression) {
624 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
625 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
626 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
627 for (plane = 0; plane < s->bpp; plane++) {
628 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
629 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
630 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
634 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
635 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
636 for(y = 0; y < avctx->height; y++) {
637 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
638 memset(s->ham_buf, 0, s->planesize * 8);
639 for (plane = 0; plane < s->bpp; plane++) {
640 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
641 if (start >= buf_end)
643 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
645 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
648 return unsupported(avctx);
649 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
650 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
651 int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
653 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
654 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
655 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
657 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
658 for(x = 0; x < avctx->width; x++)
659 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
662 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
663 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
664 for(y = 0; y < avctx->height; y++ ) {
665 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
666 memset(row, 0, avctx->width);
667 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
668 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
672 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
673 for (y = 0; y < avctx->height; y++) {
674 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
675 memset(s->ham_buf, 0, s->planesize * 8);
676 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
677 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
680 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
682 } else { // AV_PIX_FMT_BGR32
683 for(y = 0; y < avctx->height; y++ ) {
684 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
685 memset(row, 0, avctx->width << 2);
686 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
687 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
692 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
693 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
694 for(y = 0; y < avctx->height && buf_end > buf; y++ ) {
695 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
696 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
697 buf += avctx->width + (avctx->width % 2); // padding if odd
699 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
700 for (y = 0; y < avctx->height && buf_end > buf; y++) {
701 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
702 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
703 buf += avctx->width + (avctx->width & 1); // padding if odd
704 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
707 return unsupported(avctx);
711 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
712 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
713 for(y = 0; y < avctx->height ; y++ ) {
714 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
715 memset(row, 0, avctx->width);
716 for (plane = 0; plane < s->bpp; plane++) {
717 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
718 decodeplane8(row, s->planebuf, s->planesize, plane);
721 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
722 for (y = 0; y < avctx->height ; y++ ) {
723 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
724 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
725 for (plane = 0; plane < s->bpp; plane++) {
726 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
727 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
729 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
731 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
732 for (y = 0; y < avctx->height ; y++) {
733 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
734 memset(s->ham_buf, 0, s->planesize * 8);
735 for (plane = 0; plane < s->bpp; plane++) {
736 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
737 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
739 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
741 } else { //AV_PIX_FMT_BGR32
742 for(y = 0; y < avctx->height ; y++ ) {
743 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
744 memset(row, 0, avctx->width << 2);
745 for (plane = 0; plane < s->bpp; plane++) {
746 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
747 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
751 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
752 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
753 for(y = 0; y < avctx->height ; y++ ) {
754 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
755 buf += decode_byterun(row, avctx->width, buf, buf_end);
757 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
758 for (y = 0; y < avctx->height ; y++) {
759 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
760 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
761 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
764 return unsupported(avctx);
765 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP
766 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
767 if (av_get_bits_per_pixel(desc) == 32)
768 decode_deep_rle32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0]);
770 return unsupported(avctx);
774 if (avctx->codec_tag == MKTAG('D','E','E','P')) {
775 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
776 if (av_get_bits_per_pixel(desc) == 32)
777 decode_deep_tvdc32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0], s->tvdc);
779 return unsupported(avctx);
781 return unsupported(avctx);
784 return unsupported(avctx);
788 *(AVFrame*)data = s->frame;
792 static av_cold int decode_end(AVCodecContext *avctx)
794 IffContext *s = avctx->priv_data;
795 if (s->frame.data[0])
796 avctx->release_buffer(avctx, &s->frame);
797 av_freep(&s->planebuf);
798 av_freep(&s->ham_buf);
799 av_freep(&s->ham_palbuf);
803 #if CONFIG_IFF_ILBM_DECODER
804 AVCodec ff_iff_ilbm_decoder = {
806 .type = AVMEDIA_TYPE_VIDEO,
807 .id = AV_CODEC_ID_IFF_ILBM,
808 .priv_data_size = sizeof(IffContext),
811 .decode = decode_frame,
812 .capabilities = CODEC_CAP_DR1,
813 .long_name = NULL_IF_CONFIG_SMALL("IFF"),
816 #if CONFIG_IFF_BYTERUN1_DECODER
817 AVCodec ff_iff_byterun1_decoder = {
819 .type = AVMEDIA_TYPE_VIDEO,
820 .id = AV_CODEC_ID_IFF_BYTERUN1,
821 .priv_data_size = sizeof(IffContext),
824 .decode = decode_frame,
825 .capabilities = CODEC_CAP_DR1,
826 .long_name = NULL_IF_CONFIG_SMALL("IFF"),