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 Libav.
8 * Libav 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 * Libav 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 Libav; 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"
38 int init; // 1 if buffer and palette data already initialized, 0 otherwise
41 #define LUT8_PART(plane, v) \
42 AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \
43 AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \
44 AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \
45 AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \
46 AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \
47 AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \
48 AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \
49 AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \
50 AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \
51 AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \
52 AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \
53 AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \
54 AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \
55 AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \
56 AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \
57 AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane
59 #define LUT8(plane) { \
60 LUT8_PART(plane, 0x0000000), \
61 LUT8_PART(plane, 0x1000000), \
62 LUT8_PART(plane, 0x0010000), \
63 LUT8_PART(plane, 0x1010000), \
64 LUT8_PART(plane, 0x0000100), \
65 LUT8_PART(plane, 0x1000100), \
66 LUT8_PART(plane, 0x0010100), \
67 LUT8_PART(plane, 0x1010100), \
68 LUT8_PART(plane, 0x0000001), \
69 LUT8_PART(plane, 0x1000001), \
70 LUT8_PART(plane, 0x0010001), \
71 LUT8_PART(plane, 0x1010001), \
72 LUT8_PART(plane, 0x0000101), \
73 LUT8_PART(plane, 0x1000101), \
74 LUT8_PART(plane, 0x0010101), \
75 LUT8_PART(plane, 0x1010101), \
78 // 8 planes * 8-bit mask
79 static const uint64_t plane8_lut[8][256] = {
80 LUT8(0), LUT8(1), LUT8(2), LUT8(3),
81 LUT8(4), LUT8(5), LUT8(6), LUT8(7),
84 #define LUT32(plane) { \
86 0, 0, 0, 1 << plane, \
87 0, 0, 1 << plane, 0, \
88 0, 0, 1 << plane, 1 << plane, \
89 0, 1 << plane, 0, 0, \
90 0, 1 << plane, 0, 1 << plane, \
91 0, 1 << plane, 1 << plane, 0, \
92 0, 1 << plane, 1 << plane, 1 << plane, \
93 1 << plane, 0, 0, 0, \
94 1 << plane, 0, 0, 1 << plane, \
95 1 << plane, 0, 1 << plane, 0, \
96 1 << plane, 0, 1 << plane, 1 << plane, \
97 1 << plane, 1 << plane, 0, 0, \
98 1 << plane, 1 << plane, 0, 1 << plane, \
99 1 << plane, 1 << plane, 1 << plane, 0, \
100 1 << plane, 1 << plane, 1 << plane, 1 << plane, \
103 // 32 planes * 4-bit mask * 4 lookup tables each
104 static const uint32_t plane32_lut[32][16*4] = {
105 LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
106 LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
107 LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
108 LUT32(12), LUT32(13), LUT32(14), LUT32(15),
109 LUT32(16), LUT32(17), LUT32(18), LUT32(19),
110 LUT32(20), LUT32(21), LUT32(22), LUT32(23),
111 LUT32(24), LUT32(25), LUT32(26), LUT32(27),
112 LUT32(28), LUT32(29), LUT32(30), LUT32(31),
115 // Gray to RGB, required for palette table of grayscale images with bpp < 8
116 static av_always_inline uint32_t gray2rgb(const uint32_t x) {
117 return x << 16 | x << 8 | x;
121 * Convert CMAP buffer (stored in extradata) to lavc palette format
123 static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
127 if (avctx->bits_per_coded_sample > 8) {
128 av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
129 return AVERROR_INVALIDDATA;
132 count = 1 << avctx->bits_per_coded_sample;
133 // If extradata is smaller than actually needed, fill the remaining with black.
134 count = FFMIN(avctx->extradata_size / 3, count);
136 for (i=0; i < count; i++) {
137 pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 );
139 } else { // Create gray-scale color palette for bps < 8
140 count = 1 << avctx->bits_per_coded_sample;
142 for (i=0; i < count; i++) {
143 pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample);
149 static av_cold int decode_init(AVCodecContext *avctx)
151 IffContext *s = avctx->priv_data;
154 if (avctx->bits_per_coded_sample <= 8) {
155 avctx->pix_fmt = (avctx->bits_per_coded_sample < 8 ||
156 avctx->extradata_size) ? AV_PIX_FMT_PAL8
158 } else if (avctx->bits_per_coded_sample <= 32) {
159 avctx->pix_fmt = AV_PIX_FMT_BGR32;
161 return AVERROR_INVALIDDATA;
164 if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx)))
166 s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
167 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
169 return AVERROR(ENOMEM);
171 avcodec_get_frame_defaults(&s->frame);
177 * Decode interleaved plane buffer up to 8bpp
178 * @param dst Destination buffer
179 * @param buf Source buffer
181 * @param plane plane number to decode as
183 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
185 const uint64_t *lut = plane8_lut[plane];
187 uint64_t v = AV_RN64A(dst) | lut[*buf++];
190 } while (--buf_size);
194 * Decode interleaved plane buffer up to 24bpp
195 * @param dst Destination buffer
196 * @param buf Source buffer
198 * @param plane plane number to decode as
200 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
202 const uint32_t *lut = plane32_lut[plane];
204 unsigned mask = (*buf >> 2) & ~3;
205 dst[0] |= lut[mask++];
206 dst[1] |= lut[mask++];
207 dst[2] |= lut[mask++];
209 mask = (*buf++ << 2) & 0x3F;
210 dst[4] |= lut[mask++];
211 dst[5] |= lut[mask++];
212 dst[6] |= lut[mask++];
215 } while (--buf_size);
219 * Decode one complete byterun1 encoded line.
221 * @param dst the destination buffer where to store decompressed bitstream
222 * @param dst_size the destination plane size in bytes
223 * @param buf the source byterun1 compressed bitstream
224 * @param buf_end the EOF of source byterun1 compressed bitstream
225 * @return number of consumed bytes in byterun1 compressed bitstream
227 static int decode_byterun(uint8_t *dst, int dst_size,
228 const uint8_t *buf, const uint8_t *const buf_end) {
229 const uint8_t *const buf_start = buf;
231 for (x = 0; x < dst_size && buf < buf_end;) {
233 const int8_t value = *buf++;
236 memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf));
238 } else if (value > -128) {
240 memset(dst + x, *buf++, FFMIN(length, dst_size - x));
246 return buf - buf_start;
249 static int decode_frame_ilbm(AVCodecContext *avctx,
250 void *data, int *got_frame,
253 IffContext *s = avctx->priv_data;
254 const uint8_t *buf = avpkt->data;
255 int buf_size = avpkt->size;
256 const uint8_t *buf_end = buf+buf_size;
259 if ((res = ff_reget_buffer(avctx, &s->frame)) < 0)
262 if (!s->init && avctx->bits_per_coded_sample <= 8 &&
263 avctx->pix_fmt != AV_PIX_FMT_GRAY8) {
264 if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
269 if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
270 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
271 for(y = 0; y < avctx->height; y++ ) {
272 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
273 memset(row, 0, avctx->width);
274 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
275 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
279 } else { // AV_PIX_FMT_BGR32
280 for(y = 0; y < avctx->height; y++ ) {
281 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
282 memset(row, 0, avctx->width << 2);
283 for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
284 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
289 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { // IFF-PBM
290 for(y = 0; y < avctx->height; y++ ) {
291 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
292 memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
293 buf += avctx->width + (avctx->width % 2); // padding if odd
297 if ((res = av_frame_ref(data, &s->frame)) < 0)
305 static int decode_frame_byterun1(AVCodecContext *avctx,
306 void *data, int *got_frame,
309 IffContext *s = avctx->priv_data;
310 const uint8_t *buf = avpkt->data;
311 int buf_size = avpkt->size;
312 const uint8_t *buf_end = buf+buf_size;
315 if ((res = ff_reget_buffer(avctx, &s->frame)) < 0)
318 if (!s->init && avctx->bits_per_coded_sample <= 8 &&
319 avctx->pix_fmt != AV_PIX_FMT_GRAY8) {
320 if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
325 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
326 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
327 for(y = 0; y < avctx->height ; y++ ) {
328 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
329 memset(row, 0, avctx->width);
330 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
331 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
332 decodeplane8(row, s->planebuf, s->planesize, plane);
335 } else { //AV_PIX_FMT_BGR32
336 for(y = 0; y < avctx->height ; y++ ) {
337 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
338 memset(row, 0, avctx->width << 2);
339 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
340 buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
341 decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
346 for(y = 0; y < avctx->height ; y++ ) {
347 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
348 buf += decode_byterun(row, avctx->width, buf, buf_end);
352 if ((res = av_frame_ref(data, &s->frame)) < 0)
360 static av_cold int decode_end(AVCodecContext *avctx)
362 IffContext *s = avctx->priv_data;
363 av_frame_unref(&s->frame);
364 av_freep(&s->planebuf);
368 AVCodec ff_iff_ilbm_decoder = {
370 .type = AVMEDIA_TYPE_VIDEO,
371 .id = AV_CODEC_ID_IFF_ILBM,
372 .priv_data_size = sizeof(IffContext),
375 .decode = decode_frame_ilbm,
376 .capabilities = CODEC_CAP_DR1,
377 .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
380 AVCodec ff_iff_byterun1_decoder = {
381 .name = "iff_byterun1",
382 .type = AVMEDIA_TYPE_VIDEO,
383 .id = AV_CODEC_ID_IFF_BYTERUN1,
384 .priv_data_size = sizeof(IffContext),
387 .decode = decode_frame_byterun1,
388 .capabilities = CODEC_CAP_DR1,
389 .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),