1.类型:HBITMAP、CBitmap、CImage、Mat(Open cv)、HObject(Halcon)
2.注意图像单通道与三通道的问题
3.实现类
// Bmp.h : 获取bmp图片头文件
//
#pragma once
#include<vector>
#include"highgui.h"
#include "HalconCpp.h"
using namespace std;
using namespace cv;
using namespace HalconCpp;
class CBmp
{
//单例模式
private:
CBmp(CString* dir, int length);//构造函数
CBmp(const CBmp &);
CBmp& operator = (const CBmp &);
public:
static CBmp *Instantialize(CString* dir, int length);
static CBmp *pInstance;
//-----------------------------------------------------------------------
public:
~CBmp(void);
//成员变量
CBitmap m_bitmap; //创建位图对象
CImage m_image; //创建CImage
Mat m_mat; //创建opencv Mat
HObject m_object; //创建Halcon HObject
//成员函数
void GetPic(int type); //获取图片
void ShowPic(CWnd *pWnd); //用来显示指定图片的函数
void TraverseDir(CString& dir, vector<CString>& vec); //获取文件夹所有路径
bool HBitmapToMat(HBITMAP& _hBmp,Mat& _mat); //HBitmapToMat转换
void MatToCImage(Mat& mat, CImage& cimage); //MatToCImage转换
void CImageToMat(CImage& cimage, Mat& mat); //CImageToMat转换
void dev_open_window_fit_image (HObject ho_Image, HTuple hv_Row, HTuple hv_Column,
HTuple hv_WidthLimit, HTuple hv_HeightLimit, HTuple *hv_WindowHandle);//独立窗口显示HObject图片
CWnd *m_pWnd; ///< 显示图像窗口(控件)指针
HDC m_hDC; ///< 绘制图像DC句柄
vector<CString> *paths; //存储文件夹所有图片路径
int *index; //图片路径标识
};
// Bmp.cpp : 获取bmp图片实现类
//
#include "stdAfx.h"
#include "Bmp.h"
#include "MyNewDlg.h "
//指针赋0,就是不指向任何对象,相当于NULL
CBmp* CBmp::pInstance = 0;
CBmp* CBmp::Instantialize(CString* dir, int length)
{
if(pInstance == NULL)
{
pInstance = new CBmp(dir, length);
}
return pInstance;
}
CBmp::CBmp(CString* dir, int length)
: index(new int[length]),
paths(new vector<CString>[length])
{
for(int i=0;i<length; i++)
{
//获取文件夹下所有文件路径paths
TraverseDir(dir[i], paths[i]);
index[i] = 0;
}
}
CBmp::~CBmp(void)
{
CBmp::pInstance = 0;
}
void CBmp::GetPic(int type)
{
//最后一张图片提示
if(index[type] == paths[type].size())
{
index[type] = 0;
//MessageBox会暂时终止程序执行
//MessageBox(NULL,_T("最后一张图片,重新开始"),_T("提示"),MB_OK);
//自定义对话框不会暂时终止程序执行
CMyNewDlg *pDlg=new CMyNewDlg ;
pDlg->Create(IDD_DIALOG_WA);
pDlg->ShowWindow(SW_SHOW);
}
//定义bitmap指针 调用函数LoadImage装载位图
HBITMAP m_hBitmap;
m_hBitmap = (HBITMAP) LoadImage(NULL,paths[type][index[type]],IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
/*************************************************************************/
/* 1.要装载OEM图像,则设此参数值为0 OBM_ OEM位图 OIC_OEM图标 OCR_OEM光标
/* 2.BmpName要装载图片的文件名
/* 3.装载图像类型:
/* IMAGE_BITMAP-装载位图 IMAGE_CURSOR-装载光标 IMAGE_ICON-装载图标
/* 4.指定图标或光标的像素宽度和长度 以像素为单位
/* 5.加载选项:
/* IR_LOADFROMFILE-指明由lpszName指定文件中加载图像
/* IR_DEFAULTSIZE-指明使用图像默认大小
/* LR_CREATEDIBSECTION-当uType参数为IMAGE_BITMAP时,创建一个DIB项
/**************************************************************************/
//CBitmap
if( m_bitmap.m_hObject )
{
m_bitmap.Detach(); //切断CWnd和窗口联系
}
m_bitmap.Attach(m_hBitmap); //将句柄HBITMAP m_hBitmap与CBitmap m_bitmap关联
//CImage
if(!m_image.IsNull()) //Attach与Load前,必须确认img中无位图,否则会弹出异常,但忽略也可继续运行
m_image.Destroy();
//m_image.Attach(m_hBitmap);
m_image.Load(paths[type][index[type]]);
//Mat
//HBitmapToMat(m_hBitmap, m_mat);
USES_CONVERSION;
//m_mat = imread(W2A(paths[type][index[type]]));
CImageToMat(m_image, m_mat);
//HObject(Unicode下 CString->char*)
//1
_bstr_t bstrVar(paths[type][index[type]]);
char *ch = bstrVar;
//2
CString str1 = paths[type][index[type]];
//int len =WideCharToMultiByte(CP_ACP,0,str1,-1,NULL,0,NULL,NULL);
//char *ptxtTemp =new char[len +1];
//WideCharToMultiByte(CP_ACP,0,str1,-1,ptxtTemp,len,NULL,NULL );
//ReadImage(&m_object, ptxtTemp);
//3
char *ptxtTemp = W2A(str1);
TRACE(ptxtTemp);
ReadImage(&m_object, ptxtTemp);
index[type]++;
}
void CBmp::ShowPic(CWnd *pWnd)
{
//获取图像显示窗口的指针和绘图DC句柄
m_pWnd = pWnd;
m_hDC = ::GetDC(m_pWnd->m_hWnd);
MatToCImage(m_mat, m_image);
//pWnd->ModifyStyle(0, SS_BITMAP); //修改它的属性为位图
//((CStatic*)m_pWnd)->SetBitmap(m_bitmap); //显示CBitmap图片
((CStatic*)m_pWnd)->SetBitmap(m_image); //显示CImage图片
//该方式显示静态图片,并不能刷新
//HTuple width, height;
//GetImageSize(m_object, &height, &width);
//HWND hImgWnd = m_pWnd->m_hWnd;
//CRect rtWindow;
//m_pWnd->GetClientRect(&rtWindow);
//HTuple m_htWindow;
//OpenWindow(rtWindow.left, rtWindow.top, rtWindow.Width(), rtWindow.Height(), (Hlong)hImgWnd, "visible", "", &m_htWindow);
//SetPart(m_htWindow, 0, 0, width, height);
//DispObj(m_object, m_htWindow);
//pWnd->Invalidate();
HTuple hv_WindowHandle;
dev_open_window_fit_image(m_object, 0, 0, -1, -1, &hv_WindowHandle);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(m_object, HDevWindowStack::GetActive());
// 释放DC
::ReleaseDC(m_pWnd->m_hWnd, m_hDC);
}
void CBmp::TraverseDir(CString& dir, vector<CString>& vec)
{
CFileFind ff;
if (dir.Right(1) != "/")
dir += "/";
dir += "*.*";
BOOL ret = ff.FindFile(dir);
while (ret)
{
ret = ff.FindNextFile();
if (ff.IsDirectory() && !ff.IsDots())
{
CString path = ff.GetFilePath();
TraverseDir(path, vec);
}
else if (!ff.IsDirectory() && !ff.IsDots())
{
CString name = ff.GetFileName();
CString path = ff.GetFilePath();
vec.push_back(path);
}
}
ff.Close();
}
bool CBmp::HBitmapToMat(HBITMAP& _hBmp, Mat& _mat)
{
BITMAP bmp;
GetObject(_hBmp,sizeof(BITMAP),&bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
Mat v_mat;
v_mat.create(cvSize(bmp.bmWidth,bmp.bmHeight), CV_MAKETYPE(CV_8U,nChannels));
GetBitmapBits(_hBmp,bmp.bmHeight*bmp.bmWidth*nChannels,v_mat.data);
_mat=v_mat;
return TRUE;
}
void CBmp::MatToCImage(Mat& mat, CImage& cimage)
{
if (0 == mat.total())
{
return;
}
int nChannels = mat.channels();
if ((1 != nChannels) && (3 != nChannels))
{
return;
}
int nWidth = mat.cols;
int nHeight = mat.rows;
//重建cimage
cimage.Destroy();
cimage.Create(nWidth, nHeight, 8 * nChannels);
//拷贝数据
uchar* pucRow; //指向数据区的行指针
uchar* pucImage = (uchar*)cimage.GetBits(); //指向数据区的指针
int nStep = cimage.GetPitch(); //每行的字节数,注意这个返回值有正有负
if (1 == nChannels) //对于单通道的图像需要初始化调色板
{
RGBQUAD* rgbquadColorTable;
int nMaxColors = 256;
rgbquadColorTable = new RGBQUAD[nMaxColors];
cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);
for (int nColor = 0; nColor < nMaxColors; nColor++)
{
rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;
rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;
rgbquadColorTable[nColor].rgbRed = (uchar)nColor;
}
cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);
delete []rgbquadColorTable;
}
for (int nRow = 0; nRow < nHeight; nRow++)
{
pucRow = (mat.ptr<uchar>(nRow));
for (int nCol = 0; nCol < nWidth; nCol++)
{
if (1 == nChannels)
{
*(pucImage + nRow * nStep + nCol) = pucRow[nCol];
}
else if (3 == nChannels)
{
for (int nCha = 0 ; nCha < 3; nCha++)
{
*(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];
}
}
}
}
}
void CBmp::CImageToMat(CImage& cimage, Mat& mat)
{
if (true == cimage.IsNull())
{
return;
}
int nChannels = cimage.GetBPP() / 8;
if ((1 != nChannels) && (3 != nChannels))
{
return;
}
int nWidth = cimage.GetWidth();
int nHeight = cimage.GetHeight();
//重建mat
if (1 == nChannels)
{
mat.create(nHeight, nWidth, CV_8UC3);
}
else if(3 == nChannels)
{
mat.create(nHeight, nWidth, CV_8UC3);
}
//拷贝数据
uchar* pucRow; //指向数据区的行指针
uchar* pucImage = (uchar*)cimage.GetBits(); //指向数据区的指针
int nStep = cimage.GetPitch(); //每行的字节数,注意这个返回值有正有负
for (int nRow = 0; nRow < nHeight; nRow++)
{
pucRow = (mat.ptr<uchar>(nRow));
for (int nCol = 0; nCol < nWidth; nCol++)
{
if (1 == nChannels)
{
for (int nCha = 0 ; nCha < 3; nCha++)
{
pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol);
}
}
else if (3 == nChannels)
{
for (int nCha = 0 ; nCha < 3; nCha++)
{
pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol * 3 + nCha);
}
}
}
}
}
void CBmp::dev_open_window_fit_image (HObject ho_Image, HTuple hv_Row, HTuple hv_Column,
HTuple hv_WidthLimit, HTuple hv_HeightLimit, HTuple *hv_WindowHandle)
{
// Local control variables
HTuple hv_MinWidth, hv_MaxWidth, hv_MinHeight;
HTuple hv_MaxHeight, hv_ResizeFactor, hv_ImageWidth, hv_ImageHeight;
HTuple hv_TempWidth, hv_TempHeight, hv_WindowWidth, hv_WindowHeight;
//This procedure opens a new graphics window and adjusts the size
//such that it fits into the limits specified by WidthLimit
//and HeightLimit, but also maintains the correct image aspect ratio.
//
//If it is impossible to match the minimum and maximum extent requirements
//at the same time (f.e. if the image is very long but narrow),
//the maximum value gets a higher priority,
//
//Parse input tuple WidthLimit
if (0 != (HTuple((hv_WidthLimit.TupleLength())==0).TupleOr(hv_WidthLimit<0)))
{
hv_MinWidth = 500;
hv_MaxWidth = 800;
}
else if (0 != ((hv_WidthLimit.TupleLength())==1))
{
hv_MinWidth = 0;
hv_MaxWidth = hv_WidthLimit;
}
else
{
hv_MinWidth = ((const HTuple&)hv_WidthLimit)[0];
hv_MaxWidth = ((const HTuple&)hv_WidthLimit)[1];
}
//Parse input tuple HeightLimit
if (0 != (HTuple((hv_HeightLimit.TupleLength())==0).TupleOr(hv_HeightLimit<0)))
{
hv_MinHeight = 400;
hv_MaxHeight = 600;
}
else if (0 != ((hv_HeightLimit.TupleLength())==1))
{
hv_MinHeight = 0;
hv_MaxHeight = hv_HeightLimit;
}
else
{
hv_MinHeight = ((const HTuple&)hv_HeightLimit)[0];
hv_MaxHeight = ((const HTuple&)hv_HeightLimit)[1];
}
//
//Test, if window size has to be changed.
hv_ResizeFactor = 1;
GetImageSize(ho_Image, &hv_ImageWidth, &hv_ImageHeight);
//First, expand window to the minimum extents (if necessary).
if (0 != (HTuple(hv_MinWidth>hv_ImageWidth).TupleOr(hv_MinHeight>hv_ImageHeight)))
{
hv_ResizeFactor = (((hv_MinWidth.TupleReal())/hv_ImageWidth).TupleConcat((hv_MinHeight.TupleReal())/hv_ImageHeight)).TupleMax();
}
hv_TempWidth = hv_ImageWidth*hv_ResizeFactor;
hv_TempHeight = hv_ImageHeight*hv_ResizeFactor;
//Then, shrink window to maximum extents (if necessary).
if (0 != (HTuple(hv_MaxWidth<hv_TempWidth).TupleOr(hv_MaxHeight<hv_TempHeight)))
{
hv_ResizeFactor = hv_ResizeFactor*((((hv_MaxWidth.TupleReal())/hv_TempWidth).TupleConcat((hv_MaxHeight.TupleReal())/hv_TempHeight)).TupleMin());
}
hv_WindowWidth = hv_ImageWidth*hv_ResizeFactor;
hv_WindowHeight = hv_ImageHeight*hv_ResizeFactor;
//Resize window
SetWindowAttr("background_color","black");
OpenWindow(hv_Row,hv_Column,hv_WindowWidth,hv_WindowHeight,0,"","",&(*hv_WindowHandle));
HDevWindowStack::Push((*hv_WindowHandle));
if (HDevWindowStack::IsOpen())
SetPart(HDevWindowStack::GetActive(),0, 0, hv_ImageHeight-1, hv_ImageWidth-1);
return;
}
4.使用方法
CString* paths = new CString[1];
paths[0] = "C:/Users/lin/Desktop/picture/";
//获取bmp对象
bmp = CBmp::Instantialize(paths, 1);
//获取图片传入路径下标码
bmp->GetPic(0);
//获取图片数据CBitmap
bmp->m_bitmap;
//获取图片数据CImage
bmp->m_image;
//获取图片数据HObject
bmp->m_object;
//获取图片数据Mat
bmp->m_mat;
//显示图片
bmp->ShowPic(GetDlgItem(IDC_STATIC_SHOW_WND));