📄 vconvert.cxx
字号:
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight)) memcpy(dstFrameBuffer,srcFrameBuffer,srcFrameWidth*srcFrameHeight*2); else ResizeYUV422(srcFrameBuffer, dstFrameBuffer); return TRUE;}///No resize here.//Colour format change only, YUV422 is turned into YUV420P.static void Yuv422ToYuv420P(unsigned dstFrameWidth, unsigned dstFrameHeight, const BYTE * srcFrame, BYTE * dstFrame){ unsigned a,b; BYTE *u,*v; const BYTE * s = srcFrame; BYTE * y = dstFrame; u = y + (dstFrameWidth * dstFrameHeight); v = u + (dstFrameWidth * dstFrameHeight / 4); for (a = 0; a < dstFrameHeight; a+=2) { for (b = 0; b < dstFrameWidth; b+=2) { *(y++) = *(s++); *(u++) = *(s++); *(y++) = *(s++); *(v++) = *(s++); } for (b = 0; b < dstFrameWidth; b+=2) { *(y++) = *(s++); s++; *(y++) = *(s++); s++; } }}PSTANDARD_COLOUR_CONVERTER(YUV422,YUV420P){ if (srcFrameBuffer == dstFrameBuffer) return FALSE; if ((srcFrameWidth==dstFrameWidth) && (srcFrameHeight==dstFrameHeight)) Yuv422ToYuv420P(srcFrameWidth, srcFrameHeight, srcFrameBuffer, dstFrameBuffer); else { //do a resize. then convert to yuv420p. BYTE * intermed = intermediateFrameStore.GetPointer(dstFrameWidth*dstFrameHeight*2); ResizeYUV422(srcFrameBuffer, intermed); Yuv422ToYuv420P(dstFrameWidth, dstFrameHeight, intermed, dstFrameBuffer); } if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; return TRUE;}#define LIMIT(x) (unsigned char) (((x > 0xffffff) ? 0xff0000 : ((x <= 0xffff) ? 0 : x & 0xff0000)) >> 16)static inline int clip(int a, int limit) { return a<limit?a:limit;}BOOL PStandardColourConverter::SBGGR8toYUV420P(const BYTE * src, BYTE * dst, PINDEX * bytesReturned) const{#define USE_SBGGR8_NATIVE 1 // set to 0 to use the double conversion algorithm (Bayer->RGB->YUV420P) #if USE_SBGGR8_NATIVE // kernels for Y conversion, normalised by 2^16 const int kR[]={1802,9667,1802,9667,19661,9667,1802,9667,1802}; const int kG1[]={7733,9830,7733,3604,7733,3604,7733,9830,7733}; const int kG2[]={7733,3604,7733,9830,7733,9830,7733,3604,7733}; const int kB[]={4915,9667,4915,9667,7209,9667,4915,9667,4915}; // const int kID[]={0,0,0,0,65536,0,0,0,0}; identity kernel, use to test int B, G, G1, G2, R; const int stride = srcFrameWidth; unsigned const int hSize =srcFrameHeight/2; unsigned const int vSize =srcFrameWidth/2; unsigned const int lastRow=srcFrameHeight-1; unsigned const int lastCol=srcFrameWidth-1; unsigned int i,j; const BYTE *sBayer = src; // Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) + 16; // Y = round( 0.30 * R + 0.59 * G + 0.11 * B ) use this! // U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128; // V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128; // Compute U and V planes using EXACT values, reading 2x2 pixels at a time BYTE *dU = dst+srcFrameHeight*srcFrameWidth; BYTE *dV = dU+hSize*vSize; for (i=0; i<hSize; i++) { for (j=0; j<vSize; j++) { B=sBayer[0]; G1=sBayer[1]; G2=sBayer[stride]; R=sBayer[stride+1]; G=G1+G2; *dU = (BYTE)( ( (-19428 * R -19071*G +57569 * B) >> 17) + 128 ); *dV = (BYTE)( ( ( 57569 * R -24103*G -9362 * B) >> 17) + 128 ); sBayer+=2; dU++; dV++; } sBayer+=stride; // skip odd lines } // Compute Y plane BYTE *dY = dst; sBayer=src; const int * k; // kernel pointer int dxLeft, dxRight; // precalculated offsets, needed for first and last column const BYTE *sBayerTop, *sBayerBottom; for (i=0; i<srcFrameHeight; i++) { // Pointer to previous row, to the next if we are on the first one sBayerTop=sBayer+(i?(-stride):stride); // Pointer to next row, to the previous one if we are on the last sBayerBottom=sBayer+((i<lastRow)?stride:(-stride)); // offset to previous column, to the next if we are on the first col dxLeft=1; for (j=0; j<srcFrameWidth; j++) { // offset to next column, to previous if we are on the last one dxRight=j<lastCol?1:(-1); // find the proper kernel according to the current pixel color if ( (i ^ j) & 1) k=(j&1)?kG1:kG2; // green 1 or green 2 else if (!(i & 1)) k=kB; // blue else /* if (!(j & 1)) */ k=kR; // red // apply the proper kernel to this pixel and surrounding ones *dY= (BYTE)(clip( (k[0])*(int)sBayerTop[dxLeft]+ (k[1])*(int)(*sBayerTop)+ (k[2])*(int)sBayerTop[dxRight]+ (k[3])*(int)sBayer[dxLeft]+ (k[4])*(int)(*sBayer)+ (k[5])*(int)sBayer[dxRight]+ (k[6])*(int)sBayerBottom[dxLeft]+ (k[7])*(int)(*sBayerBottom)+ (k[8])*(int)sBayerBottom[dxRight], (1<<24)) >> 16); dY++; sBayer++; sBayerTop++; sBayerBottom++; dxLeft=-1; } } if (bytesReturned) *bytesReturned = srcFrameHeight*srcFrameWidth+2*hSize*vSize; return true;#else //USE_SBGGR8_NATIVE // shortest but less efficient (one malloc per conversion!) BYTE * tempDest=(BYTE*)malloc(3*srcFrameWidth*srcFrameHeight); SBGGR8toRGB(src, tempDest, NULL); BOOL r = RGBtoYUV420P(tempDest, dst, bytesReturned, 3, 2, 0); free(tempDest); return r;#endif //USE_SBGGR8_NATIVE}BOOL PStandardColourConverter::SBGGR8toRGB(const BYTE * src, BYTE * dst, PINDEX * bytesReturned) const{ if (src == dst || verticalFlip) return FALSE; long int i; const BYTE *rawpt; BYTE *scanpt; long int size; rawpt = src; scanpt = dst; long int WIDTH = srcFrameWidth, HEIGHT = srcFrameHeight; size = WIDTH*HEIGHT; for ( i = 0; i < size; i++ ) { if ( (i/WIDTH) % 2 == 0 ) { if ( (i % 2) == 0 ) { /* B */ if ( (i > WIDTH) && ((i % WIDTH) > 0) ) { *scanpt++ = (BYTE) ((*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+ *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4); /* R */ *scanpt++ = (BYTE) ((*(rawpt-1)+*(rawpt+1)+ *(rawpt+WIDTH)+*(rawpt-WIDTH))/4); /* G */ *scanpt++ = *rawpt; /* B */ } else { /* first line or left column */ *scanpt++ = *(rawpt+WIDTH+1); /* R */ *scanpt++ = (BYTE) ((*(rawpt+1)+*(rawpt+WIDTH))/2); /* G */ *scanpt++ = *rawpt; /* B */ } } else { /* (B)G */ if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) { *scanpt++ = (BYTE) ((*(rawpt+WIDTH)+*(rawpt-WIDTH))/2); /* R */ *scanpt++ = *rawpt; /* G */ *scanpt++ = (BYTE) ((*(rawpt-1)+*(rawpt+1))/2); /* B */ } else { /* first line or right column */ *scanpt++ = *(rawpt+WIDTH); /* R */ *scanpt++ = *rawpt; /* G */ *scanpt++ = *(rawpt-1); /* B */ } } } else { if ( (i % 2) == 0 ) { /* G(R) */ if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) { *scanpt++ = (BYTE) ((*(rawpt-1)+*(rawpt+1))/2); /* R */ *scanpt++ = *rawpt; /* G */ *scanpt++ = (BYTE) ((*(rawpt+WIDTH)+*(rawpt-WIDTH))/2); /* B */ } else { /* bottom line or left column */ *scanpt++ = *(rawpt+1); /* R */ *scanpt++ = *rawpt; /* G */ *scanpt++ = *(rawpt-WIDTH); /* B */ } } else { /* R */ if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) { *scanpt++ = *rawpt; /* R */ *scanpt++ = (BYTE) ((*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4); /* G */ *scanpt++ = (BYTE) ((*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4); /* B */ } else { /* bottom line or right column */ *scanpt++ = *rawpt; /* R */ *scanpt++ = (BYTE) ((*(rawpt-1)+*(rawpt-WIDTH))/2); /* G */ *scanpt++ = *(rawpt-WIDTH-1); /* B */ } } } rawpt++; } if (bytesReturned) *bytesReturned = scanpt - dst; return TRUE;}BOOL PStandardColourConverter::YUV420PtoRGB(const BYTE * srcFrameBuffer, BYTE * dstFrameBuffer, PINDEX * bytesReturned, unsigned rgbIncrement, unsigned redOffset, unsigned blueOffset) const{ if (srcFrameBuffer == dstFrameBuffer) return FALSE; BYTE *dstImageFrame; unsigned int nbytes = srcFrameWidth*srcFrameHeight; const BYTE *yplane = srcFrameBuffer; // 1 byte Y (luminance) for each pixel const BYTE *uplane = yplane+nbytes; // 1 byte U for a block of 4 pixels const BYTE *vplane = uplane+(nbytes >> 2); // 1 byte V for a block of 4 pixels unsigned int pixpos[4] = {0, 1, srcFrameWidth, srcFrameWidth + 1}; unsigned int originalPixpos[4] = {0, 1, srcFrameWidth, srcFrameWidth + 1}; unsigned int x, y, p; long int yvalue; long int l, r, g, b; if (verticalFlip) { dstImageFrame = dstFrameBuffer + ((srcFrameHeight - 2) * srcFrameWidth * rgbIncrement); pixpos[0] = srcFrameWidth; pixpos[1] = srcFrameWidth +1; pixpos[2] = 0; pixpos[3] = 1; } else dstImageFrame = dstFrameBuffer; for (y = 0; y < srcFrameHeight; y += 2) { for (x = 0; x < srcFrameWidth; x += 2) { // The RGB value without luminance long cb = *uplane-128; long cr = *vplane-128; long rd = 104635*cr; // 106986*cr long gd = -25690*cb-53294*cr; // -26261*cb + -54496*cr long bd = 132278*cb; // 135221*cb // Add luminance to each of the 4 pixels for (p = 0; p < 4; p++) { yvalue = *(yplane + originalPixpos[p])-16; if (yvalue < 0) yvalue = 0; l = 76310*yvalue; r = l+rd; g = l+gd; b = l+bd; BYTE * rgpPtr = dstImageFrame + rgbIncrement*pixpos[p]; rgpPtr[redOffset ] = LIMIT(r); rgpPtr[1 ] = LIMIT(g); rgpPtr[blueOffset] = LIMIT(b); if (rgbIncrement == 4) rgpPtr[3] = 0; } yplane += 2; dstImageFrame += rgbIncrement*2; uplane++; vplane++; } yplane += srcFrameWidth; if (verticalFlip) dstImageFrame -= 3*rgbIncrement*srcFrameWidth; else dstImageFrame += rgbIncrement*srcFrameWidth; } if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; 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++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -