使用GDI+保存图像为8bpp的灰度图像

使用GDI+保存图像为8bpp的灰度图像,GDI+真的有些特殊。。。。。哭


//   Greyscale conversion
#define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8)	// .299R + .587G + .114B
//#define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9)	// .33R + 0.5G + .17B


// BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
// 功能:保存图片为8位的灰度图像
// 参数: pszPath要保存的文件名
BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
{Bitmap *ima = this->m_pBitmap;		// GDIPlusImage的Bitmap对象if (!ima || !pszPath || !*pszPath){return FALSE;}int width = m_pBitmap->GetWidth();int height = m_pBitmap->GetHeight();int bitcount = 8;			//1, 4, 8, 24, 32////Build bitmap headerBITMAPFILEHEADER bitmapFileHeader; BITMAPINFOHEADER bitmapInfoHeader; BYTE			 rgbquad[4];			// RGBQUADint				 index = 0;DWORD stride = ((bitcount*width + 31)/32)*4;		//每行都是4的倍数,或者说是DWORD大小的倍数switch(bitcount) { case 1: index = 2; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4); break; case 4: index = 16; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4); break; case 8: index = 256; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)); break; case 24: case 32: index = 0; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); break; default:break;} //构造Bitmap文件头BITMAPFILEHEADER bitmapFileHeader.bfType = 0x4d42;    // 很重要的标志位  BM 标识bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * stride);		//bmp文件长度  bitmapFileHeader.bfReserved1 = 0; bitmapFileHeader.bfReserved2 = 0; //构造Bitmap文件信息头BITMAPINFOHEADER bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfoHeader.biWidth = width; bitmapInfoHeader.biHeight = height; bitmapInfoHeader.biPlanes = 1; bitmapInfoHeader.biBitCount = bitcount;bitmapInfoHeader.biCompression = BI_RGB;				// 未压缩bitmapInfoHeader.biSizeImage = height * stride; bitmapInfoHeader.biXPelsPerMeter = 3780; bitmapInfoHeader.biYPelsPerMeter = 3780; bitmapInfoHeader.biClrUsed = 0; bitmapInfoHeader.biClrImportant = 0; //创建BMP内存映像,写入位图头部BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize];		// 我的位图pMyBmpBYTE *curr = pMyBmp;									// curr指针指示pMyBmp的位置memset(curr, 0, bitmapFileHeader.bfSize); //写入头信息 memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));curr = pMyBmp + sizeof(BITMAPFILEHEADER); memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); curr += sizeof(BITMAPINFOHEADER);//构造调色板 if(8 == bitcount) {rgbquad[3] = 0;										//rgbReservedfor(int i = 0; i < 256; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = i; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } }else if (4 == bitcount){rgbquad[3] = 0;for (int i = 0; i < 16; i++){rgbquad[0] = rgbquad[1] = rgbquad[2] = i; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); }}else if(1 == bitcount) { rgbquad[3] = 0;										//rgbReservedfor(int i = 0; i < 2; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } }//用GDI+加载数据源,也可以是其他的,写入文件数据Rect rect(0,0,width,height);		// Gdiplus+BitmapData bmData;Status iSucess = ima->LockBits(&rect,ImageLockModeRead,ima->GetPixelFormat() ,&bmData);BYTE *_pixels = (BYTE*)bmData.Scan0;	//原图rect区域内存位置的起始指针,以BYTE作为单元类型BYTE *_pRow;int _strideoff8 = stride - width;			//前面计算的索引图像的strideBYTE _grey;// build pixles, GDI+ (windows)的图像数据的原点在左下角,参考一下OpenCV的IplImage结构体switch(ima->GetPixelFormat()){case PixelFormat24bppRGB:{int _strideoff24 = stride - 3*width;			//前面计算的索引图像的stride//  灰度化for (int i=height-1; i >= 0; i--){_pRow = _pixels + i*bmData.Stride;		// 当前的行for (int j=width-1; j >= 0; j--){	BYTE* _pixels_b;		//bBYTE* _pixels_g;		//gBYTE* _pixels_r;		//r_pixels_b = _pRow++;  //blue_pixels_g = _pRow++;  //green_pixels_r = _pRow++;  //red_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey;    //根据红绿蓝求出此像素的灰度值curr++;}curr += _strideoff8;}}break;case PixelFormat32bppARGB:{//  灰度化for (int i=height-1;i>=0;i--){_pRow = _pixels + i*bmData.Stride;for (int j=width-1;j>=0;j--){			BYTE* _pixels_b;BYTE* _pixels_g;		BYTE* _pixels_r;		_pixels_b = _pRow++;  //blue_pixels_g = _pRow++;  //green_pixels_r = _pRow++;  //red_pRow++;_grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey;curr++;}curr += _strideoff8;}}break;case PixelFormat8bppIndexed:  // Gdi+只能保存成24位真彩色的图像{// 不能直接用memcpy复制,需要水平镜像,memcpy(curr, _pixels, height * stride);for (int i=height-1; i >= 0; i--){_pRow = _pixels + i*bmData.Stride;
// 				for (int j=width-1;j >= 0;j--)
// 				{	
// 					_grey = *_pRow++; 
// 					*curr = _grey; 
// 					curr++;
// 				}memcpy(curr, _pRow, width);curr += stride;}}break;default:break;}// 保存图像 pMyBmp 到文件try{CFile f(pszPath, CFile::modeCreate | CFile::modeWrite );f.Write(pMyBmp, bitmapFileHeader.bfSize);f.Close();}catch( CFileException* e ){TCHAR szCause[255];e->GetErrorMessage(szCause, 255);CString msg;msg.Format(_T("file error: %s, m_cause:%d\n"),szCause, e->m_cause);TRACE1("%s",msg);AfxMessageBox(msg);e->Delete();}//clean:ima->UnlockBits(&bmData);delete[] pMyBmp;return TRUE;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/243325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对象类型和数据类型

对象类型和数据类型 Verilog数据类型 Verilog语言具有针对硬件的变量类型和线网类型。这些类型具有特定的仿真和综合语义&#xff0c;表示芯片或系统中的实际连接行为。 &#xff08;1&#xff09;Verilog的reg、integer和time变量的每一位都有四种逻辑&#xff1a;0、1、Z、X…

尺度空间(Scale space)理论

尺度空间方法的基本思想是&#xff1a;在视觉信息处理模型中引入一个被视为尺度的参数&#xff0c;通过连续变化尺度参数获得不同尺度下的视觉处理信息&#xff0c;然后综合这些信息以深入地挖掘图像的本质特征。尺度空间方法将传统的单尺度视觉信息处理技术纳入尺度不断变化的…

[转] Windows CE 6.0 启动过程分析

看到这么好的文章&#xff0c;小郭觉得不转载就是天理不容&#xff0c;转了&#xff01;&#xff01;&#xff01;&#xff01; *************************************************************************************** 在Windows CE 6.0中&#xff0c;内核&#xff08;Ke…

数据类型规则的放宽

数据类型规则的放宽 SystemVreilog放宽了使用变量的限制 SystemVreilog放宽了变量的使用规则&#xff0c;大大简化了模型中数据类型的使用。在SystemVreilog中共&#xff0c;任何数据类型的变量都可以通过下列方式赋值&#xff0c;但只能采用其中的一种方式。 &#xff08;1&a…

真实,让文学回到原点:关于非虚构写作的思考

任何一种文学主张&#xff0c;其实都是先有实践&#xff0c;而后再有理论和命名。“非虚构写作”也是如此。如果大胆猜想&#xff0c;“非虚构写作”可能要追溯到远古的口传心记和结绳记事。当时的人类记录下身边发生的事情&#xff0c;应该就是非虚构&#xff0c;而口头讲述的…

4位16色灰度图像处理

定义几个辅助的宏&#xff0c;如下。 // 拆分合并BYTE #define HIBITS(w) ((BYTE)((((BYTE)(w)) >> 4) & 0xf)) #define LOBITS(w) ((BYTE)(((BYTE)(w)) & 0xf)) #define MAKEBITS(a, b) ((BYTE)(((BYTE)(((BYTE)(a)) & 0xf)) | ((…

[转] 常见WinCE启动失败原因分析

*********************************************** 一般情况下&#xff0c;为设计中的IC开发SW方案&#xff0c;难免会碰到Bootloader/EBoot/OS启动失败的情况&#xff0c;对于Bootloader和EBoot&#xff0c;由于源代码很少&#xff0c;直接使用Trace32调试是最佳方法&#xff…

树莓派安装mariadb redis

安装软件 sudo apt install mariadb-server mariadb-client sudo apt install redis 二. 配置 1, mariadb 配置 配置远程访问 maridb configuration: sudo mysql_secure_installation # 设置root密码 vim.tiny mariadb.conf.d/50-server.cnf # 设置去除本地绑定 #bind-addre…

Google云服务降价,整合持续集成工具,支持Windows和托管虚拟机

本周二&#xff0c;Google举行了云平台的现场活动&#xff08;点击查看视频记录&#xff09;&#xff0c;展示了一系列新特性、改进和全新定价模型。\u0026#xD;\n定价\u0026#xD;\nGoogle认为&#xff0c;云计算价格应该跟随硬件领域的摩尔定律&#xff0c;而且在过去数年间硬件…

静态和自动变量

静态和自动变量 自动变量–也可以称为动态变量&#xff0c;主要是用来描述在测试程序、抽象系统级、交易级或总线功能模型中的验证程序。自动变量的另一个用途就是编写可重入的任务&#xff0c;当一个任务的前一次调用仍然在执行时&#xff0c;可以再次对其调用。 自动变量也允…

图像拉普拉斯金字塔融合(Laplacian Pyramid Blending)

转摘的&#xff0c;修改了下程序&#xff0c;图像融合看不太懂 。。。。http://blog.csdn.net/abcjennifer/article/details/7628655#comments // 转摘的别人的程序 // #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h>…

[转]GIS简介

************************************************** 最近论坛上经常有人讨论GIS&#xff0c;特意从别人的blog中转了一篇GIS简介的帖子************************************************** 地理信息系统(GIS,Geographic Information System)是一门用计算机来研究地理的学科…

debug设计

debug设计 会用到debug设计的阶段 (1)RTL级设计仿真 (2)实施后的设计模拟 (3)在系统调试 使用网表插入调试探测流动 (1)最高级别是一个简单的向导,用于创建和配置集成逻辑分析仪 (ILA)内核会根据选定的一组网络自动进行调试。 (2)下一级是主调试窗口,允许控制单个…

ASA 9.21 in Vmware Workstation 10

There is old post “ASA 8.02 in Vmware Workstation “ in this blog posted on Dec 2011. Anothe post “How to Make your own ASA 8.42 in VMware”. Here are all related posts in this blog: ASA 8.02 in Vmware WorkstationASA 8.42 in VMware WorkstationASA 9.21 i…

MMU及PTS说明

MMU与PTS表格 最近在FPGA上仿真调试Virgo&#xff08;基于ARM11的一款处理器&#xff09;芯片。MMU部分总是出错&#xff0c;具体的现象是查看物理地址和虚拟地址的映射时候芯片经常会挂掉。先是怀疑MMU的寄存器配置有问题&#xff0c;后来又怀疑MMU映射使用的PTS表格有问题&a…

bug?VS2010中CImageList::DrawIndirect总是返回失败

//VS2010 #if _MSC_VER > 1600pImageList->Draw(pDC, nImage, point, ILD_NORMAL); #elseSIZE size;size.cx rect.Width() < sizeImage.cx ? rect.Width() : sizeImage.cx;size.cy rect.Height() < sizeImage.cy ? rect.Height() : sizeImage.cy;pImageList-&g…

VHDL基本结构

VHDL基本结构 (1)实体(Entity):描述所设计的系统的外部接口信号,定义电路设计中得到所有的输入和输出端口。 (2)结构体(Architecture):描述系统内部的结构和行为 (3)包集合(Package):存放各设计模块能共享的数据类型、常数和子程序等; (4)配置(Configurat…

Source Code Collection for Reproducible Research

转自&#xff1a;http://www.csee.wvu.edu/~xinl/source.html “It doesnt matter how beautiful your theory is, it doesnt matter how smart you are. If it doesnt agree with experiment, its wrong” - Richard Feynman "As a method for finding things out, scien…

IClass与电源管理

IClass与电源管理 前段时间为J9项目上添加电源管理&#xff0c;中间走了一些弯路。之前错误的认为&#xff0c;IClass只是与电源状态的改变方法有关&#xff0c;也就是说IClass的正确与否只会影响到设备电源状态的正确与否&#xff0c;而不会造成设备是否可以支持设备电源状态的…

状态机在VHDL中的实现

状态机在VHDL中的实现 1、Moore状态机的VHDL描述 输出仅取决于所处的状态 LIBRARY IEEE; --库、程序包的说明调用 USE IEEE.STD_LOGIC_1164.ALL;ENTITY Moore IS PORT (RESET,CLOCK,DIN : IN STD_LOGIC;DOUT : OUT STD_LOGIC_VECTOR(2 DOWNTO 0) ); END;ARCHITECTURE Mo…