需要在Android平台上通过UVC得到纯YUV数据,需要验证数据的正确性。因此需要将每一帧的YUV数据转为RGB888,但纯的RGB888数据也无法在windows或者ubuntu上打开,需要加BMP头。此文章介绍其实现方法。
第一步:YUY2转为RGB888.
参考文章:
http://blog.csdn.net/jtujtujtu/article/details/3874621
////////////////////////////////////////////////////////////////////////// // YUV2RGB // pYUV point to the YUV data // pRGB point to the RGB data // width width of the picture // height height of the picture // alphaYUV is there an alpha channel in YUV // alphaRGB is there an alpha channel in RGB ////////////////////////////////////////////////////////////////////////// int YUV2RGB(void* pYUV, void* pRGB, int width, int height, bool alphaYUV, bool alphaRGB) { if (NULL == pYUV) { return -1; } unsigned char* pYUVData = (unsigned char *)pYUV; unsigned char* pRGBData = (unsigned char *)pRGB; if (NULL == pRGBData) { if (alphaRGB) { pRGBData = new unsigned char[width*height*4]; } else pRGBData = new unsigned char[width*height*3]; } int Y1, U1, V1, Y2, alpha1, alpha2, R1, G1, B1, R2, G2, B2; int C1, D1, E1, C2; if (alphaRGB) { if (alphaYUV) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*3+j*6); U1 = *(pYUVData+i*width*3+j*6+1); Y2 = *(pYUVData+i*width*3+j*6+2); V1 = *(pYUVData+i*width*3+j*6+3); alpha1 = *(pYUVData+i*width*3+j*6+4); alpha2 = *(pYUVData+i*width*3+j*6+5); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*4+j*8+3) = alpha1; *(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2; *(pRGBData+(height-i-1)*width*4+j*8+7) = alpha2; } } } else { int alpha = 255; for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*2+j*4); U1 = *(pYUVData+i*width*2+j*4+1); Y2 = *(pYUVData+i*width*2+j*4+2); V1 = *(pYUVData+i*width*2+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*4+j*8+3) = alpha; *(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2; *(pRGBData+(height-i-1)*width*4+j*8+7) = alpha; } } } } else { if (alphaYUV) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*3+j*4); U1 = *(pYUVData+i*width*3+j*4+1); Y2 = *(pYUVData+i*width*3+j*4+2); V1 = *(pYUVData+i*width*3+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2; } } } else { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*2+j*4); U1 = *(pYUVData+i*width*2+j*4+1); Y2 = *(pYUVData+i*width*2+j*4+2); V1 = *(pYUVData+i*width*2+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2; } } } } return 0; } ////////////////////////////////////////////////////////////////////////// // RGB2YUV // pRGB point to the RGB data // pYUV point to the YUV data // width width of the picture // height height of the picture // alphaYUV is there an alpha channel in YUV // alphaRGB is there an alpha channel in RGB ////////////////////////////////////////////////////////////////////////// int RGB2YUV(void* pRGB, void* pYUV, int width, int height, bool alphaYUV, bool alphaRGB) { if (NULL == pRGB) { return -1; } unsigned char* pRGBData = (unsigned char *)pRGB; unsigned char* pYUVData = (unsigned char *)pYUV; if (NULL == pYUVData) { if (alphaYUV) { pYUVData = new unsigned char[width*height*3]; } else pYUVData = new unsigned char[width*height*2]; } int R1, G1, B1, R2, G2, B2, Y1, U1, Y2, V1; int alpha1, alpha2; if (alphaYUV) { if (alphaRGB) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { B1 = *(pRGBData+(height-i-1)*width*4+j*8); G1 = *(pRGBData+(height-i-1)*width*4+j*8+1); R1 = *(pRGBData+(height-i-1)*width*4+j*8+2); alpha1 = *(pRGBData+(height-i-1)*width*4+j*8+3); B2 = *(pRGBData+(height-i-1)*width*4+j*8+4); G2 = *(pRGBData+(height-i-1)*width*4+j*8+5); R2 = *(pRGBData+(height-i-1)*width*4+j*8+6); alpha2 = *(pRGBData+(height-i-1)*width*4+j*8+7); Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16); U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128); Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16; V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128); *(pYUVData+i*width*3+j*6) = Y1; *(pYUVData+i*width*3+j*6+1) = U1; *(pYUVData+i*width*3+j*6+2) = Y2; *(pYUVData+i*width*3+j*6+3) = V1; *(pYUVData+i*width*3+j*6+4) = alpha1; *(pYUVData+i*width*3+j*6+5) = alpha2; } } } else { unsigned char alpha = 255; for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { B1 = *(pRGBData+(height-i-1)*width*3+j*6); G1 = *(pRGBData+(height-i-1)*width*3+j*6+1); R1 = *(pRGBData+(height-i-1)*width*3+j*6+2); B2 = *(pRGBData+(height-i-1)*width*3+j*6+3); G2 = *(pRGBData+(height-i-1)*width*3+j*6+4); R2 = *(pRGBData+(height-i-1)*width*3+j*6+5); Y1 = ((66*R1+129*G1+25*B1+128)>>8) + 16; U1 = ((-38*R1-74*G1+112*B1+128)>>8+(-38*R2-74*G2+112*B2+128)>>8)/2 + 128; Y2 = ((66*R2+129*G2+25*B2+128)>>8) + 16; V1 = ((112*R1-94*G1-18*B1+128)>>8 + (112*R2-94*G2-18*B2+128)>>8)/2 + 128; Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16); U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128); Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16; V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128); *(pYUVData+i*width*3+j*6) = Y1; *(pYUVData+i*width*3+j*6+1) = U1; *(pYUVData+i*width*3+j*6+2) = Y2; *(pYUVData+i*width*3+j*6+3) = V1; *(pYUVData+i*width*3+j*6+4) = alpha; *(pYUVData+i*width*3+j*6+5) = alpha; } } } } else { if (alphaRGB) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { B1 = *(pRGBData+(height-i-1)*width*4+j*8); G1 = *(pRGBData+(height-i-1)*width*4+j*8+1); R1 = *(pRGBData+(height-i-1)*width*4+j*8+2); B2 = *(pRGBData+(height-i-1)*width*4+j*8+4); G2 = *(pRGBData+(height-i-1)*width*4+j*8+5); R2 = *(pRGBData+(height-i-1)*width*4+j*8+6); Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16); U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128); Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16; V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128); *(pYUVData+i*width*2+j*4) = Y1; *(pYUVData+i*width*2+j*4+1) = U1; *(pYUVData+i*width*2+j*4+2) = Y2; *(pYUVData+i*width*2+j*4+3) = V1; } } } else { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { B1 = *(pRGBData+(height-i-1)*width*3+j*6); G1 = *(pRGBData+(height-i-1)*width*3+j*6+1); R1 = *(pRGBData+(height-i-1)*width*3+j*6+2); B2 = *(pRGBData+(height-i-1)*width*3+j*6+3); G2 = *(pRGBData+(height-i-1)*width*3+j*6+4); R2 = *(pRGBData+(height-i-1)*width*3+j*6+5); Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16); U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128); Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16; V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128); *(pYUVData+i*width*2+j*4) = Y1; *(pYUVData+i*width*2+j*4+1) = U1; *(pYUVData+i*width*2+j*4+2) = Y2; *(pYUVData+i*width*2+j*4+3) = V1; } } } } return 0; } ////////////////////////////////////////////////////////////////////////// // pGBYUV point to the background YUV data // pFGYUV point to the foreground YUV data // width width of the picture // height height of the picture // alphaBG is there an alpha channel in background YUV data // alphaFG is there an alpha channel in fourground YUV data ////////////////////////////////////////////////////////////////////////// int YUVBlending(void* pBGYUV, void* pFGYUV, int width, int height, bool alphaBG, bool alphaFG) { if (NULL == pBGYUV || NULL == pFGYUV) { return -1; } unsigned char* pBGData = (unsigned char*)pBGYUV; unsigned char* pFGData = (unsigned char*)pFGYUV; if (!alphaFG) { if (!alphaBG) { memcpy(pBGData, pFGData, width*height*2); } else { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { *(pBGData+i*width*2+j*4) = *(pFGData+i*width*2+j*4); *(pBGData+i*width*2+j*4+1) = *(pFGData+i*width*2+j*4+1); *(pBGData+i*width*2+j*4+2) = *(pFGData+i*width*2+j*4+2); *(pBGData+i*width*2+j*4+3) = *(pFGData+i*width*2+j*4+3); } } } } int Y11, U11, V11, Y12, Y21, U21, V21, Y22; int alpha1, alpha2; if (!alphaBG) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y11 = *(pBGData+i*width*2+j*4); U11 = *(pBGData+i*width*2+j*4+1); Y12 = *(pBGData+i*width*2+j*4+2); V11 = *(pBGData+i*width*2+j*4+3); Y21 = *(pFGData+i*width*3+j*6); U21 = *(pFGData+i*width*3+j*6+1); Y22 = *(pFGData+i*width*3+j*6+2); V21 = *(pFGData+i*width*3+j*6+3); alpha1 = *(pFGData+i*width*3+j*6+4); alpha2 = *(pFGData+i*width*3+j*6+5); *(pBGData+i*width*2+j*4) = (Y21-16)*alpha1/255+(Y11-16)*(255-alpha1)/255+16; *(pBGData+i*width*2+j*4+1) = ((U21-128)*alpha1/255+(U11-128)*(255-alpha1)/255 + (U21-128)*alpha2/255+(U11-128)*(255-alpha2)/255)/2+128; *(pBGData+i*width*2+j*4+3) = ((V21-128)*alpha1/255+(V11-128)*(255-alpha1)/255 + (V21-128)*alpha2/255+(V11-128)*(255-alpha2)/255)/2+128; *(pBGData+i*width*2+j*4+2) = (Y22-16)*alpha2/255+(Y12-16)*(255-alpha2)/255+16; } } } else { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y11 = *(pBGData+i*width*3+j*6); U11 = *(pBGData+i*width*3+j*6+1); Y12 = *(pBGData+i*width*3+j*6+2); V11 = *(pBGData+i*width*3+j*6+3); Y21 = *(pFGData+i*width*3+j*6); U21 = *(pFGData+i*width*3+j*6+1); Y22 = *(pFGData+i*width*3+j*6+2); V21 = *(pFGData+i*width*3+j*6+3); alpha1 = *(pFGData+i*width*3+j*6+4); alpha2 = *(pFGData+i*width*3+j*6+5); *(pBGData+i*width*3+j*6) = (Y21-16)*alpha1/255+(Y11-16)*(255-alpha1)/255+16; *(pBGData+i*width*3+j*6+1) = ((U21-128)*alpha1/255+(U11-128)*(255-alpha1)/255 + (U21-128)*alpha2/255+(U11-128)*(255-alpha2)/255)/2+128; *(pBGData+i*width*3+j*6+3) = ((V21-128)*alpha1/255+(V11-128)*(255-alpha1)/255 + (V21-128)*alpha2/255+(V11-128)*(255-alpha2)/255)/2+128; *(pBGData+i*width*3+j*6+2) = (Y22-16)*alpha2/255+(Y12-16)*(255-alpha2)/255+16; } } } return 0; }
将转化后数据保存。
第二步,将纯RGB888转化为BMP文件,
参考http://my.csdn.net/meng_tianshi/code/detail/2092
保存为.c文件
/**************************** RGB加上头部信息转换成BMP 参数說明: rgb_buffer :RGB数据文件中的信息 nData :RGB数据的长度 nWidth :图像宽度的像素数 nHeight :图像高度的像素数 fp1 :所存放的文件 *****************************/ int RGB2BMP(char *rgb_buffer,int nWidth,int nHeight,FILE*fp1) { BmpHead m_BMPHeader; char bfType[2]={'B','M'}; m_BMPHeader.imageSize=3*nWidth*nHeight+54; m_BMPHeader.blank=0; m_BMPHeader.startPosition=54; fwrite(bfType,1,sizeof(bfType),fp1); fwrite(&m_BMPHeader.imageSize,1,sizeof(m_BMPHeader.imageSize),fp1); fwrite(&m_BMPHeader.blank,1,sizeof(m_BMPHeader.blank),fp1); fwrite(&m_BMPHeader.startPosition,1,sizeof(m_BMPHeader.startPosition),fp1); InfoHead m_BMPInfoHeader; m_BMPInfoHeader.Length=40; m_BMPInfoHeader.width=nWidth; m_BMPInfoHeader.height=nHeight; m_BMPInfoHeader.colorPlane=1; m_BMPInfoHeader.bitColor=24; m_BMPInfoHeader.zipFormat=0; m_BMPInfoHeader.realSize=3*nWidth*nHeight; m_BMPInfoHeader.xPels=0; m_BMPInfoHeader.yPels=0; m_BMPInfoHeader.colorUse=0; m_BMPInfoHeader.colorImportant=0; fwrite(&m_BMPInfoHeader.Length,1,sizeof(m_BMPInfoHeader.Length),fp1); fwrite(&m_BMPInfoHeader.width,1,sizeof(m_BMPInfoHeader.width),fp1); fwrite(&m_BMPInfoHeader.height,1,sizeof(m_BMPInfoHeader.height),fp1); fwrite(&m_BMPInfoHeader.colorPlane,1,sizeof(m_BMPInfoHeader.colorPlane),fp1); fwrite(&m_BMPInfoHeader.bitColor,1,sizeof(m_BMPInfoHeader.bitColor),fp1); fwrite(&m_BMPInfoHeader.zipFormat,1,sizeof(m_BMPInfoHeader.zipFormat),fp1); fwrite(&m_BMPInfoHeader.realSize,1,sizeof(m_BMPInfoHeader.realSize),fp1); fwrite(&m_BMPInfoHeader.xPels,1,sizeof(m_BMPInfoHeader.xPels),fp1); fwrite(&m_BMPInfoHeader.yPels,1,sizeof(m_BMPInfoHeader.yPels),fp1); fwrite(&m_BMPInfoHeader.colorUse,1,sizeof(m_BMPInfoHeader.colorUse),fp1); fwrite(&m_BMPInfoHeader.colorImportant,1,sizeof(m_BMPInfoHeader.colorImportant),fp1); fwrite(rgb_buffer,3*nWidth*nHeight,1,fp1); return 0; } //主函数 #include <string.h> #include <stdlib.h> #include <stdio.h> #include "rgb2bmp.h" int main() { FILE* p; /*************** input data *********** filename :RGB数据文件名称 nWidth :所生成文件的水平像素 nHeight :所生成文件的垂直像素 newFile :最终生成文件的名称 ***********************************************/ char* filename = "rgb888_800_480_woman"; int nWidth = 800; int nHeight = 480; char* newFile = "bmp2s (copy).bmp"; p = fopen(filename,"rb"); if (p == NULL) { printf("!!!file %s open failed.n", filename); return 0; } printf("file %s open success.n",filename); /*********** read Image Data **************/ long nData = nWidth*nHeight*3; char* rgb_buffer = malloc(nData*sizeof(char)); char* pVisit = rgb_buffer; fread(rgb_buffer,1,nData,p); printf("read file over.nData%ldn",nData); /*********** write file *******************/ FILE *result = fopen(newFile,"wb"); if (result == NULL) { printf("open new file failed.n"); return -1; } RGB2BMP(rgb_buffer,nWidth,nHeight,result); fclose(result); return 0; }
//rgb2bmp.h头文件 #include <stdio.h> typedef unsigned char BYTE; typedef unsigned short WORD; // BMP图像各部分说明如下 /*********** 第一部分 位图文件头 该结构的长度是固定的,为14个字节,各个域的依次如下: 2byte :文件类型,必须是0x4d42,即字符串"BM"。 4byte :整个文件大小 4byte :保留字,为0 4byte :从文件头到实际的位图图像数据的偏移字节数。 *************/ typedef struct { long imageSize; long blank; long startPosition; }BmpHead; /********************* /********************* 第二部分 位图信息头 该结构的长度也是固定的,为40个字节,各个域的依次说明如下: 4byte :本结构的长度,值为40 4byte :图像的宽度是多少象素。 4byte :图像的高度是多少象素。 2Byte :必须是1。 2Byte :表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。 4byte :指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。 4byte :指定实际的位图图像数据占用的字节数,可用以下的公式计算出来: 图像数据 = Width' * Height * 表示每个象素颜色占用的byte数(即颜色位数/8,24bit图为3,256色为1) 要注意的是:上述公式中的biWidth'必须是4的整数倍(不是biWidth,而是大于或等于biWidth的最小4的整数倍)。 如果biCompression为BI_RGB,则该项可能为0。 4byte :目标设备的水平分辨率。 4byte :目标设备的垂直分辨率。 4byte :本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的(颜色位数)次幂,如颜色位数为8,2^8=256,即256色的位图 4byte :指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色都是重要的。 ***********************************/ typedef struct { long Length; long width; long height; WORD colorPlane; WORD bitColor; long zipFormat; long realSize; long xPels; long yPels; long colorUse; long colorImportant; }InfoHead; /*************************** /*************************** 第三部分 调色盘结构 颜色表 对于256色BMP位图,颜色位数为8,需要2^8 = 256个调色盘; 对于24bitBMP位图,各象素RGB值直接保存在图像数据区,不需要调色盘,不存在调色盘区 rgbBlue: 该颜色的蓝色分量。 rgbGreen: 该颜色的绿色分量。 rgbRed: 该颜色的红色分量。 rgbReserved:保留值。 ************************/ typedef struct { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; }RGBMixPlate;