zoukankan      html  css  js  c++  java
  • 我的第一个MFC小项目(4)之 位图转换(续)

    非常感谢Imageshop的指正,代码有修改,主要是:

    1. 计算8位位图像素位使用了更高效的整点运算;
    2. 去除多余的变量检测。

    求网友们支招:在32位位图中有Alpha值,在转换成8位灰阶位图的时候可以直接省略吗?                                                                                            

    我的第一个MFC小项目(3)之 位图转换中,有关于将24位的彩色位图转换为8位的灰阶位图,发散一下就很容易可以得到32位位图彩图转换为8位的灰阶位图,看图:

    image 

     32位位图多出一个Alpha字节,用来描述图片的透明度,根据这一特性,可以将Alpha特意忽略,然后将紧跟其后的RGB按照我的第一个MFC小项目(3)之 位图转换中24位位图转8位灰阶位图的方法就可以很轻易地达到我们的目的。这一次的位图转换接口我优化了一下,下面给出代码

    void Convertto8Bit(LPWSTR lpSrcFileName,LPWSTR lpDestFileName)
    {
    	HANDLE hFile;					//文件句柄
    	DWORD dwWritten;			//记录以写入的字节数
    	hFile   =   CreateFile(lpSrcFileName,GENERIC_READ,
    	FILE_SHARE_READ,
    	NULL,
    	OPEN_EXISTING,
    	FILE_FLAG_SEQUENTIAL_SCAN,
    	NULL);
    
    	BITMAPFILEHEADER  bmfh;					//文件头
    	ReadFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
    
    	BITMAPINFOHEADER   bmif;					//信息头
    	ReadFile(hFile,&bmif,40,&dwWritten,NULL);  
    
    	DWORD   dwSizeImage;						//源文件像素位大小
    	dwSizeImage   =									//获取 像素位 的大小,分配空间
    		bmif.biSizeImage;
    
    	BYTE * pBits   =   new BYTE[dwSizeImage];   
    	ReadFile(hFile,pBits,dwSizeImage,&dwWritten,NULL);
    
    	::CloseHandle(hFile);
    
    	long  lSrcWidth = bmif.biWidth;					//原图长与宽
    	long lSrcHeight = bmif.biHeight;
    
    	long lLineBytes;							//原图每行总字节数
    	long lScanWidth;						//转换为8位图之后的宽度,必须是大于原图且为4的倍数
    
    	lLineBytes = (lSrcWidth*4);			
    	/*
    	if(lLineBytes<lSrcWidth*4)					//在这里转换需要比原图每行总字节数大
    		lLineBytes += 4;
    	*/
    
    	lScanWidth = (lSrcWidth/4)*4;			//8位位图的宽度必须为4的倍数,在这里转换需要比原图宽度大
    	if(lScanWidth<lSrcWidth)
    		lSrcWidth += 4;
    
    	DWORD dwSizeNewImage = lSrcWidth * lSrcHeight + 2;			//为什么要预留两位呢
    	BYTE * bits = new BYTE[dwSizeNewImage];
    
    	for(int i=0; i<lSrcHeight; i++)
    	{
    		for(int j=0; j<lSrcWidth; j++)
    		{
    			BYTE color[3];						//对应RGB的红绿蓝值
    			DWORD dwColorTemp;			//Y值,RGB转换为Y之后的值Y=0.299*R+0.587*G+0.114*B
    			for(int s=0;s<3; s++)			//一个RGB对应一个Y值
    				color[s]=pBits[i*lLineBytes+j*4+s+1];
    
    			/*
    			dwColorTemp=unsigned int(color[2]*0.299+color[1]*0.587+color[0]*0.114);     
    			*/
    			//换成更高效的计算,确实快很多
    			dwColorTemp=unsigned int(color[2]*30+color[1]*59+color[0]*11+50)/100;     
    
    			//多余的变量检测
    			/*
    			if(dwColorTemp>255)
    				dwColorTemp = 255;
    			if(dwColorTemp<0)
    				dwColorTemp = 0;
    			*/
    
    			bits[i*lScanWidth+j]=(unsigned char)dwColorTemp;
    		}
    	}
    	bits[dwSizeNewImage-1] = 0;
    	bits[dwSizeNewImage-2] = 0;
    
    	RGBQUAD   *rgbQuad   =   new   RGBQUAD[256];   //颜色表
    	for(int i=0;i<256;i++)   
    	{   
    		rgbQuad[i].rgbBlue   =   i;     
    		rgbQuad[i].rgbGreen   =   i;     
    		rgbQuad[i].rgbRed   =   i;     
    		rgbQuad[i].rgbReserved   =   0;     
    	}   
    
    	//完善8位位图的文件头和信息头字段
    
    	bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) +
    		sizeof(BITMAPINFOHEADER) + 
    		256*sizeof(RGBQUAD);				//颜色表有256个
    
    	bmfh.bfReserved1 = 0;
    	bmfh.bfReserved2 = 0;
    	
    	bmfh.bfSize = bmfh.bfOffBits + dwSizeNewImage;			//size in byte of the file
    
    	bmif.biBitCount = 8;															//信息头中bitcounts改为8
    	bmif.biSizeImage =  dwSizeNewImage;
    
    	//写入转换后得到的8位位图
    	hFile=CreateFile(lpDestFileName,GENERIC_WRITE,
    		FILE_SHARE_WRITE,NULL,
    		CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    	::WriteFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
    	::WriteFile(hFile,&bmif,sizeof(BITMAPINFOHEADER),&dwWritten,NULL);
    	::WriteFile(hFile,rgbQuad,256*sizeof(RGBQUAD),&dwWritten,NULL);
    	::WriteFile(hFile,bits,dwSizeNewImage,&dwWritten,NULL);
    	::CloseHandle(hFile);
    }

    换汤不换药的。另外在这里问问大牛们,用MFC做图像处理的工程,是不是最好用单文档或者单文档之类的框架?

    传送门:

    我的第一个MFC小项目(3)之 位图转换


     捣乱小子 2011-12-20

    ps:欢迎讨论

    更多请访问:http://daoluan.net
  • 相关阅读:
    oracle一些常用的单记录函数
    javascript闭包(closure)
    【Matlab开发】matlab中bar绘图设置与各种距离度量
    【Matlab开发】matlab中bar绘图设置与各种距离度量
    【Matlab开发】matlab中norm范数以及向量点积、绘图设置相关
    【Matlab开发】matlab中norm范数以及向量点积、绘图设置相关
    【编程开发】opencv实现对Mat中某一列或某一行的元素进行normalization
    【编程开发】opencv实现对Mat中某一列或某一行的元素进行normalization
    【编程开发】C语言中随机数rand使用注意事项
    【编程开发】C语言中随机数rand使用注意事项
  • 原文地址:https://www.cnblogs.com/daoluanxiaozi/p/2295114.html
Copyright © 2011-2022 走看看