使用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,一经查实,立即删除!

相关文章

尺度空间(Scale space)理论

尺度空间方法的基本思想是&#xff1a;在视觉信息处理模型中引入一个被视为尺度的参数&#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>…

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…

状态机在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…

VHDL仿真

VHDL仿真 仿真(Simulation也称模拟),不接触具体的硬件系统利用计算机对电路设计的逻辑行为和运行功能进行模拟检测,较大规模的VHDL系统设计的最后完成必须经历多层次的仿真测试过程,包括针对系统的VHDL行为仿真、分模块的时序仿真和硬件仿真,直至最后系统级的硬件仿真测…

关于结构体的内容

关于结构体的内容 结构体使用类似于C语言的语法来定义 结构体使用struct关键字声明。结构体内的成员可以是任何数据类型&#xff0c;包括用户自定义类型和其他的结构体类型。 struct{int a,b; //32位变量opcode_t opcode;//用户定义类型logic [23:0] adress;//24位变量bit er…

Pushing Policy Failed because Checkpoint Firewall “Load on module failed – no memory”

One day when pushing firewall policy from Checkpoint management server to UTM 272 cluster gateways, it failed and I got error message “Load on module failed – no memory” on one of cluster members. “Network Security Policy ‘Montreal_DMZ’ was prepared …

Point-BERT:一种基于Transformer架构的点云深度网络

目录 1. 前言 2. Point Tokenization 3. Transformer Backbone 4. Masked Point Modeling 5. Experiments Reference 1. 前言 从PointNet [1] 开始&#xff0c;点云深度网络逐渐成为解决点云特征提取与语义分析的主要研究方向。尤其在OpenAI的GPT模型获得了突破性成果后&#…

GNS3 VoIP Lab (Cisco 3725 and CME 4.3)

Here is a simple VoIP Lab in GNS3 environment. It is only used for my lab test and recorded here for future reference. 1. Topology: GNS3 Topology:Logic Topology:xp(192.168.2.60)——–C3725 Router(192.168.2.10) 2. Enviroment: ESXi 5.5 (or Vmware Workstation…

关于数组的内容

关于数组的内容 Verilog数组声明的基本语法 <data_type><vector_size><array_name><array_dimension> 例如&#xff1a; reg[15:0] RAM [0:4095];//储存器数组SystemVerilog允许任何数据类型的非压缩数组 SystemVerilog将非压缩数组的声明进行了扩展…

BreadCrumb控件

BreadCrumb控件&#xff0c;如上图所示&#xff0c;即面包屑导航控件&#xff0c;类似于TreeCtrl&#xff0c;但不是一次显示所有的Item&#xff0c;VC 2010可以编译通过&#xff0c;稍微修改一下其他的也可以编译&#xff0c;源代码下载&#xff1a; http://download.csdn.net…

Android简介

最近Android很火&#xff0c;小弟也想了解一下它的结构。跟CE或者Mobile比起来&#xff0c;它的结构是有点凌乱&#xff0c;也难怪&#xff0c;毕竟是基于别人的内核在上层开发了一些应用 ---------------------------------------------------------------------------------…

说不尽的刘恒

认识刘恒快三十年了&#xff0c;作为曾经的同事和他小说的责任编辑&#xff0c;我只写过他一篇文章&#xff0c;还是在二十多年前。有时候特别熟悉的人反而不知道从何写起&#xff0c;因为一想起往事&#xff0c;各种记忆像开闸的水一样涌满眼前&#xff0c;让人很难落笔。1985…

外行看Flash的存储原理

突然在网上看到别人两年前写的一篇关于nor和nand的好文章&#xff0c;做为csdn的合法公民&#xff0c;有必要转 一、存储数据的原理 两种闪存都是用三端器件作为存储单元&#xff0c;分别为源极、漏极和栅极&#xff0c;与场效应管的工作原理相同&#xff0c;主要是利用电场的…

快速计算整数的二进制表示法中1的个数

快速计算整数的二进制表示法中1的个数 题目&#xff1a;给定一个无符号32位整数x&#xff0c;求x的二进制表示法中含1的个数&#xff1f; 第一种算法&#xff1a; int OneCount(unsigned int x){ for(int count0; x>0; count) x&x-1;//把最后面的1变0 return …

在C/C++代码中使用SSE等指令集的指令(1)介绍

http://blog.csdn.net/gengshenghong/article/details/7007100我们知道&#xff0c;在C/C代码中&#xff0c;可以插入汇编代码提高性能。现在的指令集有了很多的高级指令&#xff0c;如果我们希望使用这些高级指令来实现一些高效的算法&#xff0c;就可以在代码中嵌入汇编&…

赋值操作符

赋值操作符 和其他赋值操作符 out in;//将out和in相加并将结果赋值给out //out out in;注意&#xff1a;这些操作符都是阻塞赋值packdage definitions;typedef enum logic[2:0] {ADD,SUB,MULT,DIV,SL.SR} opcode_t;typedef enum logic{UNSIGNED,SIGNED}operand_type_t;typ…

有无关通配符的相等操作符

有无关通配符的相等操作符 逻辑相等操作符 条件相等操作 SystemVerilog通配符相等操作符允许屏蔽某些位 SystemVerilog还增加了两个新的比较操作符&#xff1a; &#xff1f; 和&#xff01;&#xff1f;。这两个操作符允许在比较中屏蔽无关位。 操作符 &#xff1f;&#x…

cab文件介绍及制作方法

转自&#xff1a;http://bbs.pcpop.com/091030/5945399.html 1. 什么是cab文件 CAB在电脑上是一种压缩文件&#xff0c;微软出品的东西&#xff0c;用WinRAR可以解压缩&#xff0c;在DOS启动盘里面可以看见一些CAB压缩文件。其实Windows里面已经带了CAB压缩程序&#xff0c;但…

CVE-2015-0235: GHOST – A Critical Vulnerability in the Glibc Library

GHOST is a ‘buffer overflow’ bug affecting the gethostbyname() and gethostbyname2() function calls in the glibc library. If a remote attacker can make an application call to gethostbyname() or gethostbyname2(), this vulnerability allows the remote attack…