2
* Copyright (C) 2001-2004 Michael H. Schimek
3
* Copyright (C) 2000-2003 I�aki Garc�a Etxebarria
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
/* $Id: pixel_format.c,v 1.4 2005/01/20 01:38:33 mschimek Exp $ */
23
# include "config.h" /* Z_BYTE_ORDER */
27
#include "pixel_format.h"
30
tv_pixfmt_name (tv_pixfmt pixfmt)
35
#define CASE(s) case TV_PIXFMT_##s : return #s ;
52
/* AVUY32_BE synonyms */
73
/* ABGR32_BE synonyms */
109
case TV_PIXFMT_RESERVED0:
110
case TV_PIXFMT_RESERVED1:
111
case TV_PIXFMT_RESERVED2:
112
case TV_PIXFMT_RESERVED3:
119
#define PIXEL_FORMAT(pixfmt, colspc, bits_per_pixel, color_depth, \
120
uv_hshift, uv_vshift, big_endian, planar, \
121
vu_order, r, g, b, a) \
123
TV_PIXFMT_##pixfmt, \
132
.mask = { .rgb = { r, g, b, a } } }
134
#if Z_BYTE_ORDER == Z_LITTLE_ENDIAN
135
# define PACKED(fmt, colspc, bits_per_pixel, color_depth, big_endian, \
136
vu_order, x, y, z, a) \
137
[TV_PIXFMT_##fmt] = PIXEL_FORMAT (fmt, colspc, \
138
bits_per_pixel, color_depth, 0, 0, big_endian, \
139
FALSE, vu_order, x, y, z, a)
141
#elif Z_BYTE_ORDER == Z_BIG_ENDIAN
142
# define PACKED(fmt, colspc, bits_per_pixel, color_depth, big_endian, \
143
vu_order, x, y, z, a) \
144
[TV_PIXFMT_##fmt] = PIXEL_FORMAT (fmt, colspc, \
145
bits_per_pixel, color_depth, 0, 0, !(big_endian), \
146
FALSE, vu_order, x, y, z, a)
148
# error unknown endianess
151
#define PLANAR(fmt, color_depth, uv_hshift, uv_vshift, vu_order) \
152
[TV_PIXFMT_##fmt] = PIXEL_FORMAT (fmt, TV_COLSPC_YUV, 8, \
153
color_depth, uv_hshift, uv_vshift, FALSE, TRUE, \
154
vu_order, 0xFF, 0xFF, 0xFF, 0)
156
#define PACKED_YUV24(fmt, bpp, vu_order, x, y, z, a) \
157
PACKED(fmt##_LE, TV_COLSPC_YUV, \
158
bpp, 24, FALSE, vu_order, x, y, z, a), \
159
PACKED(fmt##_BE, TV_COLSPC_YUV, \
160
bpp, 24, TRUE, vu_order, x, y, z, a)
162
#define YUYV(fmt, vu_order) \
163
[TV_PIXFMT_##fmt] = PIXEL_FORMAT (fmt, TV_COLSPC_YUV, 16, \
164
16, 0, 0, FALSE, FALSE, vu_order, 0xFF, 0xFF, 0xFF, 0)
166
#define PACKED_RGB24(fmt, bpp, x, y, z, a) \
167
PACKED(fmt##_LE, TV_COLSPC_RGB, \
168
bpp, 24, FALSE, FALSE, x, y, z, a), \
169
PACKED(fmt##_BE, TV_COLSPC_RGB, \
170
bpp, 24, TRUE, FALSE, x, y, z, a)
172
#define PACKED16(fmt, x, y, z, a) \
173
PACKED(fmt##_LE, TV_COLSPC_RGB, \
174
16, 16, FALSE, FALSE, x, y, z, a), \
175
PACKED(fmt##_BE, TV_COLSPC_RGB, \
176
16, 16, TRUE, FALSE, x, y, z, a)
178
#define PACKED8(fmt, x, y, z, a) \
179
[TV_PIXFMT_##fmt] = PIXEL_FORMAT (fmt, TV_COLSPC_RGB, 8, 8, \
180
0, 0, FALSE, FALSE, FALSE, x, y, z, a)
182
static const tv_pixel_format
184
PLANAR (YUV444, 24, 0, 0, FALSE),
185
PLANAR (YVU444, 24, 0, 0, TRUE),
186
PLANAR (YUV422, 16, 1, 0, FALSE),
187
PLANAR (YVU422, 16, 1, 0, TRUE),
188
PLANAR (YUV411, 12, 2, 0, FALSE),
189
PLANAR (YVU411, 12, 2, 0, TRUE),
190
PLANAR (YUV420, 12, 1, 1, FALSE),
191
PLANAR (YVU420, 12, 1, 1, TRUE),
192
PLANAR (YUV410, 9, 2, 2, FALSE),
193
PLANAR (YVU410, 9, 2, 2, TRUE),
195
PACKED_YUV24 (YUVA32, 32, FALSE, 0xFF, 0xFF00, 0xFF0000, 0xFF000000),
196
PACKED_YUV24 (YVUA32, 32, TRUE, 0xFF, 0xFF0000, 0xFF00, 0xFF000000),
198
PACKED_YUV24 (YUV24, 24, FALSE, 0xFF, 0xFF00, 0xFF0000, 0),
199
PACKED_YUV24 (YVU24, 24, FALSE, 0xFF, 0xFF0000, 0xFF00, 0),
206
[TV_PIXFMT_Y8] = PIXEL_FORMAT (Y8, TV_COLSPC_YUV, 8, 8,
207
0, 0, FALSE, FALSE, FALSE,
210
PACKED_RGB24 (RGBA32, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000),
211
PACKED_RGB24 (BGRA32, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000),
213
PACKED (RGB24_LE, TV_COLSPC_RGB,
214
24, 24, FALSE, FALSE, 0xFF, 0xFF00, 0xFF0000, 0),
215
PACKED (BGR24_LE, TV_COLSPC_RGB,
216
24, 24, FALSE, FALSE, 0xFF0000, 0xFF00, 0xFF, 0),
218
PACKED16 (RGB16, 0x001F, 0x07E0, 0xF800, 0),
219
PACKED16 (BGR16, 0xF800, 0x07E0, 0x001F, 0),
221
PACKED16 (RGBA16, 0x001F, 0x03E0, 0x7C00, 0x8000),
222
PACKED16 (BGRA16, 0x7C00, 0x03E0, 0x001F, 0x8000),
223
PACKED16 (ARGB16, 0x003E, 0x07C0, 0xF800, 0x0001),
224
PACKED16 (ABGR16, 0xF800, 0x07C0, 0x003E, 0x0001),
226
PACKED16 (RGBA12, 0x000F, 0x00F0, 0x0F00, 0xF000),
227
PACKED16 (BGRA12, 0x0F00, 0x00F0, 0x000F, 0xF000),
228
PACKED16 (ARGB12, 0x00F0, 0x0F00, 0xF000, 0x000F),
229
PACKED16 (ABGR12, 0xF000, 0x0F00, 0x00F0, 0x000F),
231
PACKED8 (RGB8, 0x07, 0x38, 0xC0, 0),
232
PACKED8 (BGR8, 0xE0, 0x1C, 0x03, 0),
234
PACKED8 (RGBA8, 0x03, 0x1C, 0x60, 0x80),
235
PACKED8 (BGRA8, 0x60, 0x1C, 0x03, 0x80),
236
PACKED8 (ARGB8, 0x06, 0x38, 0xC0, 0x01),
237
PACKED8 (ABGR8, 0xC0, 0x38, 0x06, 0x01),
239
[TV_PIXFMT_SBGGR] = PIXEL_FORMAT (SBGGR, TV_COLSPC_RGB, 8, 24,
240
0, 0, FALSE, FALSE, FALSE,
241
0xFF, 0xFF, 0xFF, 0),
245
tv_pixfmt_bytes_per_pixel (tv_pixfmt pixfmt)
247
unsigned int index = (unsigned int) pixfmt;
249
if (index > N_ELEMENTS (pixel_formats))
252
return pixel_formats[index].bits_per_pixel >> 3;
255
const tv_pixel_format *
256
tv_pixel_format_from_pixfmt (tv_pixfmt pixfmt)
258
unsigned int index = (unsigned int) pixfmt;
259
const tv_pixel_format *pf;
261
if (index > N_ELEMENTS (pixel_formats))
264
pf = &pixel_formats[index];
266
if (0 == pf->bits_per_pixel)
272
/* Number of set bits. */
274
popcnt (unsigned int x)
276
x -= ((x >> 1) & 0x55555555);
277
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
278
x = (x + (x >> 4)) & 0x0F0F0F0F;
280
return (x * 0x01010101) >> 24;
283
/* Note this works only for RGB formats. */
285
tv_pixel_format_to_pixfmt (const tv_pixel_format *format)
287
unsigned int color_depth;
293
assert (NULL != format);
295
if (format->bits_per_pixel < 7
296
|| 0 == format->mask.rgb.r
297
|| 0 == format->mask.rgb.g
298
|| 0 == format->mask.rgb.b)
299
return TV_PIXFMT_UNKNOWN;
301
mask = format->mask.rgb.r | format->mask.rgb.g | format->mask.rgb.b;
303
if (format->mask.rgb.g > format->mask.rgb.r) {
304
if (format->mask.rgb.g > format->mask.rgb.b)
305
return TV_PIXFMT_UNKNOWN; /* GRB, GBR */
307
if (format->mask.rgb.b > format->mask.rgb.g)
308
return TV_PIXFMT_UNKNOWN; /* RBG, BRG */
311
color_depth = format->color_depth;
312
if (0 == color_depth)
313
color_depth = popcnt (mask);
315
mask_a = format->mask.rgb.a;
318
^ (0xFFFFFFFFUL >> (32 - format->bits_per_pixel));
321
if (mask_a > format->mask.rgb.r
322
|| format->mask.rgb.a > format->mask.rgb.b)
323
return TV_PIXFMT_UNKNOWN; /* XGAX, XAGX */
326
a_lsb = (mask >= mask_a);
327
r_msb = (format->mask.rgb.r >= format->mask.rgb.b);
329
switch (color_depth) {
331
if (32 == format->bits_per_pixel) {
332
static tv_pixfmt mapping [] = {
333
TV_PIXFMT_RGBA32_LE, TV_PIXFMT_RGBA32_BE,
334
TV_PIXFMT_BGRA32_LE, TV_PIXFMT_BGRA32_BE,
335
TV_PIXFMT_ARGB32_LE, TV_PIXFMT_ARGB32_BE,
336
TV_PIXFMT_ABGR32_LE, TV_PIXFMT_ABGR32_BE,
339
return mapping [a_lsb * 4 + r_msb * 2
340
+ format->big_endian];
342
static tv_pixfmt mapping [] = {
343
TV_PIXFMT_RGB24_LE, TV_PIXFMT_BGR24_LE
346
return mapping [r_msb];
351
static tv_pixfmt mapping [] = {
352
TV_PIXFMT_RGB16_LE, TV_PIXFMT_RGB16_BE,
353
TV_PIXFMT_BGR16_LE, TV_PIXFMT_BGR16_BE,
356
return mapping [r_msb * 2 + format->big_endian];
361
static tv_pixfmt mapping [] = {
362
TV_PIXFMT_RGBA16_LE, TV_PIXFMT_RGBA16_BE,
363
TV_PIXFMT_BGRA16_LE, TV_PIXFMT_BGRA16_BE,
364
TV_PIXFMT_ARGB16_LE, TV_PIXFMT_ARGB16_BE,
365
TV_PIXFMT_ABGR16_LE, TV_PIXFMT_ABGR16_BE,
368
return mapping [a_lsb * 4 + r_msb * 2 + format->big_endian];
373
static tv_pixfmt mapping [] = {
374
TV_PIXFMT_RGBA12_LE, TV_PIXFMT_RGBA12_BE,
375
TV_PIXFMT_BGRA12_LE, TV_PIXFMT_BGRA12_BE,
376
TV_PIXFMT_ARGB12_LE, TV_PIXFMT_ARGB12_BE,
377
TV_PIXFMT_ABGR12_LE, TV_PIXFMT_ABGR12_BE,
380
return mapping [a_lsb * 4 + r_msb * 2 + format->big_endian];
385
static tv_pixfmt mapping [] = {
386
TV_PIXFMT_RGB8, TV_PIXFMT_BGR8
389
return mapping [r_msb];
394
static tv_pixfmt mapping [] = {
395
TV_PIXFMT_RGBA8, TV_PIXFMT_BGRA8,
396
TV_PIXFMT_ARGB8, TV_PIXFMT_ABGR8,
399
return mapping [a_lsb * 2 + r_msb];
407
return TV_PIXFMT_UNKNOWN;