图片压缩格式和图片类型
来源:互联网 发布:裴雷网络黄金是真的吗 编辑:程序博客网 时间:2024/05/17 05:19
图片类型:GRAY,BGR,RGB,YUV等
图片格式:BMP,JPEG,PNG等
一、图片类型
RGB
RGB(R,G,B)
BGR
BGR(B,G,R)
GRAY
YUV
RGB
对一种颜色进行编码的方法统称为“颜色空间”或“色域”。用最简单的话说,世界上任何一种颜色的“颜色空间”都可定义成一个固定的数字或变量。RGB (红、绿、蓝)只是众多颜色空间的一种。采用这种编码方法,每种颜色都可用三个变量来表示—红色、绿色以及蓝色的强度。记录及显示彩色图像时,RGB是最 常见的一种方案。但是,它缺乏与早期黑白显示系统的良好兼容性。因此,件多电子电器厂商普遍采用的做法是,将RGB转换成YUV颜色空同,以维持兼容,再 根据需要换回RGB格式,以便在电脑显示器上显示彩色图形。
YUV
YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL)。YUV主要用于优化彩色视频信号的传输,使其向后兼容老式黑白电视。与RGB视频信号传 输相比,它最大的优点在于只需占用极少的带宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是 灰阶值;而“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是通过 RGB输入信号来创建的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面—色调与饱和度,分别用U和V来表示。其中,V反映了 GB输入信号红色部分与RGB信号亮度值之间的差异。而U反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。
YCrCb 是YUV的一个特例,它是将UV的值限定在了0-1之间
Cb相当于U, Cr相当于V,与RGB之间的转换如下:
R′G′B′是指伽玛修正过的RGB值,正常的RGB值的公式是同样的。
公式一:(标准公式)
Y = 0.299 R + 0.587 G + 0.114 B
Cr = ((B-Y)/1.772) + 0.5
Cb = ((R-Y)/1.402) + 0.5
用8-bit格式表示就是
以下两个公式已经修正到[0-255]的范围
公式二:(RGB => YCbCr)
Y = 0.257R′ + 0.504G′ + 0.098B′ + 16
Cb = -0.148R′ - 0.291G′ + 0.439B′ + 128
Cr = 0.439R′ - 0.368G′ - 0.071B′ + 128
公式三:(YCbCr => RGB)
R′ = 1.164(Y - 16) + 1.596(Cr - 128)
G′ = 1.164(Y - 16) - 0.813(Cr - 128) - 0.392(Cb - 128)
B′ = 1.164(Y - 16) + 2.017(Cb - 128)
二、图片格式
Windows 3.1以上版本提供了对设备无关位图DIB(Device Independent Bitmap)的支持。DIB位图可以在不同的机器或系统中显示位图所固有
的 图像。相对于DDB而言,DIB是一种外部位图格式,经常存储为常见的以BMP为后缀的位图文件(有时也以DIB为后缀)。因此,通常所说的
BMP图像,即是DIB位图。
2、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();}
- 图片压缩格式和图片类型
- 图片压缩格式
- 图片压缩与格式转换
- 图片的格式与压缩
- 相册图片选取,图片压缩和图片jpg、png格式的转换
- 图片选择和图片压缩
- GIF 格式图片的存储和压缩 Node.js实现
- 截图和压缩图片
- Android 新的图片压缩格式
- Unity的图片压缩格式详解
- Unity项目UI图片压缩格式(UGUI)
- Unity项目UI图片压缩格式(UGUI)
- java实现图片压缩(格式、裁剪)--------
- 图片内存溢出和图片压缩
- iOS 中图片压缩和图片上传
- 本地预览图片和前端图片压缩
- phpPHP创建创建jpg格式图片以及压缩图片
- phpPHP创建创建jpg格式图片以及压缩图片
- make xxxconfig/Kconfig
- 《Linux设备驱动程序》——块设备驱动程序
- poj 2363 Blocks
- Android系统下载管理DownloadManager功能介绍及使用示例
- STL源码学习之迭代器
- 图片压缩格式和图片类型
- HTML 30分钟入门教程
- 小波变换
- ps aux指令詳解
- 并发新特性—Executor框架与线程池
- IOS应用上传到app store记录
- 我对自己目标的设想
- hdu 4107 Gangster (离线+打标记+树状数组)
- AMBA