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;
196 if (avctx->extradata_size < 2) {
197 av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
198 return AVERROR_INVALIDDATA;
200 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
205 return AVERROR_INVALIDDATA;
206 image_size = avpkt->size - AV_RB16(avpkt->data);
208 buf_size = bytestream_get_be16(&buf);
209 if (buf_size <= 1 || image_size <= 1) {
210 av_log(avctx, AV_LOG_ERROR,
211 "Invalid image size received: %u -> image data offset: %d\n",
212 buf_size, image_size);
213 return AVERROR_INVALIDDATA;
216 buf = avctx->extradata;
217 buf_size = bytestream_get_be16(&buf);
218 if (buf_size <= 1 || palette_size < 0) {
219 av_log(avctx, AV_LOG_ERROR,
220 "Invalid palette size received: %u -> palette data offset: %d\n",
221 buf_size, palette_size);
222 return AVERROR_INVALIDDATA;
227 s->compression = bytestream_get_byte(&buf);
228 s->bpp = bytestream_get_byte(&buf);
229 s->ham = bytestream_get_byte(&buf);
230 s->flags = bytestream_get_byte(&buf);
231 s->transparency = bytestream_get_be16(&buf);
232 s->masking = bytestream_get_byte(&buf);
233 if (s->masking == MASK_HAS_MASK) {
235 avctx->pix_fmt = PIX_FMT_RGB32;
236 av_freep(&s->mask_buf);
237 av_freep(&s->mask_palbuf);
238 s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE);
240 return AVERROR(ENOMEM);
241 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
242 if (!s->mask_palbuf) {
243 av_freep(&s->mask_buf);
244 return AVERROR(ENOMEM);
248 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
249 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
250 return AVERROR_PATCHWELCOME;
252 if (!s->bpp || s->bpp > 32) {
253 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
254 return AVERROR_INVALIDDATA;
255 } else if (s->ham >= 8) {
256 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
257 return AVERROR_INVALIDDATA;
260 av_freep(&s->ham_buf);
261 av_freep(&s->ham_palbuf);
264 int i, count = FFMIN(palette_size / 3, 1 << s->ham);
266 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
268 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
270 return AVERROR(ENOMEM);
272 ham_count = 8 * (1 << s->ham);
273 s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
274 if (!s->ham_palbuf) {
275 av_freep(&s->ham_buf);
276 return AVERROR(ENOMEM);
279 if (count) { // HAM with color palette attached
280 // prefill with black and palette and set HAM take direct value mask to zero
281 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
282 for (i=0; i < count; i++) {
283 s->ham_palbuf[i*2+1] = AV_RL24(palette + i*3);
286 } else { // HAM with grayscale color palette
288 for (i=0; i < count; i++) {
289 s->ham_palbuf[i*2] = 0; // take direct color value from palette
290 s->ham_palbuf[i*2+1] = av_le2ne32(gray2rgb((i * 255) >> s->ham));
293 for (i=0; i < count; i++) {
294 uint32_t tmp = i << (8 - s->ham);
295 tmp |= tmp >> s->ham;
296 s->ham_palbuf[(i+count)*2] = 0x00FFFF; // just modify blue color component
297 s->ham_palbuf[(i+count*2)*2] = 0xFFFF00; // just modify red color component
298 s->ham_palbuf[(i+count*3)*2] = 0xFF00FF; // just modify green color component
299 s->ham_palbuf[(i+count)*2+1] = tmp << 16;
300 s->ham_palbuf[(i+count*2)*2+1] = tmp;
301 s->ham_palbuf[(i+count*3)*2+1] = tmp << 8;
303 if (s->masking == MASK_HAS_MASK) {
304 for (i = 0; i < ham_count; i++)
305 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
313 static av_cold int decode_init(AVCodecContext *avctx)
315 IffContext *s = avctx->priv_data;
318 if (avctx->bits_per_coded_sample <= 8) {
321 if (avctx->extradata_size >= 2)
322 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
325 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
326 (avctx->extradata_size >= 2 && palette_size) ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
327 } else if (avctx->bits_per_coded_sample <= 32) {
328 if (avctx->codec_tag != MKTAG('D','E','E','P'))
329 avctx->pix_fmt = PIX_FMT_BGR32;
331 return AVERROR_INVALIDDATA;
334 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
336 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
337 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
339 return AVERROR(ENOMEM);
341 s->bpp = avctx->bits_per_coded_sample;
342 avcodec_get_frame_defaults(&s->frame);
344 if ((err = extract_header(avctx, NULL)) < 0)
346 s->frame.reference = 3;
352 * Decode interleaved plane buffer up to 8bpp
353 * @param dst Destination buffer
354 * @param buf Source buffer
356 * @param plane plane number to decode as
358 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
360 const uint64_t *lut = plane8_lut[plane];
362 uint64_t v = AV_RN64A(dst) | lut[*buf++];
365 } while (--buf_size);
369 * Decode interleaved plane buffer up to 24bpp
370 * @param dst Destination buffer
371 * @param buf Source buffer
373 * @param plane plane number to decode as
375 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
377 const uint32_t *lut = plane32_lut[plane];
379 unsigned mask = (*buf >> 2) & ~3;
380 dst[0] |= lut[mask++];
381 dst[1] |= lut[mask++];
382 dst[2] |= lut[mask++];
384 mask = (*buf++ << 2) & 0x3F;
385 dst[4] |= lut[mask++];
386 dst[5] |= lut[mask++];
387 dst[6] |= lut[mask++];
390 } while (--buf_size);
393 #define DECODE_HAM_PLANE32(x) \
394 first = buf[x] << 1; \
395 second = buf[(x)+1] << 1; \
396 delta &= pal[first++]; \
397 delta |= pal[first]; \
399 delta &= pal[second++]; \
400 delta |= pal[second]; \
404 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
406 * @param dst the destination 24bpp buffer
407 * @param buf the source 8bpp chunky buffer
408 * @param pal the HAM decode table
409 * @param buf_size the plane size in bytes
411 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
412 const uint32_t *const pal, unsigned buf_size)
416 uint32_t first, second;
417 DECODE_HAM_PLANE32(0);
418 DECODE_HAM_PLANE32(2);
419 DECODE_HAM_PLANE32(4);
420 DECODE_HAM_PLANE32(6);
423 } while (--buf_size);
426 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
427 const uint32_t *const pal, unsigned width)
430 *dst++ = pal[*buf++];
435 * Decode one complete byterun1 encoded line.
437 * @param dst the destination buffer where to store decompressed bitstream
438 * @param dst_size the destination plane size in bytes
439 * @param buf the source byterun1 compressed bitstream
440 * @param buf_end the EOF of source byterun1 compressed bitstream
441 * @return number of consumed bytes in byterun1 compressed bitstream
443 static int decode_byterun(uint8_t *dst, int dst_size,
444 const uint8_t *buf, const uint8_t *const buf_end) {
445 const uint8_t *const buf_start = buf;
447 for (x = 0; x < dst_size && buf < buf_end;) {
449 const int8_t value = *buf++;
452 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
454 } else if (value > -128) {
456 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
462 return buf - buf_start;
465 static int decode_frame_ilbm(AVCodecContext *avctx,
466 void *data, int *data_size,
469 IffContext *s = avctx->priv_data;
470 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
471 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
472 const uint8_t *buf_end = buf+buf_size;
475 if ((res = extract_header(avctx, avpkt)) < 0)
479 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
480 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
483 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
484 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
486 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == PIX_FMT_PAL8) {
487 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
492 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
493 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
494 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
495 for (plane = 0; plane < s->bpp; plane++) {
496 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
497 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
498 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
502 } else if (s->ham) { // HAM to PIX_FMT_BGR32
503 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
504 for(y = 0; y < avctx->height; y++) {
505 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
506 memset(s->ham_buf, 0, s->planesize * 8);
507 for (plane = 0; plane < s->bpp; plane++) {
508 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
509 if (start >= buf_end)
511 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
513 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
516 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
517 int raw_width = avctx->width * (av_get_bits_per_pixel(&av_pix_fmt_descriptors[avctx->pix_fmt]) >> 3);
519 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
520 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
521 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
523 if (avctx->pix_fmt == PIX_FMT_BGR32) {
524 for(x = 0; x < avctx->width; x++)
525 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
528 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
529 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
530 for(y = 0; y < avctx->height; y++ ) {
531 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
532 memset(row, 0, avctx->width);
533 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
534 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
538 } else if (s->ham) { // HAM to PIX_FMT_BGR32
539 for (y = 0; y < avctx->height; y++) {
540 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
541 memset(s->ham_buf, 0, s->planesize * 8);
542 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
543 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
546 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
548 } else { // PIX_FMT_BGR32
549 for(y = 0; y < avctx->height; y++ ) {
550 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
551 memset(row, 0, avctx->width << 2);
552 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
553 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
558 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
559 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
560 for(y = 0; y < avctx->height; y++ ) {
561 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
562 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
563 buf += avctx->width + (avctx->width % 2); // padding if odd
565 } else if (s->ham) { // IFF-PBM: HAM to PIX_FMT_BGR32
566 for (y = 0; y < avctx->height; y++) {
567 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
568 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
569 buf += avctx->width + (avctx->width & 1); // padding if odd
570 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
573 av_log_ask_for_sample(avctx, "unsupported bpp\n");
574 return AVERROR_INVALIDDATA;
578 *data_size = sizeof(AVFrame);
579 *(AVFrame*)data = s->frame;
583 static int decode_frame_byterun1(AVCodecContext *avctx,
584 void *data, int *data_size,
587 IffContext *s = avctx->priv_data;
588 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
589 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
590 const uint8_t *buf_end = buf+buf_size;
593 if ((res = extract_header(avctx, avpkt)) < 0)
596 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
597 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
600 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
601 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
603 } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
604 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
606 } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
607 if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
612 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
613 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
614 for(y = 0; y < avctx->height ; y++ ) {
615 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
616 memset(row, 0, avctx->width);
617 for (plane = 0; plane < s->bpp; plane++) {
618 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
619 decodeplane8(row, s->planebuf, s->planesize, plane);
622 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to PIX_FMT_BGR32
623 for (y = 0; y < avctx->height ; y++ ) {
624 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
625 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
626 for (plane = 0; plane < s->bpp; plane++) {
627 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
628 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
630 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
632 } else if (s->ham) { // HAM to PIX_FMT_BGR32
633 for (y = 0; y < avctx->height ; y++) {
634 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
635 memset(s->ham_buf, 0, s->planesize * 8);
636 for (plane = 0; plane < s->bpp; plane++) {
637 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
638 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
640 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
642 } else { //PIX_FMT_BGR32
643 for(y = 0; y < avctx->height ; y++ ) {
644 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
645 memset(row, 0, avctx->width << 2);
646 for (plane = 0; plane < s->bpp; plane++) {
647 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
648 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
652 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
653 if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
654 for(y = 0; y < avctx->height ; y++ ) {
655 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
656 buf += decode_byterun(row, avctx->width, buf, buf_end);
658 } else if (s->ham) { // IFF-PBM: HAM to PIX_FMT_BGR32
659 for (y = 0; y < avctx->height ; y++) {
660 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
661 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
662 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
665 av_log_ask_for_sample(avctx, "unsupported bpp\n");
666 return AVERROR_INVALIDDATA;
670 *data_size = sizeof(AVFrame);
671 *(AVFrame*)data = s->frame;
675 static av_cold int decode_end(AVCodecContext *avctx)
677 IffContext *s = avctx->priv_data;
678 if (s->frame.data[0])
679 avctx->release_buffer(avctx, &s->frame);
680 av_freep(&s->planebuf);
681 av_freep(&s->ham_buf);
682 av_freep(&s->ham_palbuf);
686 AVCodec ff_iff_ilbm_decoder = {
688 .type = AVMEDIA_TYPE_VIDEO,
689 .id = CODEC_ID_IFF_ILBM,
690 .priv_data_size = sizeof(IffContext),
693 .decode = decode_frame_ilbm,
694 .capabilities = CODEC_CAP_DR1,
695 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
698 AVCodec ff_iff_byterun1_decoder = {
699 .name = "iff_byterun1",
700 .type = AVMEDIA_TYPE_VIDEO,
701 .id = CODEC_ID_IFF_BYTERUN1,
702 .priv_data_size = sizeof(IffContext),
705 .decode = decode_frame_byterun1,
706 .capabilities = CODEC_CAP_DR1,
707 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),