IplImage和CBitmap转换
- 格式:doc
- 大小:29.00 KB
- 文档页数:2
VC++中图像处理类CBitmap的⽤法VC++中图像处理类CBitmap的⽤法class CBitmap : public CGdiObject{DECLARE_DYNAMIC(CBitmap)public:static CBitmap* PASCAL FromHandle(HBITMAP hBitmap);// ConstructorsCBitmap();BOOL LoadBitmap(LPCTSTR lpszResourceName);BOOL LoadBitmap(UINT nIDResource);BOOL LoadOEMBitmap(UINT nIDBitmap); // for OBM_/OCR_/OIC_#ifndef _AFX_NO_AFXCMN_SUPPORTBOOL LoadMappedBitmap(UINT nIDBitmap, UINT nFlags = 0,LPCOLORMAP lpColorMap = NULL, int nMapSize = 0);#endifBOOL CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitcount,const void* lpBits);BOOL CreateBitmapIndirect(LPBITMAP lpBitmap);BOOL CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight);BOOL CreateDiscardableBitmap(CDC* pDC, int nWidth, int nHeight);// Attributesoperator HBITMAP() const;int GetBitmap(BITMAP* pBitMap);// OperationsDWORD SetBitmapBits(DWORD dwCount, const void* lpBits);DWORD GetBitmapBits(DWORD dwCount, LPVOID lpBits) const;CSize SetBitmapDimension(int nWidth, int nHeight);CSize GetBitmapDimension() const;// Implementationpublic:virtual ~CBitmap();#ifdef _DEBUGvirtual void Dump(CDumpContext& dc) const;#endif};⽗CGdiObjectclass CGdiObject : public CObject{DECLARE_DYNCREATE(CGdiObject)public:// AttributesHGDIOBJ m_hObject; // must be first data memberoperator HGDIOBJ() const;HGDIOBJ GetSafeHandle() const;static CGdiObject* PASCAL FromHandle(HGDIOBJ hObject);static void PASCAL DeleteTempMap();BOOL Attach(HGDIOBJ hObject);HGDIOBJ Detach();// ConstructorsCGdiObject(); // must Create a derived class objectBOOL DeleteObject();// Operations#pragma push_macro("GetObject")#undef GetObjectint _AFX_FUNCNAME(GetObject)(int nCount, LPVOID lpObject) const;int GetObject(int nCount, LPVOID lpObject) const;#pragma pop_macro("GetObject")UINT GetObjectType() const;BOOL CreateStockObject(int nIndex);BOOL UnrealizeObject();BOOL operator==(const CGdiObject& obj) const;BOOL operator!=(const CGdiObject& obj) const;// Implementationpublic:virtual ~CGdiObject();#ifdef _DEBUGvirtual void Dump(CDumpContext& dc) const;virtual void AssertValid() const;#endif};1 装载已导⼊⼯程的位图资源// 装载位图CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP);2 装载位图⽂件为了能让CBitmap能够装载位图⽂件,必须调⽤API函数LoadImage HANDLE LoadImage(HINSTANCE hinst, // handle of the instance containing the imageLPCTSTR lpszName, // name or identifier of imageUINT uType, // type of imageint cxDesired, // desired widthint cyDesired, // desired heightUINT fuLoad // load flags);装载: Example 1:HBITMAP hBmp = (HBITMAP)LoadImage(NULL,m_fileName,IMAGE_BITMAP,0, 0,LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_DEFAULTSIZE); Example 2:HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),"BG.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);将装载后得到的HBITMAP资源句柄与 CBitmap 对象相连if (hBmp != NULL) {CBitmap *pBmp = CBitmap::FromHandle(hBmp);}或CBitmap bmp;if (hBmp != NULL) {bmp.DeleteObject();bmp.Attach(hBmp);}3 显⽰位图CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);BITMAP bm;bmp.GetBitmap(&bm);CDC dc;dc.CreateCompatibleDC(pDC);CBitmap*pOldBmp=(CBitmap *)dc.SelectObject(&bmp);pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);pDC->SelectObject(pOldBmp);bmp.DeleteObject();bmp.LoadBitmap(IDB_BITMAP2);4 删除资源CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP);CBitmap *pOld=pDC->SelectObject(&bmp);// 此时位图对象还在pDC中,因此不能马上删除// ⽽是先将位图从DC中选出然后再删除pDC->SelectObject(pOld);bmp.DeleteObject();5 CBitmap 析构当CBitmap作为局部变量在其退出作⽤范围后,会发⽣析构,这时候CBitmap会将其对应的位图资源(hBitmap )释放掉。
OpenCV中Mat与IplImage和CvMat类型之间的相互转换OpenCV中Mat与IplImage和CvMat类型之间的相互转换Mat 类型较CvMat和IplImage有更强的矩阵运算能力,支持常见的矩阵运算(参照Matlab中的各种矩阵运算),所以将IplImage类型和CvMat类型转换为Mat类型更易于数据处理。
Mat类型可用于直接存储图像信息,通过函数imread、imwrite、imshow等实现(与Matlab中的函数相似),似乎在某种程度上可以取代IplImage类型。
(1)将IplImage类型转换到Mat类型Mat::Mat(constIplImage* img, boolcopyData=false);默认情况下,新的Mat类型与原来的IplImage类型共享图像数据,转换只是创建一个Mat矩阵头。
当将参数copyData设为true后,就会复制整个图像数据。
例:IplImage* iplImg = cvLoadImage("greatwave.jpg", 1);Mat mtx(iplImg); // IplImage* ->Mat 共享数据// or : Mat mtx = iplImg;(2)将Mat类型转换到IplImage类型同样只是创建图像头,而没有复制数据。
例:IplImageipl_img = img; // Mat ->IplImage(3)将CvMat类型转换为Mat类型与IplImage的转换类似,可以选择是否复制数据。
Mat::Mat(constCvMat* m, boolcopyData=false);(4)将Mat类型转换为CvMat类型与IplImage的转换类似,不复制数据,只创建矩阵头。
例:// 假设Mat类型的imgMat图像数据存在CvMatcvMat = imgMat; // Mat ->CvMat。
Halcon和C#联合编程-图像变量的相互转换(HObject、HImage、Bitmap)/// <summary>/// 灰度图像 HObject -> Bitmap/// </summary>public static Bitmap HObject2Bitmap(HObject ho){try{HTuple type, width, height, pointer;//HOperatorSet.AccessChannel(ho, out ho, 1);HOperatorSet.GetImagePointer1(ho, out pointer, out type, out width, out height);//himg.GetImagePointer1(out type, out width, out height);Bitmap bmp = new Bitmap(width.I, height.I, PixelFormat.Format8bppIndexed);ColorPalette pal = bmp.Palette;for (int i = 0; i <= 255; i++){pal.Entries[i] = Color.FromArgb(255, i, i, i);}bmp.Palette = pal;BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8;int stride = bitmapData.Stride;int ptr = bitmapData.Scan0.ToInt32();for (int i = 0; i < height; i++){CopyMemory(ptr, pointer, width * PixelSize);pointer += width;ptr += bitmapData.Stride;}bmp.UnlockBits(bitmapData);return bmp;}catch (Exception exc){return null;}}/// <summary>/// 灰度图像 HObject -> HImage1/// </summary>public HImage HObject2HImage1(HObject hObj){HImage image = new HImage();HTuple type, width, height, pointer;HOperatorSet.GetImagePointer1(hObj, out pointer,out type, out width, out height);image.GenImage1(type, width, height, pointer);return image;}/// <summary>/// 彩⾊图像 HObject -> HImage3/// </summary>public HImage HObject2HImage3(HObject hObj){HImage image = new HImage();HTuple type, width, height, pointerRed, pointerGreen, pointerBlue;HOperatorSet.GetImagePointer3(hObj, out pointerRed, out pointerGreen, out pointerBlue,out type, out width, out height);image.GenImage3(type, width, height, pointerRed, pointerGreen, pointerBlue);return image;}。
我们知道,Visual C++的CBitmap类和静态图片控件的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。
因此,想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码。
现在,MFC和ATL共享的新类CImage为图像处理提供了许多相应的方法,这使得Visual C++在图像方面的缺憾一去不复返了。
CImage类概述CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。
由于CImage在不同的Windows操作系统中其某些性能是不一样的,因此在使用时要特别注意。
例如,CImage::PlgBlt和CImage::MaskBlt只能在Windows NT 4.0 或更高版本中使用,但不能运行在Windows 95/98 应用程序中。
CImage::AlphaBlend和CImage::TransparentBlt也只能在Windows 2000/98或其更高版本中使用。
即使在Windows 2000运行程序还必须将stdafx.h文件中的WINVER和_WIN32_WINNT的预定义修改成0x0500才能正常使用。
CImage封装了DIB(设备无关位图)的功能,因而可以让我们能够处理每个位图像素。
它具有下列最酷特性:1、AlphaBlend支持像素级的颜色混合,从而实现透明和半透明的效果。
2、PlgBlt能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。
3、TransparentBlt在目标区域中产生透明图像,SetTransparentColor用来设置某种颜色是透明色。
4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的效果。
使用CImage的一般方法使用CImage的一般方法是这样的过程:(1) 打开应用程序的stdafx.h文件添加CImage类的包含文件:#include <atlimage.h>(2) 定义一个CImage类对象,然后调用CImage::Load方法装载一个外部图像文件。
cbitmap使用实例
CBitmap类封装了Windows图形设备接口(GDI)中的位图,提供了操纵位图的成员函数。
以下是一个使用CBitmap类的实例:
#include <afxwin.h>
CDC MemDC;
CBitmap bmp;
HBITMAP
bitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),"1.bmp",IMAGE_BITMAP,0,0,LR_LO ADFROMFILE);
bmp.DeleteObject();
if(!bmp.Attach(bitmap))
Box(0,"导入背景图失败!","提示",MB_OK);
return;
bmp.GetObject(sizeof(BITMAP),&bm);
CDC pDC;
pDC.m_hDC = GetDC(this->Handle);
MemDC.CreateCompatibleDC(&pDC);
MemDC.SelectObject(&bmp);
pDC.BitBlt(0,0,bm.bmWidth,bm.bmHeight, &MemDC, 0, 0, SRCCOPY);
MemDC.DeleteDC();
上述代码中,首先通过`LoadImage`函数将位图文件加载到内存中,然后创建了一个兼容的内存设备上下文,并将位图选入其中。
最后使用`BitBlt`函数将位图绘制到窗口客户区。
如果你想了解更多关于CBitmap类的使用方法,请参阅联机文档“Visual C++ 程序员指南”中的“图形对象”。
前两天有个朋友让我帮他编一个图象处理方面的程序,需要支持目前常见的图像格式.这可把我难住了.一直以来都只会用Visual C++的CBitmap类加载各种位图资源,然后处理.Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。
如果想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码,未免过于繁琐.这阵子在学C#,装了visual studio2003.索性在网上找了一下,竟然发现.net引入了一个功能非常强大的新类 ----- CImage.有了CImage类,Visual C++在图像方面的缺憾将一去不复返。
CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。
例如通过简单的几句,就可以实现CImage类和CBitmap类实例的:HBITMAP hBitmap=image.Detach();CBitmap bmp;bmp.Attach(hBitmap);这样一来,就又回归到以前操纵CBitmap的方式了.CImage本身封装了DIB(设备无关位图)的功能,因而能够处理每个位图像素。
它具有下列最酷特性:1、AlphaBlend支持像素级的颜色混合,从而实现透明和半透明的效果。
2、PlgBlt能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。
3、TransparentBlt在目标区域中产生透明图像,SetTransparentColor用来设置某种颜色是透明色。
4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的效果。
由于CImage在不同的Windows操作系统中其某些性能是不一样的,因此在使用时要特别注意。
IplImage的像素的访问当处理图象数据时,通常需要快速高效。
使用如cvSet*D或和它等效的函数会造成调用时的开销。
我们应该尽可能使用直接存取图象内部数据的方法。
有了IplImage内部结构的知识,我们现在可以理解最好的方法。
尽管通常OpenCV提供很多对图象的操作优化良好的例程,但是经常会有些任务是库里找不到包装好的例程的。
下面我们考虑一个例子,我们想要把三通道HSV 图象的饱合度调整为255(8位图象的最大值)而保持色调不变。
要完成这个任务最好是我们自己处理图象的每个象素。
这和我们前边对矩阵的操作相似,但在IplImage和CvMat之间也有一些主要的不同。
例3-11演示了高效的方式。
例3-11,把HSV图象的S、V分量最大化:void saturate_sv( IplImage* img ) {for( int y=0; y<img->height; y++ ) {uchar* ptr = (uchar*) (img->imageData + y *img->widthStep);for( int x=0; x<img->width; x++ ) {ptr[3*x+1] = 255;ptr[3*x+2] = 255;}}}我们只是简单的直接计算相关行y最左边的象素的指针ptr(We simply compute the pointer ptr directly as the head of the relevant row y)。
从那里为参考,我们引用第x列的饱合度数值。
因为图象是三通道的,第c通道的地址为3*x+c。
在OpenCV中,一副HSV图象和RGB图象,除了对通道的翻译有所不同,其它是没有区别的。
因此由一副HSV图象构建一副RGB图象实际所有的操作完全只在“数据”区域。
在图象头中,没有任何成员用来表明数据通道的意义。
IplImage和CvMat相比一个重要的不同是imageData的行为。
用C语言实现bmp与pix图像格式相互转换一.实验目的:pix图像是PCI软件使用格式,而bmp图像是常用格式,通过分析两者的逻辑结构和存储关系,实现格式的相互转换,方便使用各类图像。
二.实验原理:现在以100*100的两种图像为例,用C语言实现相互转换。
Bmp图像格式由头文件和颜色信息两部分组成,其中bmp的头文件固定占54个字节,颜色信息的数据大小根据画面大小而定。
用winHex打开不同的bmp图像,发现其每个像素是由3个字节构成,3个字节分别存储对应的蓝、绿、红三种颜色。
颜色信息排列是从图像的左下角开始向右,再逐层向上记录的,终止于图像的右上角。
Pix图像格式由头文件,颜色信息和尾文件组成,其中头文件固定占36352个字节,颜色信息的数据大小根据画面大小而定,尾文件固定占5824个字节。
用winHex打开不同的pix图像,可以发现颜色是按蓝、绿、红三色逐个波段,逐个像素排列的。
顺序是从左上角开始向右,再逐层向下记录的,终止于左下角。
那么实现bmp转换pix就是要将bmp的颜色信息按其排列顺序读出来,再按pix的颜色信息排列的顺序写入,同时需要已有的模板pix的头文件和尾文件照搬写入新的pix中。
同理,实现pix转换bmp就是要将pix的颜色信息按其排列顺序读出来,再按bmp的颜色信息排列的顺序写入。
不同在于bmp只需要再加入头文件,将已有的模板bmp的头文件照搬写入新的bmp中。
三.实验步骤1.准备100*100的pix图像和100*100的bmp图像及模板2. bmp转换pix编程如下:#include<>main(){FILE *fp1,*fp2,*fp3;char ch,p[100][100][3];long i,j,k;fp1=fopen("E:\\pix\\","rb");fp2=fopen("E:\\pix\\","rb");fp3=fopen("E:\\pix\\","wb");for(i=1;i<=36352;i=i++){ch=fgetc(fp2);fputc(ch,fp3);}fseek(fp1,54L,0);for(i=0;i<=99;i++){for(j=0;j<=99;j++){for(k=0;k<=2;k++){ch=fgetc(fp1);p[i][j][k]=ch;}}}for(k=0;k<=2;k++){for(i=0;i<=99;i++){for(j=0;j<=99;j++){ch=p[99-i][j][k];fputc(ch,fp3);}}}fseek(fp2,66352L,0);for(i=0;i<=5824;i++){ch=fgetc(fp2);fputc(ch,fp3);}fclose(fp1);fclose(fp2);fclose(fp3);printf("%s","ok");}3.运行程序,得到图像bmp格式pix格式转换bmp编程如下:#include<>main(){FILE *fp1,*fp2,*fp3;char ch,p[100][100][3];long i,j,k;fp1=fopen("E:\\pix\\","rb");fp2=fopen("E:\\pix\\","rb");fp3=fopen("E:\\pix\\","wb");for(i=1;i<=54;i=i++){ch=fgetc(fp2);fputc(ch,fp3);}fseek(fp1,36352L,0);for(k=0;k<=2;k++){for(i=0;i<=99;i++){for(j=0;j<=99;j++){ch=fgetc(fp1);p[99-i][j][k]=ch;}}}for(i=0;i<=99;i++){for(j=0;j<=99;j++){for(k=0;k<=2;k++){ch=p[i][j][k];fputc(ch,fp3);}}}fclose(fp1);fclose(fp2);fclose(fp3);printf("%s","ok");}5.运行程序,得到图像pix格式bmp格式。
IplImage 结构解读:typedef struct _IplImage{int nSize; /* IplImage大小*/int ID; /* 版本(=0)*/int nChannels; /* 大多数OPENCV函数支持1,2,3 或4 个通道*/int alphaChannel; /* 被OpenCV忽略*/int depth; /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S,IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F andIPL_DEPTH_64F 可支持*/char colorModel[4]; /* 被OpenCV忽略*/char channelSeq[4]; /* 同上*/int dataOrder; /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.cvCreateImage只能创建交叉存取图像*/int origin; /* 0 - 顶—左结构,1 - 底—左结构(Windows bitmaps 风格) */int align; /* 图像行排列(4 or 8). OpenCV 忽略它,使用widthStep 代替*/ int width; /* 图像宽像素数*/int height; /* 图像高像素数*/struct _IplROI *roi; /* 图像感兴趣区域. 当该值非空只对该区域进行处理*/struct _IplImage *maskROI; /* 在OpenCV中必须置NULL */void *imageId; /* 同上*/struct _IplTileInfo *tileInfo; /*同上*/int imageSize; /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/char *imageData; /* 指向排列的图像数据*/int widthStep; /* 排列的图像行大小,以字节为单位*/int BorderMode[4];/* 边际结束模式, 被OpenCV忽略*/int BorderConst[4];/* 同上*/char *imageDataOrigin;/* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的*/ }IplImage;重要结构元素说明:depth和nChannelsdepth代表颜色深度,使用的是以下定义的宏,nChannels是通道数,为1,2,3或4。
C语⾔实现的bitmap位图代码分享事实上,我们是⽤每⼀个元素表⽰⼀个32位的⼆进制字符串,这样这个元素可以保留相邻32个号码是否存在的信息,数组范围就下降到10000000/32了.例如对于号码 89256,由于89256 mod 32=2789…8,这样我们应该置a[2789]中32位字符串的第8位(从低位数起)为1.#define WORD 32#define SHIFT 5 ////移动5个位,左移则相当于乘以32,右移相当于除以32取整#define MASK 0x1F //16进制下的31#define N 10000000int bitmap[1 + N / WORD];/** 置位函数——⽤"|"操作符,i&MASK相当于mod操作* m mod n 运算,当n = 2的X次幂的时候,m mod n = m&(n-1)*/void set(int i) {bitmap[i >> SHIFT] |= (1 << (i & MASK));}/* 清除位操作,⽤&~操作符 */void clear(int i) {bitmap[i >> SHIFT] &= ~(1 << (i & MASK));}/* 测试位操作⽤&操作符 */int test(int i) {return bitmap[i >> SHIFT] & (1 << (i & MASK));}实现排序(不能重复):int main(void) {FILE *in = fopen("in.txt", "r");FILE *out = fopen("out.txt", "w");if (in == NULL || out == NULL) {exit(-1);}int i = 0;int m;for (i = 0; i < N; i++) {clear(i);}while (!feof(in)) {fscanf(in, "%d", &m);printf("%d/n", m);set(m);}printf("abnother");for (i = 0; i < N; i++) {if (test(i)) {printf("%d/n", i);fprintf(out, "%d/n", i);}}fclose(in);fclose(out);return EXIT_SUCCESS;}。
c语⾔实现bitmap的基本操作 1/**2 *⽂件:bit.h3 *⽬的: 实现bitmap数据结构4 *作者:杜⼩波5 *联系⽅式:code2living@6 **/78 #ifndef _BIT_H_9#define _BIT_H_1011/**12 *存储bitmap的结构体13 *存储的顺序从左⾄右14 **/15struct _Bits;16 typedef struct _Bits *bits;1718/**19 *获得bitmap20 *@length bitmap的长度21 *@return 所有位都初始化为0的bitmap22*/23 bits bit_new(unsigned int length);2425/**26 *销毁⼀个bitmap27 **/28void bit_destroy(bits bit);2930/**31 *获得y⼀个bitmap的长度32 *@bit 需要获得长度的bitmap33 *@return bit的长度34 **/35 unsigned int bit_length(bits bit);3637/**38 *设置bitmap中相应位置的值39 *@bit 待设置的bitmap40 *@pos 需要设置的位置41 **/42void bit_set(bits bit, unsigned int pos, unsigned char value);4344/**45 *设置bitmap中相应位置的值46 *@bit 待获取的bitmap47 *@pos 获取的位置48 **/49char bit_get(bits bit, unsigned int pos);5051#endif /*_BITS_H_*/#include "bit.h"#include <stdio.h>#include <stdlib.h>#include <string.h>struct _Bits {char *bits;unsigned int length;};bits bit_new(unsigned int length){bits new_bits = (bits)malloc(sizeof(struct _Bits));if (new_bits == NULL)return NULL;int char_nums = sizeof(char) * (length >> 3) + 1;new_bits->bits = (char *)malloc(char_nums);if (new_bits == NULL) {free(new_bits);return NULL;}memset(new_bits->bits, 0, char_nums);new_bits->length = length;return new_bits;}void bit_destroy(bits bit){free(bit->bits);free(bit);}unsigned int bit_length(bits bit){return bit->length;}void bit_set(bits bit, unsigned int pos, unsigned char value) {unsigned char mask = 0x80 >> (pos & 0x7);if (value) {bit->bits[pos>>3] |= mask;} else {bit->bits[pos>>3] &= ~mask;}}char bit_get(bits bit, unsigned int pos){unsigned char mask = 0x80 >> (pos & 0x7);return (mask & bit->bits[pos>>3]) == mask ? 1 : 0;}1 #include <stdio.h>2 #include "bit.h"3#define LEN 154int main(void)5 {6 bits bit = bit_new(LEN);78 printf("length: %u\n", bit_length(bit));910 unsigned int test_value = 0x735D;11 unsigned char value;12int i;13for (i = LEN - 1; i >= 0; i--) {14 value = test_value & 1;15 bit_set(bit, i, value);16 test_value >>= 1;17 }1819for (i = 0; i < LEN; i++) {20 printf("%d", bit_get(bit, i));21 }22 printf("\n");2324 bit_destroy(bit);2526return0;27 }欢迎⼤家对⼩弟的作品进⾏挑错。
C语⾔bitmap的使⽤技巧
bitmap是⼀种以位的状态来表⽰某种特性的状态的⼀种操作⽅式,类似嵌⼊式中的寄存器操作,在表⽰某种特性enable/disable的时候很适⽤且占⽤的内存空间也很⼩
⽐如:做过交换机或者企业⽹管,路由器的⼈可能都知道vlan这个概念,vlan域分为0-4095共4096个vlan,我们在端⼝下设置vlan的时候,就需要⼀个机制来记录vlan设置与否,
这个就是bitmap;假设⽬前设置的vlan为vlan_x,那么我们是这个操作的:
1.⾸先定义⼀个128*4的空间(⽤的32位机器)
int bitmap_vlan[128];
memset(bitmap_vlan, 0, sizeof(bitmap_vlan));
2.设置bit位
bitmap_vlan[vlan_x / 32] | (0x1 << (vlan_x %32))
如果需要检查某个vlan是否设置了,那么只需要这样做:
if ( bitmap_vlan[vlan_x / 32] & (0x1 << (vlan_x % 32)) )
相信C语⾔⽐较熟练的⼈很容易就看懂了,bitmap_vlan共有128个元素,每个元素占4个字节,就是32bit,128*32那就是4096个bit,每个bit 能表⽰⼀个vlan值。
这个以vlan的设置来抛砖引⽟,
在实际开发中,很多地⽅都可以⽤到bitmap,作为⼀个C开发,怎能不会bitmap这种操作技巧呢。
Bitmap和byte[]的相互转换///<summary>///将Bitmap转换为字节数组///</summary>///<param name="width">图像宽度</param>///<param name="height">图像长度</param>///<param name="channel">图像通道</param>///<param name="img">原图像</param>///<returns></returns>public static byte[] getByteStreamFromBitmap(int width, int height, int channel, Bitmap img){byte[] bytes = new byte[width * height * channel];BitmapData im = img.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, img.PixelFormat);int stride = im.Stride;int offset = stride - width * channel;int length = stride * height;byte[] temp = new byte[stride * height];Marshal.Copy(im.Scan0, temp, 0, temp.Length);img.UnlockBits(im);int posreal = 0;int posscan = 0;for (int c = 0; c < height; c++){for (int d = 0; d < width * channel; d++){bytes[posreal++] = temp[posscan++];}posscan += offset;}return bytes;}///<summary>///将⼀个字节数组转换为8bit灰度位图///</summary>///<param name="rawValues">显⽰字节数组</param>///<param name="width">图像宽度</param>///<param name="height">图像⾼度</param>///<returns>位图</returns>public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height){//申请⽬标位图的变量,并将其内存区域锁定Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);//获取图像参数int stride = bmpData.Stride; // 扫描线的宽度int offset = stride - width; // 显⽰宽度与扫描线宽度的间隙IntPtr iptr = bmpData.Scan0; // 获取bmpData的内存起始位置int scanBytes = stride * height;// ⽤stride宽度,表⽰这是内存区域的⼤⼩//下⾯把原始的显⽰⼤⼩字节数组转换为内存中实际存放的字节数组int posScan = 0, posReal = 0;// 分别设置两个位置指针,指向源数组和⽬标数组byte[] pixelValues = new byte[scanBytes]; //为⽬标数组分配内存for (int x = 0; x < height; x++){//下⾯的循环节是模拟⾏扫描for (int y = 0; y < width; y++){pixelValues[posScan++] = rawValues[posReal++];}posScan += offset; //⾏扫描结束,要将⽬标位置指针移过那段“间隙”}//⽤Marshal的Copy⽅法,将刚才得到的内存字节数组复制到BitmapData中System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);bmp.UnlockBits(bmpData); // 解锁内存区域//下⾯的代码是为了修改⽣成位图的索引表,从伪彩修改为灰度ColorPalette tempPalette;using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)){tempPalette = tempBmp.Palette;}for (int i = 0; i < 256; i++){tempPalette.Entries[i] = Color.FromArgb(i, i, i);}bmp.Palette = tempPalette;//算法到此结束,返回结果return bmp;}。
(转)C#进⾏图像处理的⼏种⽅法(Bitmap,BitmapData,IntPtr)转⾃C#进⾏图像处理的⼏种⽅法本⽂讨论了C#图像处理中Bitmap类、BitmapData类和unsafe代码的使⽤以及字节对齐问题。
Bitmap类命名空间:System.Drawing封装 GDI+ 位图,此位图由图形图像及其属性的像素数据组成。
Bitmap 是⽤于处理由像素数据定义的图像的对象。
利⽤C#类进⾏图像处理,最⽅便的是使⽤Bitmap类,使⽤该类的GetPixel()与SetPixel()来访问图像的每个像素点。
下⾯是MSDN中的⽰例代码:public void GetPixel_Example(PaintEventArgs e){// Create a Bitmap object from an image file.Bitmap myBitmap = new Bitmap("Grapes.jpg");// Get the color of a pixel within myBitmap.Color pixelColor = myBitmap.GetPixel(50, 50);// Fill a rectangle with pixelColor.SolidBrush pixelBrush = new SolidBrush(pixelColor);e.Graphics.FillRectangle(pixelBrush, 0, 0, 100, 100);}可见,Bitmap类使⽤⼀种优雅的⽅式来操作图像,但是带来的性能的降低却是不可忽略的。
⽐如对⼀个800*600的彩⾊图像灰度化,其耗费的时间都要以秒为单位来计算。
在实际项⽬中进⾏图像处理,这种速度是决对不可忍受的。
BitmapData类命名空间:System.Drawing.Imaging指定位图图像的属性。
BitmapData 类由 Bitmap 类的 LockBits 和 UnlockBits ⽅法使⽤。
C#⽂字转Bitmap,Bitmap转为字节流或Bitmap转为图⽚1.⽂字转为Bitmap:/// <summary>/// 把⽂字转换才Bitmap/// </summary>/// <param name="text"></param>/// <param name="font"></param>/// <param name="rect">⽤于输出的矩形,⽂字在这个矩形内显⽰,为空时⾃动计算</param>/// <param name="fontcolor">字体颜⾊</param>/// <param name="backColor">背景颜⾊</param>/// <returns></returns>private static Bitmap TextToBitmap(string text, Font font, Rectangle rect, Color fontcolor, Color backColor){Graphics g;Bitmap bmp;StringFormat format = new StringFormat(StringFormatFlags.NoClip);if (rect == Rectangle.Empty){bmp = new Bitmap(1, 1);g = Graphics.FromImage(bmp);//计算绘制⽂字所需的区域⼤⼩(根据宽度计算长度),重新创建矩形区域绘图SizeF sizef = g.MeasureString(text, font, PointF.Empty, format);int width = (int)(sizef.Width + 1);int height = (int)(sizef.Height + 1);rect = new Rectangle(0, 0, width, height);bmp.Dispose();bmp = new Bitmap(width, height);}else{bmp = new Bitmap(rect.Width, rect.Height);}g = Graphics.FromImage(bmp);//使⽤ClearType字体功能g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;g.FillRectangle(new SolidBrush(backColor),rect);g.DrawString(text, font, new SolidBrush(fontcolor), rect, format);return bmp;}2.Bitmap转为字节流:/// <summary>/// bitmap转换为字节流/// </summary>/// <param name="bitmap"></param>/// <returns></returns>public static byte[] BitmapByte(Bitmap bitmap){using (MemoryStream stream = new MemoryStream()){bitmap.Save(stream, ImageFormat.Png);byte[] data = new byte[stream.Length];stream.Seek(0, SeekOrigin.Begin);stream.Read(data, 0, Convert.ToInt32(stream.Length));return data;}}3.Bitmap转为图⽚:Bitmap bmp = TextToBitmap(text, font, Rectangle.Empty, fontcolor, backColor); bmp.Save(@"D:\test.bmp", ImageFormat.Png);。
CBitmap和IplImage之间的转换
MFC编程经常在处理图片时需要对图片格式进行转换,本人最近在写一个程序,正好要运
用到这个知识点,就在网上查了资料,弄明白了。下面我对转换方法进行一下总结。
CBitmap转为IplImage
CBitmap Bmp;//载入位图
Bmp.LoadBitmap(IDB_BITMAP);
HBITMAP hBmp = HBITMAP(memBmp);//将CBitmap转换为HBITMAP
BITMAP bmp;
Bmp.GetBitmap(&bmp);//获得位图信息
int depth,nChannels;
if(bmp.bmBitsPixel == 1)//得到图像深度和通道数
{
depth=IPL_DEPTH_1U;
nChannels=1;
}
else
{
depth=IPL_DEPTH_8U;
nChannels=bmp.bmBitsPixel/8;
}
IplImage* pImg = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight), depth, nChannels); //创
建图像
BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels]; //创建缓冲区
GetBitmapBits(hBmp, bmp.bmHeight*bmp.bmWidth*nChannels, pBuffer); //将位图信息复制到
缓冲区
memcpy(pImg->imageData, pBuffer, bmp.bmHeight*bmp.bmWidth*nChannels);//将缓冲区信息
复制给IplImage
于是成功从CBitmap得到了
IplImage类型的图片pImg.
总结步骤如下:
1, 通过
GetBitmap得到从Cbitmap到BITMAP类型的转换。
2, 得到BITMAP图像的信息并以此信息创建IplImage图像。
3, 将BITMAP图像信息复制到缓冲区内。
4, 从缓冲区内得到信息赋值给IplImage图像。
IplImage转为CBitmap
IplImage *pImg = cvLoadImage(filename, 1);
CBitmap *bmp;
HBITMAP
hBitmap;
BITMAPINFOHEADER bf; //位图信息头
memset(&bf, 0, sizeof(BITMAPINFOHEADER));//置零
bf.biSize = sizeof(BITMAPINFOHEADER);//将IplImage信息赋值给信息头
bf.biWidth = pImg->width;
bf.biHeight = pImg->height;
bf.biPlanes = 1;
bf.biBitCount = pImg->depth*pImg->nChannels;
bf.biSizeImage = pImg->imageSize;
BYTE* pData=new BYTE[bf.biSizeImage];
memcpy(pData, pImg->imageDataOrigin, pImg->imageSize);
hBitmap=CreateDIBitmap(dc,bf,CBM_INIT,pImg->imageData,bf,DIB_RGB_COLORS);
bitmap->Attach(hBitmap);//关联