📄 vconvert.cxx
字号:
return TRUE;
}
PSTANDARD_COLOUR_CONVERTER(SBGGR8,RGB24)
{
return SBGGR8toRGB(srcFrameBuffer, dstFrameBuffer, bytesReturned);
}
PSTANDARD_COLOUR_CONVERTER(SBGGR8,YUV420P)
{
return SBGGR8toYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned);
}
PSTANDARD_COLOUR_CONVERTER(YUV420P,RGB24)
{
return YUV420PtoRGB(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 0, 2);
}
PSTANDARD_COLOUR_CONVERTER(YUV420P,BGR24)
{
return YUV420PtoRGB(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 2, 0);
}
PSTANDARD_COLOUR_CONVERTER(YUV420P,RGB32)
{
return YUV420PtoRGB(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 0, 2);
}
PSTANDARD_COLOUR_CONVERTER(YUV420P,BGR32)
{
return YUV420PtoRGB(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 2, 0);
}
static void SwapRedAndBlueRow(const BYTE * srcRowPtr,
BYTE * dstRowPtr,
unsigned width,
unsigned srcIncrement,
unsigned dstIncrement)
{
for (unsigned x = 0; x < width; x++) {
BYTE temp = srcRowPtr[0]; // Do it this way in case src and dst are same buffer
dstRowPtr[0] = srcRowPtr[2];
dstRowPtr[1] = srcRowPtr[1];
dstRowPtr[2] = temp;
srcRowPtr += srcIncrement;
dstRowPtr += dstIncrement;
}
}
BOOL PStandardColourConverter::SwapRedAndBlue(const BYTE * srcFrameBuffer,
BYTE * dstFrameBuffer,
PINDEX * bytesReturned,
unsigned srcIncrement,
unsigned dstIncrement) const
{
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return FALSE;
unsigned srcRowSize = srcFrameBytes/srcFrameHeight;
const BYTE * srcRowPtr = srcFrameBuffer;
unsigned dstRowSize = dstFrameBytes/dstFrameHeight;
BYTE * dstRowPtr = dstFrameBuffer;
if (verticalFlip) {
dstRowPtr += dstFrameHeight*dstRowSize;
if (srcFrameBuffer == dstFrameBuffer) {
PBYTEArray tempRow(PMAX(srcRowSize, dstRowSize));
unsigned halfHeight = (srcFrameHeight+1)/2;
for (unsigned y = 0; y < halfHeight; y++) {
dstRowPtr -= dstRowSize;
SwapRedAndBlueRow(dstRowPtr, tempRow.GetPointer(), dstFrameWidth, srcIncrement, dstIncrement);
SwapRedAndBlueRow(srcRowPtr, dstRowPtr, srcFrameWidth, srcIncrement, dstIncrement);
memcpy((BYTE *)srcRowPtr, tempRow, srcRowSize);
srcRowPtr += srcRowSize;
}
}
else {
for (unsigned y = 0; y < srcFrameHeight; y++) {
dstRowPtr -= dstRowSize;
SwapRedAndBlueRow(srcRowPtr, dstRowPtr, srcFrameWidth, srcIncrement, dstIncrement);
srcRowPtr += srcRowSize;
}
}
}
else {
for (unsigned y = 0; y < srcFrameHeight; y++) {
SwapRedAndBlueRow(srcRowPtr, dstRowPtr, srcFrameWidth, srcIncrement, dstIncrement);
srcRowPtr += srcRowSize;
dstRowPtr += dstRowSize;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
PSTANDARD_COLOUR_CONVERTER(RGB24,BGR24)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 3);
}
PSTANDARD_COLOUR_CONVERTER(BGR24,RGB24)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 3);
}
PSTANDARD_COLOUR_CONVERTER(RGB24,BGR32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 4);
}
PSTANDARD_COLOUR_CONVERTER(BGR24,RGB32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 4);
}
PSTANDARD_COLOUR_CONVERTER(RGB32,BGR24)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 3);
}
PSTANDARD_COLOUR_CONVERTER(BGR32,RGB24)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 3);
}
PSTANDARD_COLOUR_CONVERTER(RGB32,BGR32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 4);
}
PSTANDARD_COLOUR_CONVERTER(BGR32,RGB32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 4);
}
PSTANDARD_COLOUR_CONVERTER(RGB24,RGB32)
{
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return FALSE;
// Go from bottom to top so can do in place conversion
const BYTE * src = srcFrameBuffer+srcFrameBytes-1;
BYTE * dst = dstFrameBuffer+dstFrameBytes-1;
for (unsigned x = 0; x < srcFrameWidth; x++) {
for (unsigned y = 0; y < srcFrameHeight; y++) {
*dst-- = 0;
for (unsigned p = 0; p < 3; p++)
*dst-- = *src--;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
PSTANDARD_COLOUR_CONVERTER(RGB32,RGB24)
{
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return FALSE;
const BYTE * src = srcFrameBuffer;
BYTE * dst = dstFrameBuffer;
for (unsigned x = 0; x < srcFrameWidth; x++) {
for (unsigned y = 0; y < srcFrameHeight; y++) {
for (unsigned p = 0; p < 3; p++)
*dst++ = *src++;
src++;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
// Consider a YUV420P image of 8x2 pixels.
//
// A plane of Y values A B C D E F G H
// I J K L M N O P
//
// A plane of U values 1 2 3 4
// A plane of V values 1 2 3 4 ....
//
// The U1/V1 samples correspond to the ABIJ pixels.
// U2/V2 samples correspond to the CDKL pixels.
//
// Consider a YUV411P image of 8x2 pixels.
//
// A plane of Y values as before.
//
// A plane of U values 1 2
// 3 4
//
// A plane of V values 1 2
// 3 4
//
// The U1/V1 samples correspond to the ABCD pixels.
// U2/V2 samples correspond to the EFGH pixels.
//
// I choose to reoganize the U and V samples by using
// using U1 for ABCD, U3 for EFGH, U2 for IJKL, U4 for MNOP
//
// Possibly discarding U2/U4 completely, or using the
// average of U1 and U2 might be easier for compression
//
// TODO:
//
// - Inplace converter
// - Resizing / padding / scaling converter
//
PSTANDARD_COLOUR_CONVERTER(YUV420P,YUV411P)
{
if (srcFrameBuffer == dstFrameBuffer)
return FALSE;
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return FALSE;
// Copy over the Y plane.
memcpy(dstFrameBuffer, srcFrameBuffer, srcFrameWidth*srcFrameHeight);
unsigned linewidth = dstFrameWidth / 4;
// Source data is the start of the U plane
const BYTE* src = srcFrameBuffer + srcFrameWidth * srcFrameHeight;
// Two output lines at a time
BYTE *dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight;
BYTE *dst1 = dst0 + linewidth;
unsigned x, y;
// U plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
*dst0++ = *src++;
*dst1++ = *src++;
}
// Skip over the 2nd line we already did.
dst0 += linewidth;
dst1 = dst0 + linewidth;
}
// Source data is the start of the U plane
src = srcFrameBuffer + srcFrameWidth * srcFrameHeight * 5 / 4;
// Two output lines at a time
dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight * 5 / 4;
dst1 = dst0 + linewidth;
// V plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
*dst0++ = *src++;
*dst1++ = *src++;
}
// Skip over the 2nd line we already did.
dst0 += linewidth;
dst1 = dst0 + linewidth;
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
// YUV411P to YUV420P conversion
//
// Consider YUV411P U plane (. = pixel) :
//
// A... B... C... D...
// E... F... G... H...
// I... J... K... L...
// M... N... O... P...
//
// We map this to a YUV420P plane by
// discarding odd rows, and doubling up
// the even row samples:
//
// A.A. B.B. C.C. D.D.
// .... .... .... ....
// I.I. J.J. K.K. L.L.
// .... .... .... ....
//
// TODO:
//
// - Inplace converter
// - Resizing / padding / scaling converter
//
PSTANDARD_COLOUR_CONVERTER(YUV411P,YUV420P)
{
if (srcFrameBuffer == dstFrameBuffer)
return FALSE;
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return FALSE;
// Copy over the Y plane.
memcpy(dstFrameBuffer, srcFrameBuffer, srcFrameWidth*srcFrameHeight);
unsigned linewidth = dstFrameWidth / 4;
// Source data is the start of the U plane
const BYTE* src = srcFrameBuffer + srcFrameWidth * srcFrameHeight;
// Output line
BYTE *dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight;
unsigned x, y;
// U plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
// Double up the horizontal samples
*dst0++ = *src;
*dst0++ = *src++;
}
// Skip over the 2nd line we are decimating
src += linewidth;
}
// Source data is the start of the U plane
src = srcFrameBuffer + srcFrameWidth * srcFrameHeight * 5 / 4;
// Output line
dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight * 5 / 4;
// V plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
// Double up the samples horizontal samples
*dst0++ = *src;
*dst0++ = *src++;
}
// Skip over the 2nd source line we already did.
src += linewidth;
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
/*
* Format UYVY or UYVY422(non planar) 4x4
*
* off: 0 U00 Y00 V01 Y00 U02 Y01 V03 Y01
* off: 8 U10 Y10 V11 Y10 U12 Y11 V13 Y11
* off:16 U20 Y20 V21 Y20 U22 Y21 V23 Y21
* off:24 U30 Y30 V31 Y30 U32 Y31 V33 Y31
* length:32 bytes
*
* Format YUV420P:
* off: 00 Y00 Y01 Y02 Y03
* off: 04 Y10 Y11 Y12 Y13
* off: 08 Y20 Y21 Y22 Y23
* off: 12 Y30 Y31 Y32 Y33
* off: 16 U00 U02 U20 U22
* off: 20 V00 V02 V20 V22
*
* So, we loose some bit of information when converting UYVY to YUV420
*
* NOTE: This algorithm works only if the width and the height is pair.
*/
void PStandardColourConverter::UYVY422toYUV420PSameSize(const BYTE *uyvy, BYTE *yuv420p) const
{
const BYTE *s;
BYTE *y, *u, *v;
unsigned int x, h;
int npixels = srcFrameWidth * srcFrameHeight;
s = uyvy;
y = yuv420p;
u = yuv420p + npixels;
v = u + npixels/4;
for (h=0; h<srcFrameHeight; h+=2) {
/* Copy the first line keeping all information */
for (x=0; x<srcFrameWidth; x+=2) {
*u++ = *s++;
*y++ = *s++;
*v++ = *s++;
*y++ = *s++;
}
/* Copy the second line discarding u and v information */
for (x=0; x<srcFrameWidth; x+=2) {
s++;
*y++ = *s++;
s++;
*y++ = *s++;
}
}
}
/*
* Format UYVY (or UYVY422) non
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -