2 * BRender PIX (.pix) image decoder
3 * Copyright (c) 2012 Aleksi Nurmi
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 /* Tested against samples from I-War / Independence War and Defiance. */
24 #include "libavutil/imgutils.h"
27 #include "bytestream.h"
30 #define HEADER1_CHUNK 0x03
31 #define HEADER2_CHUNK 0x3D
32 #define IMAGE_DATA_CHUNK 0x21
34 /* In 8-bit colour mode, 256 colours are available at any time. Which 256
35 * colours are available is determined by the contents of the hardware palette
36 * (or CLUT). In this case, the palette supplied with BRender (std.pal) has
37 * been loaded into the CLUT.
39 * The 256 colours in std.pal are divided into seven ranges, or `colour ramps'.
40 * The first 64 colours represent shades of grey ranging from very dark grey
41 * (black) to very light grey (white). The following colours are 32-element
42 * ramps for six colours as shown below.
44 static const uint32_t std_pal_table[256] = {
46 0xFF000000, 0xFF030303, 0xFF060606, 0xFF090909, 0xFF0C0C0C, 0xFF0F0F0F,
47 0xFF121212, 0xFF151515, 0xFF181818, 0xFF1B1B1B, 0xFF1E1E1E, 0xFF212121,
48 0xFF242424, 0xFF272727, 0xFF2A2A2A, 0xFF2D2D2D, 0xFF313131, 0xFF343434,
49 0xFF373737, 0xFF3A3A3A, 0xFF3D3D3D, 0xFF404040, 0xFF434343, 0xFF464646,
50 0xFF494949, 0xFF4C4C4C, 0xFF4F4F4F, 0xFF525252, 0xFF555555, 0xFF585858,
51 0xFF5B5B5B, 0xFF5E5E5E, 0xFF626262, 0xFF656565, 0xFF686868, 0xFF6B6B6B,
52 0xFF6E6E6E, 0xFF717171, 0xFF747474, 0xFF777777, 0xFF7A7A7A, 0xFF7D7D7D,
53 0xFF808080, 0xFF838383, 0xFF868686, 0xFF898989, 0xFF8C8C8C, 0xFF8F8F8F,
54 0xFF939393, 0xFF999999, 0xFFA0A0A0, 0xFFA7A7A7, 0xFFAEAEAE, 0xFFB4B4B4,
55 0xFFBBBBBB, 0xFFC2C2C2, 0xFFC9C9C9, 0xFFCFCFCF, 0xFFD6D6D6, 0xFFDDDDDD,
56 0xFFE4E4E4, 0xFFEAEAEA, 0xFFF1F1F1, 0xFFF8F8F8,
59 0xFF000000, 0xFF020209, 0xFF050513, 0xFF07071D, 0xFF0A0A27, 0xFF0C0C31,
60 0xFF0F0F3B, 0xFF111145, 0xFF14144F, 0xFF161659, 0xFF181863, 0xFF1B1B6D,
61 0xFF1E1E77, 0xFF202080, 0xFF22228A, 0xFF252594, 0xFF28289E, 0xFF2A2AA8,
62 0xFF2D2DB2, 0xFF2F2FBC, 0xFF3131C6, 0xFF3434D0, 0xFF3737DA, 0xFF3939E4,
63 0xFF3C3CEE, 0xFF5454F0, 0xFF6C6CF2, 0xFF8585F4, 0xFF9D9DF6, 0xFFB5B5F8,
64 0xFFCECEFA, 0xFFE6E6FC,
67 0xFF000000, 0xFF020902, 0xFF051305, 0xFF071D07, 0xFF0A270A, 0xFF0C310C,
68 0xFF0F3B0F, 0xFF114511, 0xFF144F14, 0xFF165916, 0xFF186318, 0xFF1B6D1B,
69 0xFF1E771E, 0xFF208020, 0xFF228A22, 0xFF259425, 0xFF289E28, 0xFF2AA82A,
70 0xFF2DB22D, 0xFF2FBC2F, 0xFF31C631, 0xFF34D034, 0xFF37DA37, 0xFF39E439,
71 0xFF3CEE3C, 0xFF54F054, 0xFF6CF26C, 0xFF85F485, 0xFF9DF69D, 0xFFB5F8B5,
72 0xFFCEFACE, 0xFFE6FCE6,
75 0xFF000000, 0xFF020909, 0xFF051313, 0xFF071D1D, 0xFF0A2727, 0xFF0C3131,
76 0xFF0F3B3B, 0xFF114545, 0xFF144F4F, 0xFF165959, 0xFF186363, 0xFF1B6D6D,
77 0xFF1E7777, 0xFF208080, 0xFF228A8A, 0xFF259494, 0xFF289E9E, 0xFF2AA8A8,
78 0xFF2DB2B2, 0xFF2FBCBC, 0xFF31C6C6, 0xFF34D0D0, 0xFF37DADA, 0xFF39E4E4,
79 0xFF3CEEEE, 0xFF54F0F0, 0xFF6CF2F2, 0xFF85F4F4, 0xFF9DF6F6, 0xFFB5F8F8,
80 0xFFCEFAFA, 0xFFE6FCFC,
83 0xFF000000, 0xFF090202, 0xFF130505, 0xFF1D0707, 0xFF270A0A, 0xFF310C0C,
84 0xFF3B0F0F, 0xFF451111, 0xFF4F1414, 0xFF591616, 0xFF631818, 0xFF6D1B1B,
85 0xFF771E1E, 0xFF802020, 0xFF8A2222, 0xFF942525, 0xFF9E2828, 0xFFA82A2A,
86 0xFFB22D2D, 0xFFBC2F2F, 0xFFC63131, 0xFFD03434, 0xFFDA3737, 0xFFE43939,
87 0xFFEE3C3C, 0xFFF05454, 0xFFF26C6C, 0xFFF48585, 0xFFF69D9D, 0xFFF8B5B5,
88 0xFFFACECE, 0xFFFCE6E6,
91 0xFF000000, 0xFF090209, 0xFF130513, 0xFF1D071D, 0xFF270A27, 0xFF310C31,
92 0xFF3B0F3B, 0xFF451145, 0xFF4F144F, 0xFF591659, 0xFF631863, 0xFF6D1B6D,
93 0xFF771E77, 0xFF802080, 0xFF8A228A, 0xFF942594, 0xFF9E289E, 0xFFA82AA8,
94 0xFFB22DB2, 0xFFBC2FBC, 0xFFC631C6, 0xFFD034D0, 0xFFDA37DA, 0xFFE439E4,
95 0xFFEE3CEE, 0xFFF054F0, 0xFFF26CF2, 0xFFF485F4, 0xFFF69DF6, 0xFFF8B5F8,
96 0xFFFACEFA, 0xFFFCE6FC,
99 0xFF000000, 0xFF090902, 0xFF131305, 0xFF1D1D07, 0xFF27270A, 0xFF31310C,
100 0xFF3B3B0F, 0xFF454511, 0xFF4F4F14, 0xFF595916, 0xFF636318, 0xFF6D6D1B,
101 0xFF77771E, 0xFF808020, 0xFF8A8A22, 0xFF949425, 0xFF9E9E28, 0xFFA8A82A,
102 0xFFB2B22D, 0xFFBCBC2F, 0xFFC6C631, 0xFFD0D034, 0xFFDADA37, 0xFFE4E439,
103 0xFFEEEE3C, 0xFFF0F054, 0xFFF2F26C, 0xFFF4F485, 0xFFF6F69D, 0xFFF8F8B5,
104 0xFFFAFACE, 0xFFFCFCE6,
107 typedef struct PixHeader {
113 static int pix_decode_header(PixHeader *out, GetByteContext *pgb)
115 unsigned int header_len = bytestream2_get_be32(pgb);
117 out->format = bytestream2_get_byte(pgb);
118 bytestream2_skip(pgb, 2);
119 out->width = bytestream2_get_be16(pgb);
120 out->height = bytestream2_get_be16(pgb);
122 // the header is at least 11 bytes long; we read the first 7
124 return AVERROR_INVALIDDATA;
126 // skip the rest of the header
127 bytestream2_skip(pgb, header_len - 7);
132 static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
135 AVFrame *frame = data;
140 unsigned int bytes_pp;
141 unsigned int magic[4];
142 unsigned int chunk_type;
143 unsigned int data_len;
144 unsigned int bytes_per_scanline;
147 bytestream2_init(&gb, avpkt->data, avpkt->size);
149 magic[0] = bytestream2_get_be32(&gb);
150 magic[1] = bytestream2_get_be32(&gb);
151 magic[2] = bytestream2_get_be32(&gb);
152 magic[3] = bytestream2_get_be32(&gb);
154 if (magic[0] != 0x12 ||
158 av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file.\n");
159 return AVERROR_INVALIDDATA;
162 chunk_type = bytestream2_get_be32(&gb);
163 if (chunk_type != HEADER1_CHUNK && chunk_type != HEADER2_CHUNK) {
164 av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d.\n", chunk_type);
165 return AVERROR_INVALIDDATA;
168 ret = pix_decode_header(&hdr, &gb);
170 av_log(avctx, AV_LOG_ERROR, "Invalid header length.\n");
171 return AVERROR_INVALIDDATA;
173 switch (hdr.format) {
175 avctx->pix_fmt = AV_PIX_FMT_PAL8;
179 avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
183 avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
187 avctx->pix_fmt = AV_PIX_FMT_RGB24;
192 avctx->pix_fmt = AV_PIX_FMT_ARGB;
196 avctx->pix_fmt = AV_PIX_FMT_YA8;
200 avpriv_request_sample(avctx, "Format %d", hdr.format);
201 return AVERROR_PATCHWELCOME;
204 if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0)
207 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
210 chunk_type = bytestream2_get_be32(&gb);
212 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
213 (chunk_type == HEADER1_CHUNK ||
214 chunk_type == HEADER2_CHUNK)) {
215 /* read palette data from data[1] */
217 uint32_t *pal_out = (uint32_t *)frame->data[1];
219 ret = pix_decode_header(&palhdr, &gb);
221 av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n");
222 return AVERROR_INVALIDDATA;
224 if (palhdr.format != 7)
225 avpriv_request_sample(avctx, "Palette not in RGB format");
227 chunk_type = bytestream2_get_be32(&gb);
228 data_len = bytestream2_get_be32(&gb);
229 if (chunk_type != IMAGE_DATA_CHUNK ||
230 bytestream2_get_bytes_left(&gb) < data_len) {
231 av_log(avctx, AV_LOG_ERROR, "Invalid palette data.\n");
232 return AVERROR_INVALIDDATA;
235 // palette data is surrounded by 8 null bytes (both top and bottom)
236 bytestream2_skip(&gb, 8);
237 // convert to machine endian format (ARGB)
238 for (i = 0; i < 256; ++i)
239 *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb);
240 bytestream2_skip(&gb, 8);
242 frame->palette_has_changed = 1;
244 chunk_type = bytestream2_get_be32(&gb);
245 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
246 /* no palette supplied, use the default one */
247 uint32_t *pal_out = (uint32_t *)frame->data[1];
249 // TODO: add an AVOption to load custom palette files
250 av_log(avctx, AV_LOG_WARNING,
251 "Using default palette, colors might be off.\n");
252 memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256);
254 frame->palette_has_changed = 1;
257 data_len = bytestream2_get_be32(&gb);
258 bytestream2_skip(&gb, 8);
260 // read the image data to the buffer
261 bytes_per_scanline = bytes_pp * hdr.width;
262 if (chunk_type != IMAGE_DATA_CHUNK ||
263 data_len < bytes_per_scanline * hdr.height ||
264 bytestream2_get_bytes_left(&gb) < data_len) {
265 av_log(avctx, AV_LOG_ERROR, "Invalid image data.\n");
266 return AVERROR_INVALIDDATA;
269 av_image_copy_plane(frame->data[0], frame->linesize[0],
270 avpkt->data + bytestream2_tell(&gb),
272 bytes_per_scanline, hdr.height);
274 // make alpha opaque for XRGB
276 for (j = 0; j < frame->height; j++)
277 for (i = 0; i < frame->linesize[0]; i += 4)
278 frame->data[0][j * frame->linesize[0] + i] = 0xFF;
280 frame->pict_type = AV_PICTURE_TYPE_I;
281 frame->key_frame = 1;
287 AVCodec ff_brender_pix_decoder = {
288 .name = "brender_pix",
289 .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"),
290 .type = AVMEDIA_TYPE_VIDEO,
291 .id = AV_CODEC_ID_BRENDER_PIX,
292 .decode = pix_decode_frame,
293 .capabilities = CODEC_CAP_DR1,