图片压缩格式和图片类型

来源:互联网 发布:裴雷网络黄金是真的吗 编辑:程序博客网 时间:2024/05/17 05:19

图片类型:GRAY,BGR,RGB,YUV等

图片格式:BMP,JPEG,PNG等

 

一、图片类型

RGB

RGB(R,G,B)  

BGR    

BGR(B,G,R)

GRAY

什么叫灰度图?任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
1.浮点算法:Gray=R*0.3+G*0.59+B*0.11
2.整数方法:Gray=(R*30+G*59+B*11)/100
3.移位方法:Gray =(R*76+G*151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。

YUV

 

二、图片格式

 

 

 

                                      typedef struct tagBIMAPINFOHEADER
                                      {
                                             DWORD biSize; //本结构所占用字节数
                                             LONG biWidth; //位图的宽度,以像素为单位
                                             LONG biHeight; //位图的高度,以像素为单位
                                             WORD biPlanes; //目标设备的级别,必须为1
                                             WORD biBitCount; //每个像素所需的位数,必须是1(双色)、4(16色)、8(256色)或24(真彩色)之一
                                             DWORD biCompression; //位图压缩类型,必须是 0(不压缩)、1(BI_RLE8压缩类型)或2(BI_RLE压缩类型)之一
                                             DWORD biSizeImage; //位图的大小,以字节为单位
                                             LONG biXPelsPerMeter; //位图水平分辨率,每米像素数
                                             LONG biYPelsPerMeter; //位图垂直分辨率,每米像素数
                                             DWORD biClrUsed; //位图实际使用的颜色表中的颜色数
                                             DWORD biClrImportant; //位图显示过程中重要的颜色数
                                    } BITMAPINFOHEADER
 
                                    颜色表颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,且定义一种颜色,定义如下:
                                    typedef struct tagRGBQUAD
                                    {
                                              BYTE rgbBlue; //蓝色的亮度(值范围为0~255)
                                              BYTE rgbGreen; //绿色的亮度(值范围为0~255)
                                              BYTE rgbRed; //红色的亮度(值范围为0~255)
                                              BYTE rgbReserved; //保留,必须为0
                                    } RGBQUAD;
 
                                   颜色表中RGBQUAD结构数据的个数由biBitCount来确定,当biBitCount=1、4、8时,分别有2、16、256个表项;当biBitCount=24时,没有颜色表项。
                                   位图数据记录了位图的每一个像素值,记录顺序是在扫描行内从左到右、扫描行之间从下到上。位图的一个像素值所占的字节数如下:
l                                  当biBitCount=1时,8个像素占1个字节。
l                                  当biBitCount=4时,2个像素占1个字节。
l                                  当biBitCount=8时,1个像素占1个字节。
l                                  当biBitCount=24时,1个像素占3个字节。(BGR类型)
                                   注意:位图中每行像素占得字节数表示位图的宽度。位图的宽度必须是4个字节的整数倍。即32位整数倍。int stride_out =((rc.right * 24 + 31) >> 5) << 2;

 

 

                                       Windows 3.1以上版本提供了对设备无关位图DIB(Device Independent Bitmap)的支持。DIB位图可以在不同的机器或系统中显示位图所固有

                                       的 图像。相对于DDB而言,DIB是一种外部位图格式,经常存储为常见的以BMP为后缀的位图文件(有时也以DIB为后缀)。因此,通常所说的

                                      BMP图像,即是DIB位图。

 

                                        2、RAW格式

                                       扩展名是RAW。RAW是一种无损压缩格式,它的数据是没有经过相机处理的原文件。

 

 



三、RGB2YUV


//转换矩阵
#define MY(a,b,c) (( a*  0.2989  + b*  0.5866  + c*  0.1145))
#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c*  0.5000 + 128))
#define MV(a,b,c) (( a*  0.5000  + b*(-0.4184) + c*(-0.0816) + 128))
//大小判断
#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c)))
#define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))
#define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))

//读BMP
bool ReadBmp(unsigned char *RGB, char *filename, int nw, int nh);
//写YUV文件
bool WriteYUV(unsigned char *YUV, int len, char *filename);
//转换函数
void ConvertRGB2YUV(unsigned char *RGB, unsigned char *YUV, int nw, int nh);

//读BMP rgb大小为nw*nh*3,申请nw*nh*3*2,利用后半部分控件进行数据转换,bmp格式的图片位图阵列是从左到右扫描,从下到上扫描,24位类型是BGR,
bool ReadBmp(unsigned char *RGB, char *filename, int nw, int nh)
{
 if(RGB == NULL) return false;

 unsigned char temp;
 unsigned char *pTemp = RGB + nw * (nh - 1) *3;
 unsigned char *pTempN = RGB + nw * nh * 3;
 int imgSize = nw * nh;
 int readSize = 0;

 FILE *fp = NULL;
 if((fp = fopen(filename, "rb")) == NULL) return false;

 fseek(fp,54, SEEK_SET);
 readSize = fread(pTempN, 1, imgSize * 3, fp);//读取
 fclose(fp);
 if(readSize != imgSize *3) return false;

 for(int i= 0; i <  nh; ++i)//bmp存储格式:从左到右,从上到下,调整为:从左到右,从上到下
 {
  memcpy(pTemp, pTempN, nw * 3);
  pTemp -= (nw * 3);
  pTempN += (nw * 3);
 }

 //bmp存储格式:BGR,调整为:RGB
 pTemp = RGB;
 for(int i = 0; i < nw * nh; i++)
 {
  temp = pTemp[0];
  pTemp[0] = pTemp[2];
  pTemp[2] = temp;
  pTemp += 3;
 }

 return true;
}
//转换函数  
void ConvertRGB2YUV(unsigned char *RGB, unsigned char *YUV, int nw, int nh)
{
 //变量声明
 unsigned int i, j;
 unsigned char *Y = NULL;
 unsigned char *U = NULL;
 unsigned char *V = NULL;

 Y = YUV;
 U = YUV + nw * nh;
 V = U + ((nw * nh) >> 2);

 for(int y = 0; y < nh; y++)
 {
  for(int x = 0; x < nw; x++)
  {
   j = y * nw + x;
   i = j*3;
   Y[j] = (unsigned char)(DY(RGB[i], RGB[i + 1], RGB[i + 2]));

   if((x % 2 == 1) && (y % 2 == 1))
   {
    j = (nw >> 1) * (y >> 1) + (x >> 1);
    //上面i仍有效
    U[j] = (unsigned char)
     ((DU(RGB[i], RGB[i + 1], RGB[i + 2]) + 
     DU(RGB[i - 3], RGB[i - 2], RGB[i - 1]) +
     DU(RGB[i  -nw * 3], RGB[i + 1 - nw * 3], RGB[i + 2 - nw * 3]) +
     DU(RGB[i - 3 - nw * 3], RGB[i - 2 - nw * 3], RGB[i - 1 - nw * 3])) / 4);

    V[j] = (unsigned char)
     ((DV(RGB[i], RGB[i + 1], RGB[i + 2]) + 
     DV(RGB[i - 3], RGB[i - 2], RGB[i - 1]) +
     DV(RGB[i - nw * 3], RGB[i + 1 - nw * 3], RGB[i + 2 - nw * 3]) +
     DV(RGB[i - 3 - nw * 3], RGB[i - 2 - nw * 3], RGB[i - 1 - nw * 3])) / 4);
   }
  }
 }
}
//写YUV文件  YUV字节数:nw*nh*3/2
bool WriteYUV(unsigned char *YUV, int len, char *filename)
{
 FILE *fp = NULL;
 if((fp = fopen(filename, "wb")) == NULL) return false;
 fwrite(YUV, 1, len, fp);
 fclose(fp);
}


//读取YUV文件int ReadYUV(unsigned char *YUV, char *filename, int nw, int nh){ if(YUV == NULL) return false; FILE *fp = NULL; int imgSize = nw * nh; imgSize = imgSize + (imgSize >> 1); int readSize = 0; if((fp = fopen(filename, "rb")) == NULL) return false; readSize = fread(YUV, 1, imgSize, fp); fclose(fp); if(readSize != imgSize) return false; return true;}

int stride_out =((rc.right * 24 + 31) >> 5) << 2; // 每行的字节数是4的倍数

//转换函数,扫描顺序从下到上(每行的字节数是4的倍数),从左到右void YUV2BGR(unsigned char *pbSrc, unsigned char *pbDest, int iSrcWidth, int iSrcHeight, int iBGRStride){int x, y, z;unsigned char *pY = reinterpret_cast< unsigned char* >(pbSrc);unsigned char *pCb = reinterpret_cast< unsigned char* >(pbSrc) + iSrcWidth * iSrcHeight;unsigned char *pCr = reinterpret_cast< unsigned char* >(pbSrc) + iSrcWidth * iSrcHeight + (iSrcWidth >> 1) * iSrcHeight;for (y = 0, z = iSrcHeight - 1; y < iSrcHeight; ++y, --z){for (x = 0; x < iSrcWidth; x++){int iY = *(pY + y * iSrcWidth + x);int iCb = *(pCb + y * (iSrcWidth >> 1) + (x >> 1));int iCr = *(pCr + y * (iSrcWidth >> 1) + (x >> 1));int iR = ((5742 * (iCr- 128)) +  (iY * 4096)) >> 12;int iG = (-1 * (1409 * (iCb - 128) + 2925 * (iCr - 128)) + (iY * 4096)) >> 12;int iB = (7258 * (iCb - 128) + (iY * 4096)) >> 12;//int iR = static_cast< int >(1.402 * (iCr - 128) + iY);//int iG = static_cast< int >(-0.34414 * (iCb - 128) - 0.71414 * (iCr - 128) + iY);//int iB = static_cast< int >(1.772 * (iCb - 128) + iY);if (iR > 255)iR = 255;if (iR < 0)iR = 0;if (iG > 255)iG = 255;if (iG < 0)iG = 0;if (iB > 255)iB = 255;if (iB < 0)iB = 0;pbDest[ z * iBGRStride + x * 3 ] = iB;pbDest[ z * iBGRStride + x * 3 + 1 ] = iG;pbDest[ z * iBGRStride + x * 3 + 2 ] = iR;}}}

void SaveBMP(int nw,int nh, char *pDBuf, char *sfName){// 灰色图,传送过来的数据是原始数据,扫描顺序是从上到下,从左到右,每行字节数不确定是否为4的字节数int rw = nw;while( rw % 4 != 0 ){++rw;}BITMAPFILEHEADER bfh;bfh.bfOffBits = 1078;bfh.bfReserved1 = 0;bfh.bfReserved2 = 0;bfh.bfType = 19778;bfh.bfSize = 1078 + ( nw * nh);BITMAPINFOHEADER bih;ZeroMemory(&bih,sizeof(BITMAPINFOHEADER));bih.biSize  = 40;bih.biWidth = nw; bih.biHeight = nh; bih.biPlanes = 1; bih.biBitCount=8; bih.biCompression=BI_RGB; int iLen = 1024 * 512;BYTE *pIData = new BYTE[iLen];BYTE *pd = pIData;memcpy(pd,&bfh,sizeof(BITMAPFILEHEADER)); pd += sizeof(BITMAPFILEHEADER);memcpy(pd,&bih,sizeof(BITMAPINFOHEADER)); pd += sizeof(BITMAPINFOHEADER);RGBQUAD colPalette[256];for(int n=0; n<256; n++) {colPalette[n].rgbBlue = n;colPalette[n].rgbGreen = n;colPalette[n].rgbRed = n;}memcpy(pd,colPalette,1024); pd += 1024;char *p = pDBuf;p += nw * (nh - 1);for(int i=0; i<nh; i++){memcpy(pd,p,rw);pd += rw;p -= nw;}FILE *wf = fopen(sfName,"wb");if( NULL != wf ){fwrite(pIData,1,1078+(rw*nh),wf);fclose(wf);}delete []pIData;}void SaveBmp(char *pData,int dlen,int nw,int nh, char *szName){// BGR,传送过来的数据不是原始数据,已经做了处理,扫描顺序是从下到上,从左到右,每行字节数是4的字节数FILE *wf = fopen(szName,"wb");if( NULL != wf ){BITMAPFILEHEADER bfh;memset(&bfh,0,sizeof(bfh));bfh.bfType = 19778;bfh.bfSize = 54 + dlen;bfh.bfOffBits = 54;fwrite(&bfh,1,sizeof(bfh),wf);BITMAPINFOHEADER bih;memset(&bih,0,sizeof(bih));bih.biSize = sizeof(bih);bih.biWidth = nw;bih.biHeight = nh;bih.biPlanes = 1;bih.biBitCount = 24;fwrite(&bih,1,sizeof(bih),wf);fwrite(pData,1,dlen,wf);fclose(wf);}}



 

以下几种算法未测试

\\算法一:  查表法


const int Table_fv1[256]={ -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162, -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139, -138, -137, -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118, -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96, -94, -93, -92, -90, -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71, -69, -68, -66, -65, -64, -62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45, -44, -43, -41, -40, -38, -37, -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20, -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 136, 137, 138, 140, 141, 143, 144, 145, 147, 148, 150, 151, 152, 154, 155, 157, 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };
const int Table_fv2[256]={ -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81, -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66, -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51, -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21, -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6, -5, -4, -3, -3, -2, -1, 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };
const int Table_fu1[256]={ -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39, -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31, -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24, -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43 };
const int Table_fu2[256]={ -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204, -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173, -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141, -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109, -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73, -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36, -34, -32, -31, -29, -27, -25, -24, -22, -20, -18, -16, -15, -13, -11, -9, -8, -6, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21, 23, 24, 26, 28, 30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141, 143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218, 219, 221, 223, 225 };

#define WIDTH 176

#define HEIGHT 144
#define PIXELSIZE WIDTH*HEIGHT
static void YV12_to_RGB24(unsigned char* pYV0, unsigned char* pYV1,
        unsigned char* pYV2,unsigned char* pRGB24)
{
 if(!pYV0 || !pRGB24)
  return ;
 
 const long nYLen = long(PIXELSIZE);
 const int nHfWidth = (WIDTH>>1);
 
 if(nYLen<1 || nHfWidth<1)
  return ;
 
 // Y data
 unsigned char* yData = pYV0;
 // v data
 unsigned char* vData = pYV1;
 // u data
 unsigned char* uData = pYV2;

 
 if(!uData || !vData)
  return ;
 
 int rgb[3];
 int i, j, m, n, x, y, pu, pv, py, rdif, invgdif, bdif;
 m = -WIDTH;
 n = -nHfWidth;
 
 bool addhalf = true;
 for(y=0; y<HEIGHT;y++) {
  m += WIDTH;
  if( addhalf ){
   n+=nHfWidth;
   addhalf = false;
  } else {
   addhalf = true;
  }
  for(x=0; x<WIDTH;x++)  {
   i = m + x;
   j = n + (x>>1);
   
   py = yData[i];
   
   // search tables to get rdif invgdif and bidif
   rdif = Table_fv1[vData[j]];    // fv1
   invgdif = Table_fu1[uData[j]] + Table_fv2[vData[j]]; // fu1+fv2
   bdif = Table_fu2[uData[j]]; // fu2
   
    rgb[0] = py+rdif;    // R
    rgb[1] = py-invgdif; // G
    rgb[2] = py+bdif;    // B

   j = nYLen - WIDTH - m + x;
   i = (j<<1) + j;
   
   // copy this pixel to rgb data
   for(j=0; j<3; j++)
   {
    if(rgb[j]>=0 && rgb[j]<=255){
     pRGB24[i + j] = rgb[j];
    }
    else{
     pRGB24[i + j] = (rgb[j] < 0)? 0 : 255;
    }
   }
  }
 }
}

 

算法二: cscc.lib

void YV12_to_RGB24(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,int width,int height);

在很多进行yuv与rgb图像格式转换的程序中都使用了cscc.lib这个库.

 

算法三: asm

//How to use:
//YUV_TO_RGB24(pY,width,pU,pV,width>>1,pRGBBuf,width,(int)0-height,width*3);

typedef    UCHAR     uint8_t;
typedef    ULONGLONG    uint64_t;

#define MAXIMUM_Y_WIDTH 1280
static uint64_t mmw_mult_Y     = 0x2568256825682568;
static uint64_t mmw_mult_U_G   = 0xf36ef36ef36ef36e;
static uint64_t mmw_mult_U_B   = 0x40cf40cf40cf40cf;
static uint64_t mmw_mult_V_R   = 0x3343334333433343;
static uint64_t mmw_mult_V_G   = 0xe5e2e5e2e5e2e5e2;
static uint64_t mmb_0x10       = 0x1010101010101010;
static uint64_t mmw_0x0080     = 0x0080008000800080;
static uint64_t mmw_0x00ff     = 0x00ff00ff00ff00ff;
static uint64_t mmw_cut_red    = 0x7c007c007c007c00;
static uint64_t mmw_cut_green = 0x03e003e003e003e0;
static uint64_t mmw_cut_blue   = 0x001f001f001f001f;

static void YUV_TO_RGB24(uint8_t *puc_y, int stride_y, 
       uint8_t *puc_u, uint8_t *puc_v, int stride_uv, 
       uint8_t *puc_out, int width_y, int height_y,int stride_out) 
{
  int y, horiz_count;
  uint8_t *puc_out_remembered;
//int stride_out = width_y * 3;
    
  if (height_y < 0) {
   //we are flipping our output upside-down
   height_y   = -height_y;
   puc_y      += (height_y    - 1) * stride_y ;
   puc_u      += (height_y/2 - 1) * stride_uv;
   puc_v      += (height_y/2 - 1) * stride_uv;
   stride_y   = -stride_y;
   stride_uv = -stride_uv;
  }
  horiz_count = -(width_y >> 3);
  for (y=0; y<height_y; y++) {
  if (y == height_y-1) {
    //this is the last output line - we need to be careful not to overrun the end of this line
    uint8_t temp_buff[3*MAXIMUM_Y_WIDTH+1];
    puc_out_remembered = puc_out;
    puc_out = temp_buff; //write the RGB to a temporary store
   }
   _asm {
    push eax
    push ebx
    push ecx
    push edx
    push edi
    mov eax, puc_out       
    mov ebx, puc_y       
    mov ecx, puc_u       
    mov edx, puc_v
    mov edi, horiz_count
    horiz_loop:
    movd mm2, [ecx]
    pxor mm7, mm7
    movd mm3, [edx]
    punpcklbw mm2, mm7       
    movq mm0, [ebx]          
    punpcklbw mm3, mm7       
    movq mm1, mmw_0x00ff     
    psubusb mm0, mmb_0x10    
    psubw mm2, mmw_0x0080    
    pand mm1, mm0            
    psubw mm3, mmw_0x0080    
    psllw mm1, 3             
    psrlw mm0, 8             
    psllw mm2, 3             
    pmulhw mm1, mmw_mult_Y   
    psllw mm0, 3             
    psllw mm3, 3             
    movq mm5, mm3            
    pmulhw mm5, mmw_mult_V_R 
    movq mm4, mm2            
    pmulhw mm0, mmw_mult_Y   
    movq mm7, mm1            
    pmulhw mm2, mmw_mult_U_G 
    paddsw mm7, mm5
    pmulhw mm3, mmw_mult_V_G
    packuswb mm7, mm7
    pmulhw mm4, mmw_mult_U_B
    paddsw mm5, mm0      
    packuswb mm5, mm5
    paddsw mm2, mm3          
    movq mm3, mm1            
    movq mm6, mm1            
    paddsw mm3, mm4
    paddsw mm6, mm2
    punpcklbw mm7, mm5
    paddsw mm2, mm0
    packuswb mm6, mm6
    packuswb mm2, mm2
    packuswb mm3, mm3
    paddsw mm4, mm0
    packuswb mm4, mm4
    punpcklbw mm6, mm2
    punpcklbw mm3, mm4
    // 32-bit shuffle.
    pxor mm0, mm0
    movq mm1, mm6
    punpcklbw mm1, mm0
    movq mm0, mm3
    punpcklbw mm0, mm7
    movq mm2, mm0
    punpcklbw mm0, mm1
    punpckhbw mm2, mm1
    // 24-bit shuffle and sav
    movd    [eax], mm0
    psrlq mm0, 32
    movd   3[eax], mm0
    movd   6[eax], mm2
 
    psrlq mm2, 32            
    movd   9[eax], mm2        
    // 32-bit shuffle.
    pxor mm0, mm0            
    movq mm1, mm6            
    punpckhbw mm1, mm0       
    movq mm0, mm3            
    punpckhbw mm0, mm7       
    movq mm2, mm0            
    punpcklbw mm0, mm1       
    punpckhbw mm2, mm1       
    // 24-bit shuffle and sav
    movd 12[eax], mm0        
    psrlq mm0, 32            
    movd 15[eax], mm0        
    add ebx, 8               
    movd 18[eax], mm2        
    psrlq mm2, 32            
    add ecx, 4               
    add edx, 4               
    movd 21[eax], mm2        
    add eax, 24              
    inc edi
    jne horiz_loop
    pop edi
    pop edx
    pop ecx
    pop ebx
    pop eax
    emms
   }
   if (y == height_y-1) {
    //last line of output - we have used the temp_buff and need to copy
    int x = 3 * width_y;                   //interation counter
    uint8_t *ps = puc_out;                 // source pointer (temporary line store)
    uint8_t *pd = puc_out_remembered;      // dest pointer
    while (x--) *(pd++) = *(ps++);           // copy the line
   }   puc_y    += stride_y;
   if (y%2) {
    puc_u    += stride_uv;
    puc_v    += stride_uv;
   }
   puc_out += stride_out; 
}
}

 

算法四: 数组

long int crv_tab[256];
long int cbu_tab[256];
long int cgu_tab[256];
long int cgv_tab[256];
long int tab_76309[256];
unsigned char clp[1024];

init_dither_tab()
{
 long int crv,cbu,cgu,cgv;
 int i,ind;
 
 crv = 104597; cbu = 132201; 
 cgu = 25675;  cgv = 53279;
 
 for (i = 0; i < 256; i++) {
  crv_tab[i] = (i-128) * crv;
  cbu_tab[i] = (i-128) * cbu;
  cgu_tab[i] = (i-128) * cgu;
  cgv_tab[i] = (i-128) * cgv;
  tab_76309[i] = 76309*(i-16);
 }
 
 for (i=0; i<384; i++)
  clp[i] =0;
 ind=384;
 for (i=0;i<256; i++)
  clp[ind++]=i;
 ind=640;
 for (i=0;i<384;i++)
 clp[ind++]=255;
}

YUV2RGB420(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,int width,int height)
{
 int y1,y2,u,v; 
 unsigned char *py1,*py2;
 int i,j, c1, c2, c3, c4;
 unsigned char *d1, *d2;
 
 py1=src0;
 py2=py1+width;
 d1=dst_ori;
 d2=d1+3*width;
 for (j = 0; j < height; j += 2) { 
  for (i = 0; i < width; i += 2) {
   
   u = *src1++;
   v = *src2++;
   
   c1 = crv_tab[v];
   c2 = cgu_tab[u];
   c3 = cgv_tab[v];
   c4 = cbu_tab[u];
   
   //up-left
   y1 = tab_76309[*py1++];    
   *d1++ = clp[384+((y1 + c1)>>16)];  
   *d1++ = clp[384+((y1 - c2 - c3)>>16)];
   *d1++ = clp[384+((y1 + c4)>>16)];
   
   //down-left
   y2 = tab_76309[*py2++];
   *d2++ = clp[384+((y2 + c1)>>16)];  
   *d2++ = clp[384+((y2 - c2 - c3)>>16)];
   *d2++ = clp[384+((y2 + c4)>>16)];
   
   //up-right
   y1 = tab_76309[*py1++];
   *d1++ = clp[384+((y1 + c1)>>16)];  
   *d1++ = clp[384+((y1 - c2 - c3)>>16)];
   *d1++ = clp[384+((y1 + c4)>>16)];
   
   //down-right
   y2 = tab_76309[*py2++];
   *d2++ = clp[384+((y2 + c1)>>16)];  
   *d2++ = clp[384+((y2 - c2 - c3)>>16)];
   *d2++ = clp[384+((y2 + c4)>>16)];
  }
  d1 += 3*width;
  d2 += 3*width;
  py1+=   width;
  py2+=   width;
        }
}

 

算法五: ffmpeg 中的swscale函数

 

这几个算法都实验了一下, 前4种算法在低分辨率的情况下都可以正常显示, 在解1280*720的视频时雪花点点, 只能采用第五种算法,

第五种的话可能比较麻烦一点, 涉及开源的ffmpeg.

cscc.lib源文件和头文件声明下载看这里:http://files.cnblogs.com/doorsky/cscc.lib.rar

ffmepg源码实例看这里:http://files.cnblogs.com/doorsky/ffmepg_H.264.rar

SDLDemo下载看这里:http://files.cnblogs.com/doorsky/SDLDemo.rar

更多ffmepg的相关资料参阅: http://www.bairuitech.com/html/ruanjianxiazai/index.html

中华视频网论坛: http://bbs.chinavideo.org/index.ph


四、图片解码、图片编码

以后完善。
往控件上绘制图片。

方法一
bool DrawPic(CDC *pDC, CRect rect, BYTE *pData, int iLen){if( !pData  || !pDC || iLen < 1 ){return false;}ULONG iWritten = NULL;  IStream *pStm = NULL;CreateStreamOnHGlobal( NULL, TRUE, &pStm );if( !pStm ){return false;}CPictureHolder picholder;  LARGE_INTEGER liTempstar ={0};pStm->Seek( liTempstar, STREAM_SEEK_SET, NULL );pStm->Write(pData, iLen, &iWritten);pStm->Seek( liTempstar, STREAM_SEEK_SET, NULL );if( SUCCEEDED(OleLoadPicture(pStm, iLen, TRUE, IID_IPicture, (void **)&picholder))) {                                                            picholder.Render(pDC, rect, CRect( 0, 0, 0, 0 ) );}pStm->Release();return true;}


方法二
#define SWFIDF_ZOMM_OPTION0x000F#define SWFIDF_ZOMM_ORIGIN0x0001#define SWFIDF_ZOOM_INSIDE0x0002#define SWFIDF_ALIGN_OPTION0x00F0#define SWFIDF_ALIGN_CENTER0x0010#define SWFIDF_BACK_FILL0x1000static SWFRESULT SWFImage_Draw(SWFIMAGE *pImage, HDC hDC, int nTargetW, int nTargetH, int nX, int nY, int nFlag = 0){if (!pImage || (!pImage->pEnc && !pImage->pRaw)) return SWF_E_NULL;SWFRESULT nRet = SWF_S_OK;unsigned char *pBits = NULL;BYTE pBMIBufGray[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)] = {0};BITMAPINFO* pBMI = (BITMAPINFO*)pBMIBufGray;if (!pImage->pRaw){if (pImage->nEncType == SWFIET_NONE){nRet = SWFImage_DecodeInfo(pImage);if (SWFFAIL(nRet)) return nRet;}if (pImage->nEncType == SWFIET_JPG){unsigned long ul = CHECKJPEGFORMAT;if ((ExtEscape(hDC, QUERYESCSUPPORT, sizeof(ul), (LPCSTR)&ul, 0, 0) > 0) &&// Check if CHECKJPEGFORMAT exists:(ExtEscape(hDC, CHECKJPEGFORMAT, pImage->nEncLen, (LPCSTR)pImage->pEnc, sizeof(ul), (LPSTR)&ul) > 0) &&// Check if CHECKJPEGFORMAT executed without error:(ul == 1) )// Check status code returned by CHECKJPEGFORMAT:{pBMI->bmiHeader.biCompression = BI_JPEG;pBMI->bmiHeader.biSizeImage = pImage->nEncLen;pBits = pImage->pEnc;}}if (pImage->nEncType == SWFIET_PNG){unsigned long ul = CHECKPNGFORMAT;if ((ExtEscape(hDC, QUERYESCSUPPORT, sizeof(ul),(LPCSTR) &ul, 0, 0) > 0) &&// Check if CHECKPNGFORMAT exists:(ExtEscape(hDC, CHECKPNGFORMAT, pImage->nEncLen, (LPCSTR)pImage->pEnc, sizeof(ul), (LPSTR)&ul) > 0) &&// Check if CHECKPNGFORMAT executed without error:(ul == 1) )// Check status code returned by CHECKPNGFORMAT:{pBMI->bmiHeader.biCompression = BI_PNG;pBMI->bmiHeader.biSizeImage = pImage->nEncLen;pBits = pImage->pEnc;}}if (!pBits){nRet = SWFImage_Decode(pImage);if (SWFFAIL(nRet)) return nRet;}}if (!pBits){pBMI->bmiHeader.biCompression = BI_RGB;pBMI->bmiHeader.biBitCount = pImage->nClrBit;if (pImage->nClrBit == 8){for (int i = 0; i < 256; i++){pBMI->bmiColors[i].rgbBlue = i;pBMI->bmiColors[i].rgbRed = i;pBMI->bmiColors[i].rgbGreen = i;pBMI->bmiColors[i].rgbReserved = 0;}}if ((pImage->nWidth % 4) == 0) pBits = pImage->pRaw;else{int nLineWidth =  pImage->nWidth * pImage->nClrBit / 8;int nWidthPad = (nLineWidth  + 3) & ~3;pBits = new unsigned char[nWidthPad * pImage->nHeight];for (int i = 0; i < pImage->nHeight; i++){memcpy(pBits + i * nWidthPad, pImage->pRaw + i * nLineWidth, nLineWidth);}}}// 确定目标图像大小int nDrawW, nDrawH;switch (nFlag & SWFIDF_ZOMM_OPTION){default:nDrawW = nTargetW;nDrawH = nTargetH;break;case SWFIDF_ZOMM_ORIGIN:nDrawW = pImage->nWidth;nDrawH = pImage->nHeight;break;case SWFIDF_ZOOM_INSIDE:{double dXRate = 1.0 * nTargetW / pImage->nWidth;double dYRate = 1.0 * nTargetH / pImage->nHeight;double dRate  = min(dXRate, dYRate);nDrawW = (int)(dRate * pImage->nWidth);nDrawH = (int)(dRate * pImage->nHeight);}break;}// 确定目标图像位置int nDrawX, nDrawY;switch (nFlag & SWFIDF_ALIGN_OPTION){default:nDrawX = nX;nDrawY = nY;case SWFIDF_ALIGN_CENTER:nDrawX = nX + (nTargetW - nDrawW) / 2;nDrawY = nY + (nTargetH - nDrawH) / 2;break;}// 画图pBMI->bmiHeader.biSize   = sizeof(BITMAPINFOHEADER);pBMI->bmiHeader.biPlanes = 1;pBMI->bmiHeader.biWidth  = pImage->nWidth;pBMI->bmiHeader.biHeight = -pImage->nHeight; // top-down imagenRet = SWF_S_OK;if (GDI_ERROR == (StretchDIBits(hDC, nDrawX, nDrawY, nDrawW, nDrawH, 0, 0, pImage->nWidth, pImage->nHeight, pBits, pBMI, DIB_RGB_COLORS, SRCCOPY))) nRet = SWF_E_FAIL;if (pBits != pImage->pRaw && pBits != pImage->pEnc) delete[] pBits;if (nFlag & SWFIDF_BACK_FILL){RECT rcBack;if (nDrawX > nX){rcBack.left= nX;rcBack.right= nDrawX;rcBack.top= nY;rcBack.bottom= nY + nTargetH;::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcBack, NULL, 0, NULL);}if (nDrawY > nY){rcBack.left= nX;rcBack.right= nX + nTargetW;rcBack.top= nY;rcBack.bottom= nDrawY;::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcBack, NULL, 0, NULL);}if (nDrawX + nDrawW < nX + nTargetW){rcBack.left= nDrawX + nDrawW;rcBack.right= nX + nTargetW;rcBack.top= nY;rcBack.bottom= nY + nTargetH;::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcBack, NULL, 0, NULL);}if (nDrawY + nDrawH < nY + nTargetH){rcBack.left= nX;rcBack.right= nX + nTargetW;rcBack.top= nDrawY + nDrawH;rcBack.bottom= nY + nTargetH;::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcBack, NULL, 0, NULL);}}return nRet;}

方法三
//往picter控件中画图void ShowPic(CString str){CFile file;CFileFind finder;BOOL bWorking = finder.FindFile(str);if(!bWorking){str="test.jpg";}CDC* pDc = statictp.GetDC();IPicture* pPic;  IStream* pStm;      ::CoInitialize(NULL); // COM 初始化//打开文件并获得文件的真实大小if(file.Open(str,CFile::modeRead | CFile::shareDenyNone )) // 读入文件内容{ULONGLONG dwSize = file.GetLength();if(dwSize>0){//从堆中分配指定数量字节的一整块,这时系统无法提供零零碎碎的局部或全局的堆HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwSize);      LPVOID pvData = NULL; if(NULL != hGlobal) {  //锁定全局内存对象并返回它的首地址if(NULL != (pvData = GlobalLock(hGlobal)))      {  //把文件内容读进全局内存对象的地址空间中file.Read(pvData,dwSize);  file.Close();//GlobalUnlock函数把以GMEM_MOVEABLE方式分配的内存对象的锁定计数器减GlobalUnlock(hGlobal);  //从全局内存中创建stream对象,第二个参数指定当stream释放时是否自动释放全局内存if(SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStm))){//创建一个新的picture对象并用stream对象中的内容初始化if(SUCCEEDED(OleLoadPicture(pStm, dwSize, TRUE, IID_IPicture, (LPVOID*)&pPic))) {   long nWidth,nHeight; // 宽高,MM_HIMETRIC 模式,单位是.01毫米pPic->get_Width( &nWidth ); // 宽pPic->get_Height( &nHeight ); // 高////////按窗口尺寸显示////////CRect rect; statictp.GetClientRect(&rect);pPic->Render(pDc->m_hDC,0,0,rect.Width(),rect.Height(),0,nHeight,nWidth,-nHeight,NULL);///////////////////////////////pDc->SetBkMode(TRANSPARENT);  // 释放IStream 指针,同时释放了hGlobalpStm->Release(); pStm = NULL;  //释放不要的picture对象,并把指针清空pPic->Release(); pPic = NULL;  //释放不要的全局内存对象,这个千万别忘了(32位程序不需要这行,系统会自动释放;位程序一定要) FreeResource(hGlobal); } }}}}}ReleaseDC(pDc);::CoUninitialize();}


1 0
原创粉丝点击