📄 vconvert.cxx
字号:
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;
}
/*
* The following functions converts video from IEEE 1394 cameras into
* YUV420P format. The video format of IEEE 1394 cameras can be found
* at Section 2.1.3 of
http://www.1394ta.org/Download/Technology/Specifications/2000/IIDC_Spec_v1_30.pdf
* 320x240 and 160x120 resolutions are used.
*
*
* UYVY422 is just a byte permutation of YUV422. I believe this is not
* due to endian problem
*
* These functions should accept arbitrary size of image.
*/
PSTANDARD_COLOUR_CONVERTER(UYVY422,YUV420P)
{
if (srcFrameBuffer == dstFrameBuffer)
return FALSE;
unsigned int row,column;
unsigned char *y = dstFrameBuffer; //Initialise y,u,v here, to stop compiler warnings.
unsigned char *u = dstFrameBuffer + dstFrameWidth*dstFrameHeight;
unsigned char *v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4);
const unsigned char *src = srcFrameBuffer;
for(row=0; row < PMIN(srcFrameHeight, dstFrameHeight); row+=2) {
y = dstFrameBuffer + dstFrameWidth*row;
u = dstFrameBuffer + dstFrameWidth*dstFrameHeight + dstFrameWidth*row/4;
v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4) + dstFrameWidth*row/4;
src = srcFrameBuffer + row*srcFrameWidth*2;
for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column+=2) {
*(u++) = (unsigned char)(((int)src[0] + src[srcFrameWidth*2])/2);
*(y++) = src[1];
*(v++) = (unsigned char)(((int)src[2] + src[2+srcFrameWidth*2])/2);
*(y++) = src[3];
src += 4;
}
for(column = PMIN(srcFrameWidth, dstFrameWidth);
column < dstFrameWidth; column+=2) {
*(u++) = BLACK_U;
*(y++) = BLACK_Y;
*(v++) = BLACK_V;
*(y++) = BLACK_Y;
}
y = dstFrameBuffer + dstFrameWidth*(row+1);
src = srcFrameBuffer + (row+1)*srcFrameWidth*2;
for(column=0; column < PMIN(srcFrameWidth,dstFrameWidth); column+=2) {
src++;
*(y++) = *(src++);
src++;
*(y++) = *(src++);
}
for(column = PMIN(srcFrameWidth, dstFrameWidth);
column < dstFrameWidth; column+=2) {
*(y++) = BLACK_Y;
*(y++) = BLACK_Y;
}
}
for(row = PMIN(srcFrameHeight, dstFrameHeight);
row < dstFrameHeight; row+=2) {
for(column = 0; column < dstFrameWidth; column+=2) {
*(u++) = BLACK_U;
*(y++) = BLACK_Y;
*(v++) = BLACK_V;
*(y++) = BLACK_Y;
}
for(column = 0; column < dstFrameWidth; column+=2) {
*(y++) = BLACK_Y;
*(y++) = BLACK_Y;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
PSTANDARD_COLOUR_CONVERTER(UYV444,YUV420P)
{
if (srcFrameBuffer == dstFrameBuffer)
return FALSE;
unsigned int row,column;
unsigned char *y = dstFrameBuffer; //Initialise y,u,v here, to stop compiler warnings.
unsigned char *u = dstFrameBuffer + dstFrameWidth*dstFrameHeight;
unsigned char *v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4);
const unsigned char *src = srcFrameBuffer;
for(row=0; row < PMIN(srcFrameHeight, dstFrameHeight); row+=2) {
y = dstFrameBuffer + dstFrameWidth*row;
u = dstFrameBuffer + dstFrameWidth*dstFrameHeight + dstFrameWidth*row/4;
v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4) + dstFrameWidth*row/4;
src = srcFrameBuffer + row*srcFrameWidth*3;
for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column+=2) {
*(u++) = (unsigned char)(((unsigned int)src[0] + src[3] + src[srcFrameWidth*3] + src[3+srcFrameWidth*3])/4);
*(y++) = src[1];
*(v++) = (unsigned char)(((unsigned int)src[2] + src[5] + src[srcFrameWidth*3] +src[3+srcFrameWidth*3])/4);
*(y++) = src[4];
src += 6;
}
for(column = PMIN(srcFrameWidth, dstFrameWidth);
column < dstFrameWidth; column+=2) {
*(u++) = BLACK_U;
*(y++) = BLACK_Y;
*(v++) = BLACK_V;
*(y++) = BLACK_Y;
}
y = dstFrameBuffer + dstFrameWidth*(row+1);
src = srcFrameBuffer + (row+1)*srcFrameWidth*3;
for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column++) {
src++;
*(y++) = *(src++);
src++;
}
for(column = PMIN(srcFrameWidth, dstFrameWidth);
column < dstFrameWidth; column++)
*(y++) = BLACK_Y;
}
for(row = PMIN(srcFrameHeight, dstFrameHeight);
row<dstFrameHeight; row+=2) {
for(column = 0; column < dstFrameWidth; column+=2) {
*(u++) = BLACK_U;
*(y++) = BLACK_Y;
*(v++) = BLACK_V;
*(y++) = BLACK_Y;
}
for(column = 0; column < dstFrameWidth; column+=2) {
*(y++) = BLACK_Y;
*(y++) = BLACK_Y;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
#ifdef __GNUC__
#ifndef P_MACOSX
/*
* Convert a MJPEG Buffer to one plane pixel format (RGB24, BGR24, GRAY)
* image need to be same size.
*/
bool PStandardColourConverter::MJPEGtoXXXSameSize(const BYTE *mjpeg, BYTE *rgb, int format)
{
BYTE *components[1];
components[0] = rgb;
if (jdec == NULL) {
jdec = tinyjpeg_init();
if (jdec == NULL) {
PTRACE(2, "PColCnv\tJpeg error: Can't allocate memory");
return FALSE;
}
tinyjpeg_set_flags(jdec, TINYJPEG_FLAGS_MJPEG_TABLE);
}
tinyjpeg_set_components(jdec, components, 1);
if (tinyjpeg_parse_header(jdec, mjpeg, srcFrameBytes) < 0) {
PTRACE(2, "PColCnv\tJpeg error: " << tinyjpeg_get_errorstring(jdec));
return FALSE;
}
if (tinyjpeg_decode(jdec, format) < 0) {
PTRACE(2, "PColCnv\tJpeg error: " << tinyjpeg_get_errorstring(jdec));
return FALSE;
}
return TRUE;
}
bool PStandardColourConverter::MJPEGtoXXX(const BYTE *mjpeg,
BYTE *output_data,
PINDEX *bytesReturned,
int format)
{
if ((srcFrameWidth | dstFrameWidth | srcFrameHeight | dstFrameHeight) & 0xf) {
PTRACE(2,"PColCnv\tError MJPEG decoder need width and height to be a multiple of 16");
return FALSE;
}
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight)) {
if (MJPEGtoXXXSameSize(mjpeg, output_data, format) == FALSE)
return FALSE;
} else {
/* not efficient (convert then resize) */
/* TODO: */
return FALSE;
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
PSTANDARD_COLOUR_CONVERTER(MJPEG,RGB24)
{
return MJPEGtoXXX(srcFrameBuffer, dstFrameBuffer, bytesReturned, TINYJPEG_FMT_RGB24);
}
PSTANDARD_COLOUR_CONVERTER(MJPEG,BGR24)
{
return MJPEGtoXXX(srcFrameBuffer, dstFrameBuffer, bytesReturned, TINYJPEG_FMT_BGR24);
}
PSTANDARD_COLOUR_CONVERTER(MJPEG,Grey)
{
return MJPEGtoXXX(srcFrameBuffer, dstFrameBuffer, bytesReturned, TINYJPEG_FMT_GREY);
}
PSTANDARD_COLOUR_CONVERTER(JPEG,RGB24)
{
return MJPEGtoXXX(srcFrameBuffer, dstFrameBuffer, bytesReturned, TINYJPEG_FMT_RGB24);
}
PSTANDARD_COL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -