2 * IFF PBM/ILBM 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 PBM/ILBM bitmap decoder
28 #include "libavutil/imgutils.h"
29 #include "bytestream.h"
37 MASK_HAS_TRANSPARENT_COLOR,
45 uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation
46 uint32_t *ham_palbuf; ///< HAM decode table
47 uint32_t *mask_buf; ///< temporary buffer for palette indices
48 uint32_t *mask_palbuf; ///< masking palette table
49 unsigned compression; ///< delta compression method used
50 unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
51 unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
52 unsigned flags; ///< 1 for EHB, 0 is no extra half darkening
53 unsigned transparency; ///< TODO: transparency color index in palette
54 unsigned masking; ///< TODO: masking method used
55 int init; // 1 if buffer and palette data already initialized, 0 otherwise
58 #define LUT8_PART(plane, v) \
59 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
60 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
61 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
62 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
63 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
64 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
65 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
66 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
67 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
68 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
69 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
70 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
71 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
72 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
73 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
74 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
76 #define LUT8(plane) { \
77 LUT8_PART(plane, 0x0000000), \
78 LUT8_PART(plane, 0x1000000), \
79 LUT8_PART(plane, 0x0010000), \
80 LUT8_PART(plane, 0x1010000), \
81 LUT8_PART(plane, 0x0000100), \
82 LUT8_PART(plane, 0x1000100), \
83 LUT8_PART(plane, 0x0010100), \
84 LUT8_PART(plane, 0x1010100), \
85 LUT8_PART(plane, 0x0000001), \
86 LUT8_PART(plane, 0x1000001), \
87 LUT8_PART(plane, 0x0010001), \
88 LUT8_PART(plane, 0x1010001), \
89 LUT8_PART(plane, 0x0000101), \
90 LUT8_PART(plane, 0x1000101), \
91 LUT8_PART(plane, 0x0010101), \
92 LUT8_PART(plane, 0x1010101), \
95 // 8 planes * 8-bit mask
96 static const uint64_t plane8_lut[8][256] = {
97 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
98 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
101 #define LUT32(plane) { \
103 0, 0, 0, 1 << plane, \
104 0, 0, 1 << plane, 0, \
105 0, 0, 1 << plane, 1 << plane, \
106 0, 1 << plane, 0, 0, \
107 0, 1 << plane, 0, 1 << plane, \
108 0, 1 << plane, 1 << plane, 0, \
109 0, 1 << plane, 1 << plane, 1 << plane, \
110 1 << plane, 0, 0, 0, \
111 1 << plane, 0, 0, 1 << plane, \
112 1 << plane, 0, 1 << plane, 0, \
113 1 << plane, 0, 1 << plane, 1 << plane, \
114 1 << plane, 1 << plane, 0, 0, \
115 1 << plane, 1 << plane, 0, 1 << plane, \
116 1 << plane, 1 << plane, 1 << plane, 0, \
117 1 << plane, 1 << plane, 1 << plane, 1 << plane, \
120 // 32 planes * 4-bit mask * 4 lookup tables each
121 static const uint32_t plane32_lut[32][16*4] = {
122 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
123 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
124 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
125 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
126 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
127 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
128 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
129 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
132 // Gray to RGB, required for palette table of grayscale images with bpp < 8
133 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
134 return x << 16 | x << 8 | x;
138 * Convert CMAP buffer (stored in extradata) to lavc palette format
140 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
142 IffContext *s = avctx->priv_data;
144 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
145 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
147 if (avctx->bits_per_coded_sample > 8) {
148 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
149 return AVERROR_INVALIDDATA;
152 count = 1 << avctx->bits_per_coded_sample;
153 // If extradata is smaller than actually needed, fill the remaining with black.
154 count = FFMIN(palette_size / 3, count);
156 for (i=0; i < count; i++) {
157 pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
159 if (s->flags && count >= 32) { // EHB
160 for (i = 0; i < 32; i++)
161 pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1;
162 count = FFMAX(count, 64);
164 } else { // Create gray-scale color palette for bps < 8
165 count = 1 << avctx->bits_per_coded_sample;
167 for (i=0; i < count; i++) {
168 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
171 if (s->masking == MASK_HAS_MASK) {
172 memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4);
173 for (i = 0; i < count; i++)
175 } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR &&
176 s->transparency < 1 << avctx->bits_per_coded_sample)
177 pal[s->transparency] &= 0xFFFFFF;
182 * Extracts the IFF extra context and updates internal
183 * decoder structures.
185 * @param avctx the AVCodecContext where to extract extra context to
186 * @param avpkt the AVPacket to extract extra context from or NULL to use avctx
187 * @return 0 in case of success, a negative error code otherwise
189 static int extract_header(AVCodecContext *const avctx,
190 const AVPacket *const avpkt) {
193 IffContext *s = avctx->priv_data;
194 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
199 return AVERROR_INVALIDDATA;
200 image_size = avpkt->size - AV_RB16(avpkt->data);
202 buf_size = bytestream_get_be16(&buf);
203 if (buf_size <= 1 || image_size <= 1) {
204 av_log(avctx, AV_LOG_ERROR,
205 "Invalid image size received: %u -> image data offset: %d\n",
206 buf_size, image_size);
207 return AVERROR_INVALIDDATA;
210 if (avctx->extradata_size < 2)
211 return AVERROR_INVALIDDATA;
212 buf = avctx->extradata;
213 buf_size = bytestream_get_be16(&buf);
214 if (buf_size <= 1 || palette_size < 0) {
215 av_log(avctx, AV_LOG_ERROR,
216 "Invalid palette size received: %u -> palette data offset: %d\n",
217 buf_size, palette_size);
218 return AVERROR_INVALIDDATA;
223 s->compression = bytestream_get_byte(&buf);
224 s->bpp = bytestream_get_byte(&buf);
225 s->ham = bytestream_get_byte(&buf);
226 s->flags = bytestream_get_byte(&buf);
227 s->transparency = bytestream_get_be16(&buf);
228 s->masking = bytestream_get_byte(&buf);
229 if (s->masking == MASK_HAS_MASK) {
231 avctx->pix_fmt = PIX_FMT_RGB32;
232 av_freep(&s->mask_buf);
233 av_freep(&s->mask_palbuf);
234 s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE);
236 return AVERROR(ENOMEM);
237 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
238 if (!s->mask_palbuf) {
239 av_freep(&s->mask_buf);
240 return AVERROR(ENOMEM);
244 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
245 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
246 return AVERROR_PATCHWELCOME;
248 if (!s->bpp || s->bpp > 32) {
249 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
250 return AVERROR_INVALIDDATA;
251 } else if (s->ham >= 8) {
252 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
253 return AVERROR_INVALIDDATA;
256 av_freep(&s->ham_buf);
257 av_freep(&s->ham_palbuf);
260 int i, count = FFMIN(palette_size / 3, 1 << s->ham);
262 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
264 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
266 return AVERROR(ENOMEM);
268 ham_count = 8 * (1 << s->ham);
269 s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
270 if (!s->ham_palbuf) {
271 av_freep(&s->ham_buf);
272 return AVERROR(ENOMEM);
275 if (count) { // HAM with color palette attached
276 // prefill with black and palette and set HAM take direct value mask to zero
277 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
278 for (i=0; i < count; i++) {
279 s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
282 } else { // HAM with grayscale color palette
284 for (i=0; i < count; i++) {
285 s->ham_palbuf[i*2] = 0; // take direct color value from palette
286 s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
289 for (i=0; i < count; i++) {
290 uint32_t tmp = i << (8 - s->ham);
291 tmp |= tmp >> s->ham;
292 s->ham_palbuf[(i+count)*2] = 0x00FFFF; // just modify blue color component
293 s->ham_palbuf[(i+count*2)*2] = 0xFFFF00; // just modify red color component
294 s->ham_palbuf[(i+count*3)*2] = 0xFF00FF; // just modify green color component
295 s->ham_palbuf[(i+count)*2+1] = tmp << 16;
296 s->ham_palbuf[(i+count*2)*2+1] = tmp;
297 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
299 if (s->masking == MASK_HAS_MASK) {
300 for (i = 0; i < ham_count; i++)
301 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
309 static av_cold int decode_init(AVCodecContext *avctx)
311 IffContext *s = avctx->priv_data;
314 if (avctx->bits_per_coded_sample <= 8) {
315 int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
316 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
317 (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
318 } else if (avctx->bits_per_coded_sample <= 32) {
319 if (avctx->codec_tag != MKTAG('D','E','E','P'))
320 avctx->pix_fmt = PIX_FMT_BGR32;
322 return AVERROR_INVALIDDATA;
325 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
327 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
328 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
330 return AVERROR(ENOMEM);
332 s->bpp = avctx->bits_per_coded_sample;
333 avcodec_get_frame_defaults(&s->frame);
335 if ((err = extract_header(avctx, NULL)) < 0)
337 s->frame.reference = 3;
343 * Decode interleaved plane buffer up to 8bpp
344 * @param dst Destination buffer
345 * @param buf Source buffer
347 * @param plane plane number to decode as
349 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
351 const uint64_t *lut = plane8_lut[plane];
353 uint64_t v = AV_RN64A(dst) | lut[*buf++];
356 } while (--buf_size);
360 * Decode interleaved plane buffer up to 24bpp
361 * @param dst Destination buffer
362 * @param buf Source buffer
364 * @param plane plane number to decode as
366 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
368 const uint32_t *lut = plane32_lut[plane];
370 unsigned mask = (*buf >> 2) & ~3;
371 dst[0] |= lut[mask++];
372 dst[1] |= lut[mask++];
373 dst[2] |= lut[mask++];
375 mask = (*buf++ << 2) & 0x3F;
376 dst[4] |= lut[mask++];
377 dst[5] |= lut[mask++];
378 dst[6] |= lut[mask++];
381 } while (--buf_size);
384 #define DECODE_HAM_PLANE32(x) \
385 first = buf[x] << 1; \
386 second = buf[(x)+1] << 1; \
387 delta &= pal[first++]; \
388 delta |= pal[first]; \
390 delta &= pal[second++]; \
391 delta |= pal[second]; \
395 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
397 * @param dst the destination 24bpp buffer
398 * @param buf the source 8bpp chunky buffer
399 * @param pal the HAM decode table
400 * @param buf_size the plane size in bytes
402 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
403 const uint32_t *const pal, unsigned buf_size)
407 uint32_t first, second;
408 DECODE_HAM_PLANE32(0);
409 DECODE_HAM_PLANE32(2);
410 DECODE_HAM_PLANE32(4);
411 DECODE_HAM_PLANE32(6);
414 } while (--buf_size);
417 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
418 const uint32_t *const pal, unsigned width)
421 *dst++ = pal[*buf++];
426 * Decode one complete byterun1 encoded line.
428 * @param dst the destination buffer where to store decompressed bitstream
429 * @param dst_size the destination plane size in bytes
430 * @param buf the source byterun1 compressed bitstream
431 * @param buf_end the EOF of source byterun1 compressed bitstream
432 * @return number of consumed bytes in byterun1 compressed bitstream
434 static int decode_byterun(uint8_t *dst, int dst_size,
435 const uint8_t *buf, const uint8_t *const buf_end) {
436 const uint8_t *const buf_start = buf;
438 for (x = 0; x < dst_size && buf < buf_end;) {
440 const int8_t value = *buf++;
443 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
445 } else if (value > -128) {
447 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
453 return buf - buf_start;
456 static int decode_frame_ilbm(AVCodecContext *avctx,
457 void *data, int *data_size,
460 IffContext *s = avctx->priv_data;
461 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
462 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
463 const uint8_t *buf_end = buf+buf_size;
466 if ((res = extract_header(avctx, avpkt)) < 0)
470 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
471 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
474 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
475 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
477 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
478 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
483 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
484 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
485 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
486 for (plane = 0; plane < s->bpp; plane++) {
487 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
488 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
489 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
493 } else if (s->ham) { // HAM to PIX_FMT_BGR32
494 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
495 for(y = 0; y < avctx->height; y++) {
496 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
497 memset(s->ham_buf, 0, s->planesize * 8);
498 for (plane = 0; plane < s->bpp; plane++) {
499 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
500 if (start >= buf_end)
502 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
504 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
507 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
508 int raw_width = avctx->width * (av_get_bits_per_pixel(&av_pix_fmt_descriptors[avctx->pix_fmt]) >> 3);
510 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
511 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
512 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
514 if (avctx->pix_fmt == PIX_FMT_BGR32) {
515 for(x = 0; x < avctx->width; x++)
516 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
519 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
520 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
521 for(y = 0; y < avctx->height; y++ ) {
522 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
523 memset(row, 0, avctx->width);
524 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
525 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
529 } else if (s->ham) { // HAM to PIX_FMT_BGR32
530 for (y = 0; y < avctx->height; y++) {
531 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
532 memset(s->ham_buf, 0, s->planesize * 8);
533 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
534 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
537 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
539 } else { // PIX_FMT_BGR32
540 for(y = 0; y < avctx->height; y++ ) {
541 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
542 memset(row, 0, avctx->width << 2);
543 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
544 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
549 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
550 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
551 for(y = 0; y < avctx->height; y++ ) {
552 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
553 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
554 buf += avctx->width + (avctx->width % 2); // padding if odd
556 } else if (s->ham) { // IFF-PBM: HAM to PIX_FMT_BGR32
557 for (y = 0; y < avctx->height; y++) {
558 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
559 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
560 buf += avctx->width + (avctx->width & 1); // padding if odd
561 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
564 av_log_ask_for_sample(avctx, "unsupported bpp\n");
565 return AVERROR_INVALIDDATA;
569 *data_size = sizeof(AVFrame);
570 *(AVFrame*)data = s->frame;
574 static int decode_frame_byterun1(AVCodecContext *avctx,
575 void *data, int *data_size,
578 IffContext *s = avctx->priv_data;
579 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
580 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
581 const uint8_t *buf_end = buf+buf_size;
584 if ((res = extract_header(avctx, avpkt)) < 0)
587 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
588 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
591 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
592 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
594 } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
595 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
597 } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
598 if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
603 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
604 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
605 for(y = 0; y < avctx->height ; y++ ) {
606 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
607 memset(row, 0, avctx->width);
608 for (plane = 0; plane < s->bpp; plane++) {
609 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
610 decodeplane8(row, s->planebuf, s->planesize, plane);
613 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to PIX_FMT_BGR32
614 for (y = 0; y < avctx->height ; y++ ) {
615 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
616 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
617 for (plane = 0; plane < s->bpp; plane++) {
618 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
619 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
621 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
623 } else if (s->ham) { // HAM to PIX_FMT_BGR32
624 for (y = 0; y < avctx->height ; y++) {
625 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
626 memset(s->ham_buf, 0, s->planesize * 8);
627 for (plane = 0; plane < s->bpp; plane++) {
628 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
629 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
631 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
633 } else { //PIX_FMT_BGR32
634 for(y = 0; y < avctx->height ; y++ ) {
635 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
636 memset(row, 0, avctx->width << 2);
637 for (plane = 0; plane < s->bpp; plane++) {
638 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
639 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
643 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
644 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
645 for(y = 0; y < avctx->height ; y++ ) {
646 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
647 buf += decode_byterun(row, avctx->width, buf, buf_end);
649 } else if (s->ham) { // IFF-PBM: HAM to PIX_FMT_BGR32
650 for (y = 0; y < avctx->height ; y++) {
651 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
652 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
653 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
656 av_log_ask_for_sample(avctx, "unsupported bpp\n");
657 return AVERROR_INVALIDDATA;
661 *data_size = sizeof(AVFrame);
662 *(AVFrame*)data = s->frame;
666 static av_cold int decode_end(AVCodecContext *avctx)
668 IffContext *s = avctx->priv_data;
669 if (s->frame.data[0])
670 avctx->release_buffer(avctx, &s->frame);
671 av_freep(&s->planebuf);
672 av_freep(&s->ham_buf);
673 av_freep(&s->ham_palbuf);
677 AVCodec ff_iff_ilbm_decoder = {
679 .type = AVMEDIA_TYPE_VIDEO,
680 .id = CODEC_ID_IFF_ILBM,
681 .priv_data_size = sizeof(IffContext),
684 .decode = decode_frame_ilbm,
685 .capabilities = CODEC_CAP_DR1,
686 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
689 AVCodec ff_iff_byterun1_decoder = {
690 .name = "iff_byterun1",
691 .type = AVMEDIA_TYPE_VIDEO,
692 .id = CODEC_ID_IFF_BYTERUN1,
693 .priv_data_size = sizeof(IffContext),
696 .decode = decode_frame_byterun1,
697 .capabilities = CODEC_CAP_DR1,
698 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),