]> git.sesse.net Git - ffmpeg/blob - libavcodec/iff.c
Simplify RGB32 png encoding.
[ffmpeg] / libavcodec / iff.c
1 /*
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>
5  *
6  * This file is part of FFmpeg.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 /**
24  * @file
25  * IFF PBM/ILBM bitmap decoder
26  */
27
28 #include "libavutil/imgutils.h"
29 #include "bytestream.h"
30 #include "avcodec.h"
31 #include "get_bits.h"
32
33 // TODO: masking bits
34 typedef enum {
35     MASK_NONE,
36     MASK_HAS_MASK,
37     MASK_HAS_TRANSPARENT_COLOR,
38     MASK_LASSO
39 } mask_type;
40
41 typedef struct {
42     AVFrame frame;
43     int planesize;
44     uint8_t * planebuf;
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
56 } IffContext;
57
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
75
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),                \
93 }
94
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),
99 };
100
101 #define LUT32(plane) {                                \
102              0,          0,          0,          0,   \
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,   \
118 }
119
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),
130 };
131
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;
135 }
136
137 /**
138  * Convert CMAP buffer (stored in extradata) to lavc palette format
139  */
140 static int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
141 {
142     IffContext *s = avctx->priv_data;
143     int count, i;
144     const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
145     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
146
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;
150     }
151
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);
155     if (count) {
156         for (i=0; i < count; i++) {
157             pal[i] = 0xFF000000 | AV_RB24(palette + i*3);
158         }
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);
163         }
164     } else { // Create gray-scale color palette for bps < 8
165         count = 1 << avctx->bits_per_coded_sample;
166
167         for (i=0; i < count; i++) {
168             pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
169         }
170     }
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++)
174             pal[i] &= 0xFFFFFF;
175     } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR &&
176         s->transparency < 1 << avctx->bits_per_coded_sample)
177         pal[s->transparency] &= 0xFFFFFF;
178     return 0;
179 }
180
181 /**
182  * Extracts the IFF extra context and updates internal
183  * decoder structures.
184  *
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
188  */
189 static int extract_header(AVCodecContext *const avctx,
190                           const AVPacket *const avpkt) {
191     const uint8_t *buf;
192     unsigned buf_size;
193     IffContext *s = avctx->priv_data;
194     int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
195
196     if (avpkt) {
197         int image_size;
198         if (avpkt->size < 2)
199             return AVERROR_INVALIDDATA;
200         image_size = avpkt->size - AV_RB16(avpkt->data);
201         buf = 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;
208         }
209     } else {
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;
219         }
220     }
221
222     if (buf_size > 8) {
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) {
230             if (s->bpp >= 8) {
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);
235                 if (!s->mask_buf)
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);
241                 }
242             }
243             s->bpp++;
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;
247         }
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;
254         }
255
256         av_freep(&s->ham_buf);
257         av_freep(&s->ham_palbuf);
258
259         if (s->ham) {
260             int i, count = FFMIN(palette_size / 3, 1 << s->ham);
261             int ham_count;
262             const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata);
263
264             s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE);
265             if (!s->ham_buf)
266                 return AVERROR(ENOMEM);
267
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);
273             }
274
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);
280                 }
281                 count = 1 << s->ham;
282             } else { // HAM with grayscale color palette
283                 count = 1 << s->ham;
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));
287                 }
288             }
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;
298             }
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;
302             }
303         }
304     }
305
306     return 0;
307 }
308
309 static av_cold int decode_init(AVCodecContext *avctx)
310 {
311     IffContext *s = avctx->priv_data;
312     int err;
313
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         avctx->pix_fmt = PIX_FMT_BGR32;
320     } else {
321         return AVERROR_INVALIDDATA;
322     }
323
324     if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
325         return err;
326     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
327     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
328     if (!s->planebuf)
329         return AVERROR(ENOMEM);
330
331     s->bpp = avctx->bits_per_coded_sample;
332     avcodec_get_frame_defaults(&s->frame);
333
334     if ((err = extract_header(avctx, NULL)) < 0)
335         return err;
336     s->frame.reference = 3;
337
338     return 0;
339 }
340
341 /**
342  * Decode interleaved plane buffer up to 8bpp
343  * @param dst Destination buffer
344  * @param buf Source buffer
345  * @param buf_size
346  * @param plane plane number to decode as
347  */
348 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
349 {
350     const uint64_t *lut = plane8_lut[plane];
351     do {
352         uint64_t v = AV_RN64A(dst) | lut[*buf++];
353         AV_WN64A(dst, v);
354         dst += 8;
355     } while (--buf_size);
356 }
357
358 /**
359  * Decode interleaved plane buffer up to 24bpp
360  * @param dst Destination buffer
361  * @param buf Source buffer
362  * @param buf_size
363  * @param plane plane number to decode as
364  */
365 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
366 {
367     const uint32_t *lut = plane32_lut[plane];
368     do {
369         unsigned mask = (*buf >> 2) & ~3;
370         dst[0] |= lut[mask++];
371         dst[1] |= lut[mask++];
372         dst[2] |= lut[mask++];
373         dst[3] |= lut[mask];
374         mask = (*buf++ << 2) & 0x3F;
375         dst[4] |= lut[mask++];
376         dst[5] |= lut[mask++];
377         dst[6] |= lut[mask++];
378         dst[7] |= lut[mask];
379         dst += 8;
380     } while (--buf_size);
381 }
382
383 #define DECODE_HAM_PLANE32(x)       \
384     first       = buf[x] << 1;      \
385     second      = buf[(x)+1] << 1;  \
386     delta      &= pal[first++];     \
387     delta      |= pal[first];       \
388     dst[x]      = delta;            \
389     delta      &= pal[second++];    \
390     delta      |= pal[second];      \
391     dst[(x)+1]  = delta
392
393 /**
394  * Converts one line of HAM6/8-encoded chunky buffer to 24bpp.
395  *
396  * @param dst the destination 24bpp buffer
397  * @param buf the source 8bpp chunky buffer
398  * @param pal the HAM decode table
399  * @param buf_size the plane size in bytes
400  */
401 static void decode_ham_plane32(uint32_t *dst, const uint8_t  *buf,
402                                const uint32_t *const pal, unsigned buf_size)
403 {
404     uint32_t delta = 0;
405     do {
406         uint32_t first, second;
407         DECODE_HAM_PLANE32(0);
408         DECODE_HAM_PLANE32(2);
409         DECODE_HAM_PLANE32(4);
410         DECODE_HAM_PLANE32(6);
411         buf += 8;
412         dst += 8;
413     } while (--buf_size);
414 }
415
416 static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
417                          const uint32_t *const pal, unsigned width)
418 {
419     do {
420         *dst++ = pal[*buf++];
421     } while (--width);
422 }
423
424 /**
425  * Decode one complete byterun1 encoded line.
426  *
427  * @param dst the destination buffer where to store decompressed bitstream
428  * @param dst_size the destination plane size in bytes
429  * @param buf the source byterun1 compressed bitstream
430  * @param buf_end the EOF of source byterun1 compressed bitstream
431  * @return number of consumed bytes in byterun1 compressed bitstream
432 */
433 static int decode_byterun(uint8_t *dst, int dst_size,
434                           const uint8_t *buf, const uint8_t *const buf_end) {
435     const uint8_t *const buf_start = buf;
436     unsigned x;
437     for (x = 0; x < dst_size && buf < buf_end;) {
438         unsigned length;
439         const int8_t value = *buf++;
440         if (value >= 0) {
441             length = value + 1;
442             memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
443             buf += length;
444         } else if (value > -128) {
445             length = -value + 1;
446             memset(dst + x, *buf++, FFMIN(length, dst_size - x));
447         } else { // noop
448             continue;
449         }
450         x += length;
451     }
452     return buf - buf_start;
453 }
454
455 static int decode_frame_ilbm(AVCodecContext *avctx,
456                             void *data, int *data_size,
457                             AVPacket *avpkt)
458 {
459     IffContext *s = avctx->priv_data;
460     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
461     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
462     const uint8_t *buf_end = buf+buf_size;
463     int y, plane, res;
464
465     if ((res = extract_header(avctx, avpkt)) < 0)
466         return res;
467
468     if (s->init) {
469         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
470             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
471             return res;
472         }
473     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
474         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
475         return res;
476     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt != PIX_FMT_GRAY8) {
477         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
478             return res;
479     }
480     s->init = 1;
481
482     if (avctx->codec_tag == MKTAG('A','C','B','M')) {
483         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
484             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
485             for (plane = 0; plane < s->bpp; plane++) {
486                 for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
487                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
488                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
489                     buf += s->planesize;
490                 }
491             }
492         } else if (s->ham) { // HAM to PIX_FMT_BGR32
493             memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
494             for(y = 0; y < avctx->height; y++) {
495                 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
496                 memset(s->ham_buf, 0, s->planesize * 8);
497                 for (plane = 0; plane < s->bpp; plane++) {
498                     const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
499                     if (start >= buf_end)
500                         break;
501                     decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
502                 }
503                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
504             }
505         }
506     } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
507         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
508             for(y = 0; y < avctx->height; y++ ) {
509                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
510                 memset(row, 0, avctx->width);
511                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
512                     decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
513                     buf += s->planesize;
514                 }
515             }
516         } else if (s->ham) { // HAM to PIX_FMT_BGR32
517             for (y = 0; y < avctx->height; y++) {
518                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
519                 memset(s->ham_buf, 0, s->planesize * 8);
520                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
521                     decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
522                     buf += s->planesize;
523                 }
524                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
525             }
526         } else { // PIX_FMT_BGR32
527             for(y = 0; y < avctx->height; y++ ) {
528                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
529                 memset(row, 0, avctx->width << 2);
530                 for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
531                     decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
532                     buf += s->planesize;
533                 }
534             }
535         }
536     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
537         for(y = 0; y < avctx->height; y++ ) {
538             uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
539             memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
540             buf += avctx->width + (avctx->width % 2); // padding if odd
541         }
542     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
543         for (y = 0; y < avctx->height; y++) {
544             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
545             memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
546             buf += avctx->width + (avctx->width & 1); // padding if odd
547             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
548         }
549     }
550
551     *data_size = sizeof(AVFrame);
552     *(AVFrame*)data = s->frame;
553     return buf_size;
554 }
555
556 static int decode_frame_byterun1(AVCodecContext *avctx,
557                             void *data, int *data_size,
558                             AVPacket *avpkt)
559 {
560     IffContext *s = avctx->priv_data;
561     const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
562     const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
563     const uint8_t *buf_end = buf+buf_size;
564     int y, plane, res;
565
566     if ((res = extract_header(avctx, avpkt)) < 0)
567         return res;
568     if (s->init) {
569         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
570             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
571             return res;
572         }
573     } else if ((res = avctx->get_buffer(avctx, &s->frame)) < 0) {
574         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
575         return res;
576     } else if (avctx->pix_fmt == PIX_FMT_PAL8) {
577         if ((res = ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
578             return res;
579     } else if (avctx->pix_fmt == PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
580         if ((res = ff_cmap_read_palette(avctx, s->mask_palbuf)) < 0)
581             return res;
582     }
583     s->init = 1;
584
585     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
586         if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) {
587             for(y = 0; y < avctx->height ; y++ ) {
588                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
589                 memset(row, 0, avctx->width);
590                 for (plane = 0; plane < s->bpp; plane++) {
591                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
592                     decodeplane8(row, s->planebuf, s->planesize, plane);
593                 }
594             }
595         } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to PIX_FMT_BGR32
596             for (y = 0; y < avctx->height ; y++ ) {
597                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
598                 memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
599                 for (plane = 0; plane < s->bpp; plane++) {
600                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
601                     decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
602                 }
603                 lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
604             }
605         } else if (s->ham) { // HAM to PIX_FMT_BGR32
606             for (y = 0; y < avctx->height ; y++) {
607                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
608                 memset(s->ham_buf, 0, s->planesize * 8);
609                 for (plane = 0; plane < s->bpp; plane++) {
610                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
611                     decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
612                 }
613                 decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
614             }
615         } else { //PIX_FMT_BGR32
616             for(y = 0; y < avctx->height ; y++ ) {
617                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
618                 memset(row, 0, avctx->width << 2);
619                 for (plane = 0; plane < s->bpp; plane++) {
620                     buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
621                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
622                 }
623             }
624         }
625     } else if (avctx->pix_fmt == PIX_FMT_PAL8 || avctx->pix_fmt == PIX_FMT_GRAY8) { // IFF-PBM
626         for(y = 0; y < avctx->height ; y++ ) {
627             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
628             buf += decode_byterun(row, avctx->width, buf, buf_end);
629         }
630     } else { // IFF-PBM: HAM to PIX_FMT_BGR32
631         for (y = 0; y < avctx->height ; y++) {
632             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
633             buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
634             decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, avctx->width);
635         }
636     }
637
638     *data_size = sizeof(AVFrame);
639     *(AVFrame*)data = s->frame;
640     return buf_size;
641 }
642
643 static av_cold int decode_end(AVCodecContext *avctx)
644 {
645     IffContext *s = avctx->priv_data;
646     if (s->frame.data[0])
647         avctx->release_buffer(avctx, &s->frame);
648     av_freep(&s->planebuf);
649     av_freep(&s->ham_buf);
650     av_freep(&s->ham_palbuf);
651     return 0;
652 }
653
654 AVCodec ff_iff_ilbm_decoder = {
655     .name           = "iff_ilbm",
656     .type           = AVMEDIA_TYPE_VIDEO,
657     .id             = CODEC_ID_IFF_ILBM,
658     .priv_data_size = sizeof(IffContext),
659     .init           = decode_init,
660     .close          = decode_end,
661     .decode         = decode_frame_ilbm,
662     .capabilities   = CODEC_CAP_DR1,
663     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
664 };
665
666 AVCodec ff_iff_byterun1_decoder = {
667     .name           = "iff_byterun1",
668     .type           = AVMEDIA_TYPE_VIDEO,
669     .id             = CODEC_ID_IFF_BYTERUN1,
670     .priv_data_size = sizeof(IffContext),
671     .init           = decode_init,
672     .close          = decode_end,
673     .decode         = decode_frame_byterun1,
674     .capabilities   = CODEC_CAP_DR1,
675     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
676 };