📄 vconvert.cxx
字号:
: PColourConverterRegistration(srcFmt,dstFmt){}PColourConverter * PSynonymColourRegistration::Create(unsigned w, unsigned h) const{ PINDEX tab = Find('\t'); return new PSynonymColour(Left(tab), Mid(tab+1), w, h);}BOOL PSynonymColour::Convert(const BYTE *srcFrameBuffer, BYTE *dstFrameBuffer, PINDEX * bytesReturned){ if ((srcFrameWidth != dstFrameWidth) || (srcFrameHeight != dstFrameHeight)) { PTRACE(2,"PColCnv\tCannot do synonym colour conversion, source and destination frame size not equal."); return FALSE; } if (verticalFlip) { PINDEX rowSize = dstFrameBytes/srcFrameHeight; if (rowSize*srcFrameHeight != dstFrameBytes) { PTRACE(2,"PColCnv\tCannot do synonym colour conversion, frame does not have equal sized scan lines."); return FALSE; } if (srcFrameBuffer != dstFrameBuffer) { const BYTE * srcRowPtr = srcFrameBuffer; BYTE * dstRowPtr = dstFrameBuffer + srcFrameHeight*rowSize; for (unsigned y = 0; y < srcFrameHeight; y++) { dstRowPtr -= rowSize; memcpy(dstRowPtr, srcRowPtr, rowSize); srcRowPtr += rowSize; } } else { BYTE * rowPtr1 = dstFrameBuffer; BYTE * rowPtr2 = dstFrameBuffer + srcFrameHeight*rowSize; PBYTEArray temp(rowSize); for (unsigned y = 0; y < srcFrameHeight; y += 2) { rowPtr2 -= rowSize; memcpy(temp.GetPointer(), rowPtr1, rowSize); memcpy(rowPtr1, rowPtr2, rowSize); memcpy(rowPtr2, temp.GetPointer(), rowSize); rowPtr1 += rowSize; } } } else { if (srcFrameBuffer != dstFrameBuffer) memcpy(dstFrameBuffer, srcFrameBuffer, dstFrameBytes); } if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; return TRUE;}///////////////////////////////////////////////////////////////////////////////#define BLACK_Y 0#define BLACK_U 128#define BLACK_V 128#define greytoy(r, y) y=r#define greytoyuv(r, y, u, v) greytoy(r,y); u=BLACK_U; v=BLACK_Vvoid PStandardColourConverter::GreytoYUV420PSameSize(const BYTE * grey, BYTE * yuv) const{ const unsigned planeSize = srcFrameWidth*srcFrameHeight; const unsigned halfWidth = srcFrameWidth >> 1; // get pointers to the data BYTE * yplane = yuv; BYTE * uplane = yuv + planeSize; BYTE * vplane = yuv + planeSize + (planeSize >> 2); const BYTE * greyIndex = grey; for (unsigned y = 0; y < srcFrameHeight; y++) { BYTE * yline = yplane + (y * srcFrameWidth); BYTE * uline = uplane + ((y >> 1) * halfWidth); BYTE * vline = vplane + ((y >> 1) * halfWidth); if (verticalFlip) greyIndex = grey + srcFrameWidth*(srcFrameHeight-1-y); for (unsigned x = 0; x < srcFrameWidth; x+=2) { greytoy(*greyIndex, *yline); greyIndex++; yline++; greytoyuv(*greyIndex, *yline, *uline, *vline); greyIndex++; yline++; uline++; vline++; } }}// Simple crop/pad version. Image aligned to top-left// and cropped / padded with black borders as required.void PStandardColourConverter::GreytoYUV420PWithResize(const BYTE * grey, BYTE * yuv) const{ int planeSize = dstFrameWidth*dstFrameHeight; const int halfWidth = dstFrameWidth >> 1; unsigned min_width, min_height; min_width = (dstFrameWidth < srcFrameWidth) ? dstFrameWidth : srcFrameWidth; min_height = (dstFrameHeight < srcFrameHeight) ? dstFrameHeight : srcFrameHeight; // get pointers to the data BYTE * yplane = yuv; BYTE * uplane = yuv + planeSize; BYTE * vplane = yuv + planeSize + (planeSize >> 2); const BYTE * greyIndex = grey; for (unsigned y = 0; y < min_height; y++) { BYTE * yline = yplane + (y * dstFrameWidth); BYTE * uline = uplane + ((y >> 1) * halfWidth); BYTE * vline = vplane + ((y >> 1) * halfWidth); if (verticalFlip) greyIndex = grey + srcFrameWidth*(min_height-1-y); for (unsigned x = 0; x < min_width; x+=2) { greytoy(*greyIndex, *yline); greyIndex++; yline++; greytoyuv(*greyIndex, *yline, *uline, *vline); greyIndex++; yline++; uline++; vline++; } // Crop if source width > dest width if (srcFrameWidth > dstFrameWidth) greyIndex += srcFrameWidth - dstFrameWidth; // Pad if dest width < source width if (dstFrameWidth > srcFrameWidth) { memset(yline, BLACK_Y, dstFrameWidth - srcFrameWidth); memset(uline, BLACK_U, (dstFrameWidth - srcFrameWidth)>>1); memset(vline, BLACK_V, (dstFrameWidth - srcFrameWidth)>>1); } } // Pad if dest height > source height if (dstFrameHeight > srcFrameHeight) { BYTE * yline = yplane + (srcFrameHeight * dstFrameWidth); BYTE * uline = uplane + ((srcFrameHeight >> 1) * halfWidth); BYTE * vline = vplane + ((srcFrameHeight >> 1) * halfWidth); unsigned fill = (dstFrameHeight - srcFrameHeight) * dstFrameWidth; memset(yline, BLACK_Y, fill); memset(uline, BLACK_U, fill >> 2); memset(vline, BLACK_V, fill >> 2); }}BOOL PStandardColourConverter::GreytoYUV420P(const BYTE * grey, BYTE * yuv, PINDEX * bytesReturned) const{ if (grey == yuv) return FALSE; // Cannot do in place conversion if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight)) GreytoYUV420PSameSize(grey, yuv); else GreytoYUV420PWithResize(grey, yuv); if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; return TRUE;}#define RGB2Y(r, g, b, y) \ y=(BYTE)(((int)257*(r) +(int)504*(g) +(int)98*(b))/1000)#define RGB2YUV(r, g, b, y, cb, cr) \ RGB2Y(r, g, b, y); \ cb=(BYTE)((-148*(r) -291*(g) +439*(b))/1000 + 128); \ cr=(BYTE)(( 439*(r) -368*(g) - 71*(b))/1000 + 128)void PStandardColourConverter::RGBtoYUV420PSameSize(const BYTE * rgb, BYTE * yuv, unsigned rgbIncrement, unsigned redOffset, unsigned blueOffset) const{ const unsigned planeSize = srcFrameWidth*srcFrameHeight; const unsigned halfWidth = srcFrameWidth >> 1; // get pointers to the data BYTE * yplane = yuv; BYTE * uplane = yuv + planeSize; BYTE * vplane = yuv + planeSize + (planeSize >> 2); const BYTE * rgbIndex = rgb; for (unsigned y = 0; y < srcFrameHeight; y++) { BYTE * yline = yplane + (y * srcFrameWidth); BYTE * uline = uplane + ((y >> 1) * halfWidth); BYTE * vline = vplane + ((y >> 1) * halfWidth); if (verticalFlip) rgbIndex = rgb + (srcFrameWidth*(srcFrameHeight-1-y)*rgbIncrement); for (unsigned x = 0; x < srcFrameWidth; x+=2) { RGB2Y(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline); rgbIndex += rgbIncrement; yline++; RGB2YUV(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline, *uline, *vline); rgbIndex += rgbIncrement; yline++; uline++; vline++; } }}// Simple crop/pad version. Image aligned to top-left// and cropped / padded with black borders as required.void PStandardColourConverter::RGBtoYUV420PWithResize(const BYTE * rgb, BYTE * yuv, unsigned rgbIncrement, unsigned redOffset, unsigned blueOffset) const{ int planeSize = dstFrameWidth*dstFrameHeight; const int halfWidth = dstFrameWidth >> 1; unsigned min_width, min_height; min_width = (dstFrameWidth < srcFrameWidth) ? dstFrameWidth : srcFrameWidth; min_height = (dstFrameHeight < srcFrameHeight) ? dstFrameHeight : srcFrameHeight; // get pointers to the data BYTE * yplane = yuv; BYTE * uplane = yuv + planeSize; BYTE * vplane = yuv + planeSize + (planeSize >> 2); const BYTE * rgbIndex = rgb; for (unsigned y = 0; y < min_height; y++) { BYTE * yline = yplane + (y * dstFrameWidth); BYTE * uline = uplane + ((y >> 1) * halfWidth); BYTE * vline = vplane + ((y >> 1) * halfWidth); if (verticalFlip) rgbIndex = rgb + (srcFrameWidth*(min_height-1-y)*rgbIncrement); for (unsigned x = 0; x < min_width; x+=2) { RGB2Y(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline); rgbIndex += rgbIncrement; yline++; RGB2YUV(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline, *uline, *vline); rgbIndex += rgbIncrement; yline++; uline++; vline++; } // Crop if source width > dest width if (srcFrameWidth > dstFrameWidth) rgbIndex += rgbIncrement * (srcFrameWidth - dstFrameWidth); // Pad if dest width < source width if (dstFrameWidth > srcFrameWidth) { memset(yline, BLACK_Y, dstFrameWidth - srcFrameWidth); memset(uline, BLACK_U, (dstFrameWidth - srcFrameWidth)>>1); memset(vline, BLACK_V, (dstFrameWidth - srcFrameWidth)>>1); } } // Pad if dest height > source height if (dstFrameHeight > srcFrameHeight) { BYTE * yline = yplane + (srcFrameHeight * dstFrameWidth); BYTE * uline = uplane + ((srcFrameHeight >> 1) * halfWidth); BYTE * vline = vplane + ((srcFrameHeight >> 1) * halfWidth); unsigned fill = (dstFrameHeight - srcFrameHeight) * dstFrameWidth; memset(yline, BLACK_Y, fill); memset(uline, BLACK_U, fill >> 2); memset(vline, BLACK_V, fill >> 2); }}BOOL PStandardColourConverter::RGBtoYUV420P(const BYTE * rgb, BYTE * yuv, PINDEX * bytesReturned, unsigned rgbIncrement, unsigned redOffset, unsigned blueOffset) const{ if (rgb == yuv) return FALSE; // Cannot do in place conversion if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight)) RGBtoYUV420PSameSize(rgb, yuv, rgbIncrement, redOffset, blueOffset); else RGBtoYUV420PWithResize(rgb, yuv, rgbIncrement, redOffset, blueOffset); if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; return TRUE;}PSTANDARD_COLOUR_CONVERTER(Grey,YUV420P){ return GreytoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned);}PSTANDARD_COLOUR_CONVERTER(RGB24,YUV420P){ return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 0, 2);}PSTANDARD_COLOUR_CONVERTER(BGR24,YUV420P){ return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 2, 0);}PSTANDARD_COLOUR_CONVERTER(RGB32,YUV420P){ return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 0, 2);}PSTANDARD_COLOUR_CONVERTER(BGR32,YUV420P){ return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 2, 0);}// Consider a YUV422P 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 .// 5 . 6 . 7 . 8 .//// A plane of V values 1 . 2 . 3 . 4 .// 5 . 6 . 7 . 8 .// // YUV422 is stored as Y U Y V // thus, a 4x4 image requires 32 bytes of storage.//// Image has two possible transformations.// padded (src smaller than dst) // subsampled and padded (src bigger than dst) void PStandardColourConverter::ResizeYUV422(const BYTE * src, BYTE * dest) const{ DWORD *result = (DWORD *)dest; DWORD black = (DWORD)(BLACK_U<<24) + (BLACK_Y<<16) + (BLACK_U<<8) + BLACK_Y; unsigned maxIndex = dstFrameWidth*dstFrameHeight/2; for (unsigned i = 0; i < maxIndex; i++) *result++ = black; if ( (dstFrameWidth*dstFrameHeight) > (srcFrameWidth*srcFrameHeight) ) { //dest is bigger than the source. No subsampling. //Place the src in the middle of the destination. unsigned yOffset = dstFrameHeight - srcFrameHeight; unsigned xOffset = dstFrameWidth - srcFrameWidth; BYTE *s_ptr,*d_ptr; d_ptr = (yOffset * dstFrameWidth) + xOffset + dest; s_ptr = (BYTE *)src; for (unsigned y = 0; y < srcFrameHeight; y++) { memcpy(d_ptr,s_ptr, srcFrameWidth*2); d_ptr += 2*dstFrameWidth; s_ptr += 2*srcFrameWidth; } } else { // source is bigger than the destination. // unsigned subSample = 1 + (srcFrameHeight/dstFrameHeight) ; unsigned yOffset = dstFrameHeight - (srcFrameHeight/subSample); unsigned xOffset = dstFrameWidth - (srcFrameWidth/subSample); unsigned subSample2 = subSample*2; DWORD *s_ptr = (DWORD * )src; DWORD *d_ptr = (DWORD *) dest + ((yOffset * dstFrameWidth) + xOffset)/4 ; DWORD *sl_ptr, *dl_ptr; for (unsigned y = 0; y < srcFrameHeight; y+= subSample) { sl_ptr = s_ptr; dl_ptr = d_ptr; for (unsigned x = 0; x < srcFrameWidth; x+= subSample2) { *dl_ptr++ = *sl_ptr; sl_ptr += subSample; } d_ptr += dstFrameWidth/2; s_ptr += srcFrameWidth*subSample/2; } }}PSTANDARD_COLOUR_CONVERTER(YUV422,YUV422){ if (bytesReturned != NULL) *bytesReturned = dstFrameBytes; if (srcFrameBuffer == dstFrameBuffer) return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -