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, "bits_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) {
234 if (s->bpp >= 8 && !s->ham) {
235 avctx->pix_fmt = AV_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);
242 av_log(avctx, AV_LOG_ERROR, "bpp %d too large for palette\n", s->bpp);
243 av_freep(&s->mask_buf);
244 return AVERROR(ENOMEM);
246 s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
247 if (!s->mask_palbuf) {
248 av_freep(&s->mask_buf);
249 return AVERROR(ENOMEM);
253 } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) {
254 av_log(avctx, AV_LOG_ERROR, "Masking not supported\n");
255 return AVERROR_PATCHWELCOME;
257 if (!s->bpp || s->bpp > 32) {
258 av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp);
259 return AVERROR_INVALIDDATA;
260 } else if (s->ham >= 8) {
261 av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham);
262 return AVERROR_INVALIDDATA;
265 av_freep(&s->ham_buf);
266 av_freep(&s->ham_palbuf);
269 int i, count = FFMIN(palette_size / 3, 1 << s->ham);
271 const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
273 s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
275 return AVERROR(ENOMEM);
277 ham_count = 8 * (1 << s->ham);
278 s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE);
279 if (!s->ham_palbuf) {
280 av_freep(&s->ham_buf);
281 return AVERROR(ENOMEM);
284 if (count) { // HAM with color palette attached
285 // prefill with black and palette and set HAM take direct value mask to zero
286 memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t));
287 for (i=0; i < count; i++) {
288 s->ham_palbuf[i*2+1] = 0xFF000000 | AV_RL24(palette + i*3);
291 } else { // HAM with grayscale color palette
293 for (i=0; i < count; i++) {
294 s->ham_palbuf[i*2] = 0xFF000000; // take direct color value from palette
295 s->ham_palbuf[i*2+1] = 0xFF000000 | av_le2ne32(gray2rgb((i * 255) >> s->ham));
298 for (i=0; i < count; i++) {
299 uint32_t tmp = i << (8 - s->ham);
300 tmp |= tmp >> s->ham;
301 s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; // just modify blue color component
302 s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; // just modify red color component
303 s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; // just modify green color component
304 s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16;
305 s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp;
306 s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8;
308 if (s->masking == MASK_HAS_MASK) {
309 for (i = 0; i < ham_count; i++)
310 s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
318 static av_cold int decode_init(AVCodecContext *avctx)
320 IffContext *s = avctx->priv_data;
323 if (avctx->bits_per_coded_sample <= 8) {
326 if (avctx->extradata_size >= 2)
327 palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
330 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) ||
331 (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8;
332 } else if (avctx->bits_per_coded_sample <= 32) {
333 if (avctx->codec_tag != MKTAG('D','E','E','P')) {
334 if (avctx->bits_per_coded_sample == 24) {
335 avctx->pix_fmt = AV_PIX_FMT_RGB0;
336 } else if (avctx->bits_per_coded_sample == 32) {
337 avctx->pix_fmt = AV_PIX_FMT_BGR32;
339 av_log_ask_for_sample(avctx, "unknown bits_per_coded_sample\n");
340 return AVERROR_PATCHWELCOME;
344 return AVERROR_INVALIDDATA;
347 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
349 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
350 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
352 return AVERROR(ENOMEM);
354 s->bpp = avctx->bits_per_coded_sample;
355 avcodec_get_frame_defaults(&s->frame);
357 if ((err = extract_header(avctx, NULL)) < 0)
359 s->frame.reference = 3;
365 * Decode interleaved plane buffer up to 8bpp
366 * @param dst Destination buffer
367 * @param buf Source buffer
369 * @param plane plane number to decode as
371 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
373 const uint64_t *lut = plane8_lut[plane];
375 av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n");
379 uint64_t v = AV_RN64A(dst) | lut[*buf++];
382 } while (--buf_size);
386 * Decode interleaved plane buffer up to 24bpp
387 * @param dst Destination buffer
388 * @param buf Source buffer
390 * @param plane plane number to decode as
392 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
394 const uint32_t *lut = plane32_lut[plane];
396 unsigned mask = (*buf >> 2) & ~3;
397 dst[0] |= lut[mask++];
398 dst[1] |= lut[mask++];
399 dst[2] |= lut[mask++];
401 mask = (*buf++ << 2) & 0x3F;
402 dst[4] |= lut[mask++];
403 dst[5] |= lut[mask++];
404 dst[6] |= lut[mask++];
407 } while (--buf_size);
410 #define DECODE_HAM_PLANE32(x) \
411 first = buf[x] << 1; \
412 second = buf[(x)+1] << 1; \
413 delta &= pal[first++]; \
414 delta |= pal[first]; \
416 delta &= pal[second++]; \
417 delta |= pal[second]; \
421 * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
423 * @param dst the destination 24bpp buffer
424 * @param buf the source 8bpp chunky buffer
425 * @param pal the HAM decode table
426 * @param buf_size the plane size in bytes
428 static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf,
429 const uint32_t *const pal, unsigned buf_size)
431 uint32_t delta = pal[1]; /* first palette entry */
433 uint32_t first, second;
434 DECODE_HAM_PLANE32(0);
435 DECODE_HAM_PLANE32(2);
436 DECODE_HAM_PLANE32(4);
437 DECODE_HAM_PLANE32(6);
440 } while (--buf_size);
443 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
444 const uint32_t *const pal, unsigned width)
447 *dst++ = pal[*buf++];
452 * Decode one complete byterun1 encoded line.
454 * @param dst the destination buffer where to store decompressed bitstream
455 * @param dst_size the destination plane size in bytes
456 * @param buf the source byterun1 compressed bitstream
457 * @param buf_end the EOF of source byterun1 compressed bitstream
458 * @return number of consumed bytes in byterun1 compressed bitstream
460 static int decode_byterun(uint8_t *dst, int dst_size,
461 const uint8_t *buf, const uint8_t *const buf_end) {
462 const uint8_t *const buf_start = buf;
464 for (x = 0; x < dst_size && buf < buf_end;) {
466 const int8_t value = *buf++;
469 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
471 } else if (value > -128) {
473 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
479 return buf - buf_start;
482 static int decode_frame_ilbm(AVCodecContext *avctx,
483 void *data, int *data_size,
486 IffContext *s = avctx->priv_data;
487 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
488 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
489 const uint8_t *buf_end = buf+buf_size;
492 if ((res = extract_header(avctx, avpkt)) < 0)
496 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
497 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
500 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
501 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
503 } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
504 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
509 if (avctx->codec_tag == MKTAG('A','C','B','M')) {
510 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
511 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
512 for (plane = 0; plane < s->bpp; plane++) {
513 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
514 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
515 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
519 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
520 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
521 for(y = 0; y < avctx->height; y++) {
522 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
523 memset(s->ham_buf, 0, s->planesize * 8);
524 for (plane = 0; plane < s->bpp; plane++) {
525 const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
526 if (start >= buf_end)
528 decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
530 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
533 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
534 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
535 int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
537 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
538 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
539 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
541 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
542 for(x = 0; x < avctx->width; x++)
543 row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
546 } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
547 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
548 for(y = 0; y < avctx->height; y++ ) {
549 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
550 memset(row, 0, avctx->width);
551 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
552 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
556 } else if (s->ham) { // HAM to AV_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 memset(s->ham_buf, 0, s->planesize * 8);
560 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
561 decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
564 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
566 } else { // AV_PIX_FMT_BGR32
567 for(y = 0; y < avctx->height; y++ ) {
568 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
569 memset(row, 0, avctx->width << 2);
570 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
571 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
576 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
577 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
578 for(y = 0; y < avctx->height && buf_end > buf; y++ ) {
579 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
580 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
581 buf += avctx->width + (avctx->width % 2); // padding if odd
583 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
584 for (y = 0; y < avctx->height && buf_end > buf; y++) {
585 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
586 memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
587 buf += avctx->width + (avctx->width & 1); // padding if odd
588 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
591 av_log_ask_for_sample(avctx, "unsupported bpp\n");
592 return AVERROR_INVALIDDATA;
596 *data_size = sizeof(AVFrame);
597 *(AVFrame*)data = s->frame;
602 * Decode DEEP RLE 32-bit buffer
603 * @param[out] dst Destination buffer
604 * @param[in] src Source buffer
605 * @param src_size Source buffer size (bytes)
606 * @param width Width of destination buffer (pixels)
607 * @param height Height of destination buffer (pixels)
608 * @param linesize Line size of destination buffer (bytes)
610 static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize)
612 const uint8_t *src_end = src + src_size;
614 while (src + 5 <= src_end) {
616 opcode = *(int8_t *)src++;
618 int size = opcode + 1;
619 for (i = 0; i < size; i++) {
620 int length = FFMIN(size - i, width);
621 memcpy(dst + y*linesize + x * 4, src, length * 4);
633 int size = -opcode + 1;
634 uint32_t pixel = AV_RL32(src);
635 for (i = 0; i < size; i++) {
636 *(uint32_t *)(dst + y*linesize + x * 4) = pixel;
650 static int decode_frame_byterun1(AVCodecContext *avctx,
651 void *data, int *data_size,
654 IffContext *s = avctx->priv_data;
655 const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
656 const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
657 const uint8_t *buf_end = buf+buf_size;
660 if ((res = extract_header(avctx, avpkt)) < 0)
663 if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
664 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
667 } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
668 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
670 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
671 if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
673 } else if (avctx->pix_fmt == AV_PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
674 if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
679 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
680 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
681 for(y = 0; y < avctx->height ; y++ ) {
682 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
683 memset(row, 0, avctx->width);
684 for (plane = 0; plane < s->bpp; plane++) {
685 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
686 decodeplane8(row, s->planebuf, s->planesize, plane);
689 } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
690 for (y = 0; y < avctx->height ; y++ ) {
691 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
692 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
693 for (plane = 0; plane < s->bpp; plane++) {
694 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
695 decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
697 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
699 } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
700 for (y = 0; y < avctx->height ; y++) {
701 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
702 memset(s->ham_buf, 0, s->planesize * 8);
703 for (plane = 0; plane < s->bpp; plane++) {
704 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
705 decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
707 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
709 } else { //AV_PIX_FMT_BGR32
710 for(y = 0; y < avctx->height ; y++ ) {
711 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
712 memset(row, 0, avctx->width << 2);
713 for (plane = 0; plane < s->bpp; plane++) {
714 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
715 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
719 } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
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 buf += decode_byterun(row, avctx->width, buf, buf_end);
725 } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
726 for (y = 0; y < avctx->height ; y++) {
727 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
728 buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
729 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
732 av_log_ask_for_sample(avctx, "unsupported bpp\n");
733 return AVERROR_INVALIDDATA;
735 } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP
736 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
737 if (av_get_bits_per_pixel(desc) == 32)
738 decode_deep_rle32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0]);
740 av_log_ask_for_sample(avctx, "unsupported bpp\n");
741 return AVERROR_INVALIDDATA;
745 *data_size = sizeof(AVFrame);
746 *(AVFrame*)data = s->frame;
750 static av_cold int decode_end(AVCodecContext *avctx)
752 IffContext *s = avctx->priv_data;
753 if (s->frame.data[0])
754 avctx->release_buffer(avctx, &s->frame);
755 av_freep(&s->planebuf);
756 av_freep(&s->ham_buf);
757 av_freep(&s->ham_palbuf);
761 #if CONFIG_IFF_ILBM_DECODER
762 AVCodec ff_iff_ilbm_decoder = {
764 .type = AVMEDIA_TYPE_VIDEO,
765 .id = AV_CODEC_ID_IFF_ILBM,
766 .priv_data_size = sizeof(IffContext),
769 .decode = decode_frame_ilbm,
770 .capabilities = CODEC_CAP_DR1,
771 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
774 #if CONFIG_IFF_BYTERUN1_DECODER
775 AVCodec ff_iff_byterun1_decoder = {
776 .name = "iff_byterun1",
777 .type = AVMEDIA_TYPE_VIDEO,
778 .id = AV_CODEC_ID_IFF_BYTERUN1,
779 .priv_data_size = sizeof(IffContext),
782 .decode = decode_frame_byterun1,
783 .capabilities = CODEC_CAP_DR1,
784 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),