📄 yuvtofromrgb.c
字号:
/**************************************************************************** * * ROUTINE : CopyYUVtoBmp * * INPUTS : YUV_BUFFER_ENTRY_PTR YUVPtr * Pointers to the raw yuv planes. * * BOOL ConvertAll * Should all blocks be converted or only those marked for update. * * BOOL ReconBuffer * Is the input buffer fromatted as a reconstruction buffer or is * it a simple YUV buffer. * * OUTPUTS : UINT8 * BmpPtr, * Pointer to buffer to contain the BGR data. * * * RETURNS : None. * * FUNCTION : Copies data in a YUV sturcture into a bitmaps data part. * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/void CopyYUVtoBmp( PB_INSTANCE * pbi, YUV_BUFFER_ENTRY_PTR YUVPtr, UINT8 * BmpPtr, BOOL ConvertAll __attribute__((unused)), BOOL ReconBuffer ){ unsigned x, y; //static UINT8 YDisp[MAX_FRAGMENTS], *UDisp, *VDisp; //BOOL UVRow = TRUE; //BOOL UVColumn = TRUE; int YFrag; // fragment numbers being processed int Quadrant0; int Quadrant1; int Quadrant2; int Quadrant3; //UINT32 YDispOffset = 0; // Set up UV quadrant offsets Quadrant0 = 0; Quadrant1 = 4; if ( ReconBuffer ) Quadrant2 = pbi->Configuration.UVStride * 4; // (UV plane width * 4) else Quadrant2 = pbi->Configuration.VideoFrameWidth * 2; // (UV plane width * 4) Quadrant3 = Quadrant2 + 4; /* Now scan Y list and update any blocks that need it */ /* This will update any Y blocks in need as well as any UV blocks marked */ /* above. */ YFrag = 0; for ( y = 0; y < pbi->VFragments; y++ ) { for ( x = 0; x < pbi->HFragments; x++ ) { if ( pbi->display_fragments[YFrag] || pbi->display_fragments[pbi->YPlaneFragments + YFrag / 4] || pbi->display_fragments[pbi->YPlaneFragments + pbi->UVPlaneFragments +YFrag / 4] ) /* Need to update Y */ { int ublock = pbi->YPlaneFragments + (( y >> 1 ) * ( pbi->HFragments >> 1 )) + ( x >> 1 ); int vblock = ublock + pbi->UVPlaneFragments; int uvoffset; if ( x & 1 ) uvoffset = y & 1 ? Quadrant3: Quadrant1; else uvoffset = y & 1 ? Quadrant2: Quadrant0; if ( ReconBuffer ) { pbi->YUVtoRGB ( pbi, YUVPtr + ReconGetFragIndex ( pbi->recon_pixel_index_table, YFrag ), YUVPtr + ReconGetFragIndex ( pbi->recon_pixel_index_table, ublock ), YUVPtr + ReconGetFragIndex ( pbi->recon_pixel_index_table, vblock ), uvoffset, (BGR_TYPE *) BmpPtr + GetFragIndex ( pbi->pixel_index_table, YFrag ), ReconBuffer ); } else { pbi->YUVtoRGB ( pbi, YUVPtr + GetFragIndex ( pbi->pixel_index_table, YFrag ), YUVPtr + GetFragIndex ( pbi->pixel_index_table, ublock ), YUVPtr + GetFragIndex ( pbi->pixel_index_table, vblock ), uvoffset, (BGR_TYPE *) BmpPtr + GetFragIndex ( pbi->pixel_index_table, YFrag ), ReconBuffer ); } } YFrag++; } }}/**************************************************************************** * * ROUTINE : SetupRgbYuvAccelerators * * INPUTS : Nonex. * * OUTPUTS : None. * * RETURNS : None * * FUNCTION : Pre-calculates numbers for acceleration of RGB<->YUV * * SPECIAL NOTES : None. * * * ERRORS : None. * ****************************************************************************/void SetupRgbYuvAccelerators(){ #define Clamp255( x) (unsigned char) ( (x) < 0 ? 0 : ( (x) <= 255 ? (x) : 255 ) ) INT32 i; LimitVal_VP31[0] = 0; for( i = 0; i < VAL_RANGE * 3; i++) { int x = i - VAL_RANGE; LimitVal_VP31[ i] = Clamp255( x); } // V range raw is +/- 179. // Correct to approx 16-240 by dividing by 1.596 and adding 128. // U range raw is +/- 226. // Correct to approx 16-240 by dividing by 2.018 and adding 128. for( i = -VAL_RANGE; i < VAL_RANGE; i++) { INT32 x; if ( i < 0 ) { x = (INT32)((i / 1.596) - 0.5) + 128; CalcVTable[ i + VAL_RANGE] = Clamp255(x); CalcUTable[ i + VAL_RANGE] = (signed char)((i / 2.018) - 0.5) + 128; } else { x = (INT32)((i / 1.596) + 0.5) + 128; CalcVTable[ i + VAL_RANGE] = Clamp255( x); CalcUTable[ i + VAL_RANGE] = (signed char)((i / 2.018) + 0.5) + 128; } } for( i = 0; i < VAL_RANGE * 10; i++) DivByTen[i] = (UINT8)((i + 5) / 10); for( i = 0; i < (VAL_RANGE * 14); i++) { INT32 x = (i - (VAL_RANGE * 4)); if ( x < 0 ) x = (INT32)((x / 5.87) - 0.5); else x = (INT32)((x / 5.87) + 0.5); DivBy5p87[i] = Clamp255( x); } for( i = 0; i < VAL_RANGE; i++) { InvYScale[i] = Clamp255( (i - 16) / YFACTOR); if ( i < 128 ) { CalcRVTable[i] = (INT32) ( ((i - 128) * 1.596) - 0.5 ); CalcRUTable[i] = (INT32) ( ((i - 128) * 2.018) - 0.5 ); } else { CalcRVTable[i] = (INT32) ( ((i - 128) * 1.596) + 0.5 ); CalcRUTable[i] = (INT32) ( ((i - 128) * 2.018) + 0.5); } Times2p99[i] = (INT32)((i * 2.99) + 0.5); Times5p87[i] = (INT32)((i * 5.87) + 0.5); Times1p14[i] = (INT32)((i * 1.14) + 0.5); TimesTen[i] = (INT32)(i * 10); } #undef Clamp255}/**************************************************************************** * * ROUTINE : ConvertBmpToYUV * * INPUTS : None * * OUTPUTS : None. * * RETURNS : None. * * FUNCTION : Loads a frame from disk and converts it to YUV. * * SPECIAL NOTES : Matrix assumed to be: * * Y = .587G + .299R + .114B * U = B - Y * V = R - Y * * ERRORS : None. * ****************************************************************************/void ConvertBmpToYUV( PB_INSTANCE *pbi, UINT8 * BmpDataPtr, UINT8 * YuvBufferPtr ){ UINT32 i, j; YUV_ENTRY YVal; /* Workspace for calculating YU and V */ YUV_BUFFER_ENTRY_PTR UPtr; YUV_BUFFER_ENTRY_PTR VPtr; YUV_BUFFER_ENTRY_PTR YPtr; YUV_BUFFER_ENTRY_PTR YPtrEven; YUV_BUFFER_ENTRY_PTR YPtrOdd; BGR_TYPE * RGBPtr; BGR_TYPE * RGBPtrEven; BGR_TYPE * RGBPtrOdd; UINT8 * VLookupTable = &CalcVTable[256]; UINT8 * ULookupTable = &CalcUTable[256]; /* Set up pointers into the YUV data structure. */ YPtr = YuvBufferPtr; UPtr = &YuvBufferPtr[(pbi->Configuration.VideoFrameHeight * pbi->Configuration.VideoFrameWidth)]; VPtr = &YuvBufferPtr[((pbi->Configuration.VideoFrameHeight * pbi->Configuration.VideoFrameWidth)*5)/4]; // Set up the pointers the the RGB data buffer (actually BGR). */ RGBPtr = (BGR_TYPE *)BmpDataPtr; /* For the moment the U and V will be taken from the first pixel in the group of four. */ for ( i = 0; i < pbi->Configuration.VideoFrameHeight; i += 2 ) { RGBPtrEven = (BGR_TYPE *)RGBPtr; RGBPtrOdd = RGBPtrEven + pbi->Configuration.VideoFrameWidth; YPtrEven = YPtr; YPtrOdd = YPtrEven + pbi->Configuration.VideoFrameWidth; for (j = 0; j < pbi->Configuration.VideoFrameWidth; j += 2 ) { int R,B,Y; // compute Y. YVal = Times1p14[RGBPtrEven->Blue] + Times5p87[RGBPtrEven->Green] + Times2p99[RGBPtrEven->Red]; YPtrEven[0] = (UINT8)DivByTen[YVal]; Y = YPtrEven[0]; R = RGBPtrEven->Red; B = RGBPtrEven->Blue; YPtrEven[0] = (UINT8)(((double)(YPtrEven[0]) * YFACTOR) + 16); // Scale the Y value to the approximate range 16-235. RGBPtrEven++; YVal = Times1p14[RGBPtrEven->Blue] + Times5p87[RGBPtrEven->Green] + Times2p99[RGBPtrEven->Red]; YPtrEven[1] = (UINT8)DivByTen[YVal]; Y += YPtrEven[1]; R += RGBPtrEven->Red; B += RGBPtrEven->Blue; YPtrEven[1] = (UINT8)(((double)(YPtrEven[1]) * YFACTOR) + 16); // Scale the Y value to the approximate range 16-235. RGBPtrEven++; YVal = Times1p14[RGBPtrOdd->Blue] + Times5p87[RGBPtrOdd->Green] + Times2p99[RGBPtrOdd->Red]; YPtrOdd[0] = (UINT8)DivByTen[YVal]; Y += YPtrOdd[0]; R += RGBPtrOdd->Red; B += RGBPtrOdd->Blue; YPtrOdd[0] = (UINT8)(((double)(YPtrOdd[0]) * YFACTOR) + 16); // Scale the Y value to the approximate range 16-235. RGBPtrOdd++; YVal = Times1p14[RGBPtrOdd->Blue] + Times5p87[RGBPtrOdd->Green] + Times2p99[RGBPtrOdd->Red]; YPtrOdd[1] = (UINT8)DivByTen[YVal]; Y += YPtrOdd[1]; R += RGBPtrOdd->Red; B += RGBPtrOdd->Blue; YPtrOdd[1] = (UINT8)(((double)(YPtrOdd[1]) * YFACTOR) + 16); // Scale the Y value to the approximate range 16-235. RGBPtrOdd++; // Calculate U and V using average Y,R,B for the four pixels *UPtr = ULookupTable[(2 + B - Y) >> 2]; // +2 is for rounding *VPtr = VLookupTable[(2 + R - Y) >> 2]; // +2 is for rounding UPtr++; VPtr++; // Step on Y pointers on YPtrEven += 2; YPtrOdd += 2; } // Step on to start of next pair of rows. RGBPtr += (pbi->Configuration.VideoFrameWidth * 2); YPtr += (pbi->Configuration.VideoFrameWidth * 2); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -