2002-04-13 02:09:18 +00:00
|
|
|
In general
|
|
|
|
==========
|
2002-03-24 18:42:05 +00:00
|
|
|
|
2002-04-13 02:09:18 +00:00
|
|
|
There are planar and packed modes.
|
2005-03-31 22:45:03 +00:00
|
|
|
- Planar mode means: You have 3 separate images, one for each component,
|
2002-04-20 21:01:41 +00:00
|
|
|
each image 8 bits/pixel. To get the real colored pixel, you have to
|
2002-04-13 02:09:18 +00:00
|
|
|
mix the components from all planes. The resolution of planes may differ!
|
|
|
|
- Packed mode means: you have all components mixed/interleaved together,
|
|
|
|
so you have small "packs" of components in a single, big image.
|
2002-03-24 18:42:05 +00:00
|
|
|
|
2002-04-13 02:09:18 +00:00
|
|
|
There are RGB and YUV colorspaces.
|
2005-03-31 22:45:03 +00:00
|
|
|
- RGB: Red, Green and Blue components. Used by analog VGA monitors.
|
2002-04-13 02:09:18 +00:00
|
|
|
- YUV: Luminance (Y) and Chrominance (U,V) components. Used by some
|
2005-03-31 22:45:03 +00:00
|
|
|
video systems, like PAL. Also most M(J)PEG/DCT based codecs use this.
|
2002-04-13 02:09:18 +00:00
|
|
|
|
|
|
|
With YUV, they used to reduce the resolution of U,V planes:
|
|
|
|
The most common YUV formats:
|
2005-03-31 22:45:03 +00:00
|
|
|
FOURCC: bpp: IEEE: plane sizes: (w=width h=height of original image)
|
2002-10-22 01:22:35 +00:00
|
|
|
444P 24 YUV 4:4:4 Y: w * h U,V: w * h
|
|
|
|
YUY2,UYVY 16 YUV 4:2:2 Y: w * h U,V: (w/2) * h [MJPEG]
|
2005-03-31 22:45:03 +00:00
|
|
|
YV12,I420 12 YUV 4:2:0 Y: w * h U,V: (w/2) * (h/2) [MPEG, H.263]
|
2002-10-22 01:22:35 +00:00
|
|
|
411P 12 YUV 4:1:1 Y: w * h U,V: (w/4) * h [DV-NTSC, CYUV]
|
|
|
|
YVU9,IF09 9 YUV 4:1:0 Y: w * h U,V: (w/4) * (h/4) [Sorenson, Indeo]
|
2002-04-13 02:09:18 +00:00
|
|
|
|
2003-01-06 01:07:17 +00:00
|
|
|
The YUV a:b:c naming style means: for <a> samples of Y there are <b> samples
|
|
|
|
of UV in odd lines and <c> samples of UV in even lines.
|
|
|
|
|
2002-04-13 02:09:18 +00:00
|
|
|
conversion: (some cut'n'paste from www and maillist)
|
2002-03-24 18:42:05 +00:00
|
|
|
|
|
|
|
RGB to YUV Conversion:
|
|
|
|
Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
|
|
|
|
Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
|
|
|
|
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
|
|
|
|
YUV to RGB Conversion:
|
|
|
|
B = 1.164(Y - 16) + 2.018(U - 128)
|
|
|
|
G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
|
|
|
|
R = 1.164(Y - 16) + 1.596(V - 128)
|
|
|
|
|
|
|
|
In both these cases, you have to clamp the output values to keep them in
|
|
|
|
the [0-255] range. Rumour has it that the valid range is actually a subset
|
|
|
|
of [0-255] (I've seen an RGB range of [16-235] mentioned) but clamping the
|
|
|
|
values into [0-255] seems to produce acceptable results to me.
|
|
|
|
|
2005-03-31 22:45:03 +00:00
|
|
|
Julien (sorry, I can't recall his surname) suggests that there are
|
|
|
|
problems with the above formula and proposes the following instead:
|
2002-04-20 21:01:41 +00:00
|
|
|
Y = 0.299R + 0.587G + 0.114B
|
2002-03-24 18:42:05 +00:00
|
|
|
Cb = U'= (B-Y)*0.565
|
|
|
|
Cr = V'= (R-Y)*0.713
|
|
|
|
with reciprocal versions:
|
|
|
|
R = Y + 1.403V'
|
|
|
|
G = Y - 0.344U' - 0.714V'
|
|
|
|
B = Y + 1.770U'
|
2005-03-31 22:45:03 +00:00
|
|
|
Note: This formula doesn't contain the +128 offsets of U,V values!
|
2002-03-24 18:42:05 +00:00
|
|
|
|
|
|
|
Conclusion:
|
|
|
|
Y = luminance, the weighted average of R G B components. (0=black 255=white)
|
|
|
|
U = Cb = blue component (0=green 128=grey 255=blue)
|
2002-03-24 18:44:15 +00:00
|
|
|
V = Cr = red component (0=green 128=grey 255=red)
|
2002-03-24 18:42:05 +00:00
|
|
|
|
2002-04-13 02:09:18 +00:00
|
|
|
|
|
|
|
Huh. The planar YUV modes.
|
|
|
|
==========================
|
|
|
|
|
2002-04-20 21:01:41 +00:00
|
|
|
The most misunderstood thingie...
|
2002-04-13 02:09:18 +00:00
|
|
|
|
2002-03-24 18:42:05 +00:00
|
|
|
In MPlayer, we usually have 3 pointers to the Y, U and V planes, so it
|
2005-03-31 22:45:03 +00:00
|
|
|
doesn't matter what the order of the planes in the memory is:
|
2002-03-24 18:44:15 +00:00
|
|
|
for mp_image_t and libvo's draw_slice():
|
2010-04-12 10:56:17 +00:00
|
|
|
planes[0] = Y = luminance
|
|
|
|
planes[1] = U = Cb = blue
|
|
|
|
planes[2] = V = Cr = red
|
2005-03-31 22:45:03 +00:00
|
|
|
Note: planes[1] is ALWAYS U, and planes[2] is V, the FOURCC
|
|
|
|
(YV12 vs. I420) doesn't matter here! So, every codec using 3 pointers
|
|
|
|
(not only the first one) normally supports YV12 and I420 (=IYUV), too!
|
2002-03-24 18:44:15 +00:00
|
|
|
|
2005-03-31 22:45:03 +00:00
|
|
|
But there are some codecs (VfW, dshow) and vo drivers (xv) ignoring the 2nd
|
|
|
|
and 3rd pointer that use only a single pointer to the planar YUV image. In
|
2002-03-24 18:42:05 +00:00
|
|
|
this case we must know the right order and alignment of planes in the memory!
|
|
|
|
|
|
|
|
from the webartz fourcc list:
|
|
|
|
YV12: 12 bpp, full sized Y plane followed by 2x2 subsampled V and U planes
|
|
|
|
I420: 12 bpp, full sized Y plane followed by 2x2 subsampled U and V planes
|
|
|
|
IYUV: the same as I420
|
|
|
|
YVU9: 9 bpp, full sized Y plane followed by 4x4 subsampled V and U planes
|
|
|
|
|
2002-04-13 02:17:43 +00:00
|
|
|
Huh 2. RGB vs. BGR ?
|
|
|
|
====================
|
|
|
|
|
2002-04-20 21:01:41 +00:00
|
|
|
The 2nd most misunderstood thingie...
|
2002-04-13 02:17:43 +00:00
|
|
|
|
|
|
|
You know, there are Intel and Motorola, and they use different byteorder.
|
2005-03-31 22:45:03 +00:00
|
|
|
There are also others, like MIPS or Alpha, but all follow either Intel
|
2002-04-13 02:17:43 +00:00
|
|
|
or Motorola byteorder.
|
2002-04-20 21:01:41 +00:00
|
|
|
Unfortunately, the packed colorspaces depend on CPU byteorder. So, RGB
|
2002-04-13 02:17:43 +00:00
|
|
|
on Intel and Motorola means different order of bytes.
|
|
|
|
|
|
|
|
In MPlayer, we have constants IMGFMT_RGBxx and IMGFMT_BGRxx.
|
2002-04-20 21:01:41 +00:00
|
|
|
Unfortunately, some codecs and vo drivers follow Intel, some follow Motorola
|
2002-04-13 02:17:43 +00:00
|
|
|
byteorder, so they are incompatible. We had to find a stable base, so long
|
2002-04-20 21:01:41 +00:00
|
|
|
time ago I've chosen OpenGL, as it's a wide-spreaded standard, and it well
|
|
|
|
defines what RGB is and what BGR is. So, MPlayer's RGB is compatible with
|
|
|
|
OpenGL's GL_RGB on all platforms, and the same goes for BGR - GL_BGR.
|
2005-03-31 22:45:03 +00:00
|
|
|
Unfortunately, most of the x86 codecs call our BGR RGB, so it sometimes
|
|
|
|
confuses developers.
|
2002-04-13 02:17:43 +00:00
|
|
|
|
2004-08-11 01:52:17 +00:00
|
|
|
memory order: name
|
2004-08-17 01:06:24 +00:00
|
|
|
lowest address .. highest address
|
2004-08-11 01:52:17 +00:00
|
|
|
RGBA IMGFMT_RGBA
|
|
|
|
ARGB IMGFMT_ARGB
|
|
|
|
BGRA IMGFMT_BGRA
|
|
|
|
ABGR IMGFMT_ABGR
|
|
|
|
RGB IMGFMT_RGB24
|
|
|
|
BGR IMGFMT_BGR24
|
|
|
|
|
|
|
|
order in an int name
|
2004-10-02 18:02:30 +00:00
|
|
|
most significant .. least significant bit
|
2004-08-11 01:52:17 +00:00
|
|
|
8A8R8G8B IMGFMT_BGR32
|
|
|
|
8A8B8G8R IMGFMT_RGB32
|
|
|
|
5R6G5B IMGFMT_BGR16
|
|
|
|
5B6G5R IMGFMT_RGB16
|
|
|
|
1A5R5G5B IMGFMT_BGR15
|
|
|
|
1A5B5G5R IMGFMT_RGB15
|
2004-11-20 10:53:04 +00:00
|
|
|
|
|
|
|
The following are palettized formats, the palette is in the second plane.
|
|
|
|
When they come out of the swscaler (this can be different when they
|
2005-03-31 22:45:03 +00:00
|
|
|
come from a codec!), their palette is organized in such a way
|
2004-11-20 10:53:04 +00:00
|
|
|
that you actually get:
|
|
|
|
|
2004-08-11 01:52:17 +00:00
|
|
|
3R3G2B IMGFMT_BGR8
|
|
|
|
2B3G3R IMGFMT_RGB8
|
|
|
|
1R2G1B IMGFMT_BGR4_CHAR
|
|
|
|
1B2G1R IMGFMT_RGB4_CHAR
|
|
|
|
1R2G1B1R2G1B IMGFMT_BGR4
|
|
|
|
1B2G1R1B2G1R IMGFMT_RGB4
|
|
|
|
|
2005-03-31 22:45:03 +00:00
|
|
|
Depending upon the CPU being little- or big-endian, different 'in memory' and
|
2004-08-17 01:06:24 +00:00
|
|
|
'in register' formats will be equal (LE -> BGRA == BGR32 / BE -> ARGB == BGR32)
|
2006-02-24 22:18:45 +00:00
|
|
|
|
|
|
|
Practical coding guide:
|
|
|
|
|
|
|
|
The 4, 8, 15, and 16 bit formats are defined so that the portable way to
|
|
|
|
access them is to load the pixel into an integer and use bitmasks.
|
|
|
|
|
|
|
|
The 24 bit formats are defined so that the portable way to access them is
|
|
|
|
to address the 3 components as separate bytes, as in ((uint8_t *)pixel)[0],
|
|
|
|
((uint8_t *)pixel)[1], ((uint8_t *)pixel)[2].
|
|
|
|
|
|
|
|
When a 32-bit format is identified by the four characters A, R, G, and B in
|
|
|
|
some order, the portable way to access it is by addressing the 4 components
|
|
|
|
as separate bytes.
|
|
|
|
|
|
|
|
When a 32-bit format is identified by the 3 characters R, G, and B in some
|
|
|
|
order followed by the number 32, the portable way to access it is to load
|
|
|
|
the pixel into an integer and use bitmasks.
|
|
|
|
|
|
|
|
When the above portable access methods are not used, you will need to write
|
2009-07-26 19:53:00 +00:00
|
|
|
2 versions of your code, and use #if HAVE_BIGENDIAN to choose the correct
|
2006-02-24 22:18:45 +00:00
|
|
|
one.
|