边城浪子(QQ:16168666)
IPicture接口是Window95及以上操作系统支持的一个COM接口,它用来操作各种在WINDOWS常见的图像格式。如,BMP、JPEG、GIF等许多文件格式都能识别。使用很方便。但是可能很多朋友对这个接口并不很熟悉,或者不太了解对COM接口的操作。就我个人认为,对COM接口的直接操作的确也是一件比较烦的工作。所以自然就想到了将这些操作封装起来以备后用。(我了解自己是比较懒的,所以经常做这些事)经过使用,感觉很方便,呵呵,所以介绍给大家共享一下吧(热烈鼓掌)。
将大的图片压缩成JPG或GIF文件将大大减少你的软件的体积。使用这个类来操作它们和使用标准的BMP格式图像一样的方便和快速。
如果你对本文有什第疑问或建议或什么更好的想法,欢迎和我讨论。
一个类,最重要的当然就是怎样使用了,所以首先就介绍这个类如何使用的问题,类的源代码就附在最后吧。
********************************************************************************
CPicture 类的使用参考
类名称:CPicture
用途:封装了通过IPicture接口对各种常见格式的图像(如BMP、JPEG、GIF等)文件及资源的操作,在MFC的支持下工作,当然,如果你有兴趣,完全可以改成不需要MFC的支持就能工作。由于本人通常工作在MFC下,所以方便起见写成MFC的啦。
基类:无。
注:以下对图像的坐标、尺寸的单位指的都是象素,图像的坐标原点位于图像左上角向下是+Y方向,向右是+X方向。
成员函数描述:
CPicture::CPicture();
说明:构造函数。构造一个空的CPicture对象。
BOOL CPicture::LoadPicture(UINT nResource, LPCTSTR lpszResType);
BOOL CPicture::LoadPicture(LPCTSTR lpszResource,LPCTSTR lpszResType);
说明:该函数从资源是加载一个图像,如果该对象已经包含一个图像,则原图像先被自动释放,而不论本次加载是否成功。
返回值:如果加载成功则返回TRUE,否则返回FALSE。
参数:
nResource指定一个资源的ID号,该ID指定一个资源,函数将根据该资源来生成图像,资源的格式不用担心,对象会自动识别的(如果不认识该资源的格式自然加载就会失败)。
lpszResType指定该资源的类型,国为该函数可以识别多种非标准的图像资源所以你应该指明你加载的该资源的类型
lpszResource指定一个资源的标识符,该标识指定一个资源,函数将根据该资源来生成图像,资源的格式不用担心,对象会自动识别的(如果不认识该资源的格式自然加载就会失败)。
BOOL CPicture::LoadPictureFromFile(LPCTSTR lpszFileName);
说明:该函数从文件中加载一个图像。
返回值:如果加载成功则返回TRUE,否则返回FALSE。
参数:
lpszFileName一个指向文件名字符串的指针。
BOOL CPicture::IsValid();
说明:判断对象是否有效。
返回值:如果对象中有一个有效的图像则返回TRUE,否则返回FALSE。
参数:无
CSize CPicture::GetSize();
说明:取得图象的尺寸
返回值:一个CSize对象,包含了图像的尺寸,对一个无效的CPicture对象使用该函数将返回(0,0)。
void CPicture::Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc);
void CPicture::Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest ,
int xSrc ,int ySrc ,int cxSrc ,int cySrc);
说明:在一个DC表面绘制对象内包含的图像,如果对象没有包含任何图象,则什么也不做。
返回值:无返回值。
参数:
pDC一个指向DC对象的指针,图像将绘制在该设备表面。
lprcDest指定一个目标矩形。源矩形内的部分图像被拉伸并绘制到设备表面的该象区域内
lprcSrc指定一个源矩形区域。图像中位于源矩形内的部分被拉伸并绘制到设备表面目标矩形区域
xDest指定目标矩形左上角的水平方向(X)坐标,见参数lprcDest的说明。
yDest指定目标矩形左上角的垂直方向(Y)坐标,见参数lprcDest的说明。
cxDest指定目标矩形的水平方向尺寸(宽度),见参数lprcDest的说明。
cyDest指定目标矩形的垂直方向尺寸(高度),见参数lprcDest的说明。
xSrc指定源矩形左上角的水平方向(X)坐标,见参数lprcSrc的说明。
ySrc指定源矩形左上角的垂直方向(Y)坐标,见参数lprcSrc的说明。
cxSrc指定源矩形的水平方向尺寸(宽度),见参数lprcSrc的说明。
cySrc指定源矩形的垂直方向尺寸(高度),见参数lprcSrc的说明。
void CPicture::Release();
说明:将对象所包含的图像从内存中移除。注意对象本身并不会从内存中移除。你仍然可以用它来重新加载一个新的图像。你无须时刻记着为不再使用的图像调用Release,当类析构时,该函数自然被调用。当然我并不反对你显式地调用该函数来释放图像以便空出一点内存资源。
返回值:无。
参数:无。
******************************************************************************
例子:一个使用该类来实现的简单的图片浏览程序(MFC程序)我们需要添加和修改的地方加起来不超过5行,但是功能相对(5行代码)来说已经是"太强大"了,它可以浏览包括BMP,JPEG,GIF,ICON,TIF等格式在内的好多种图像了。
1) 生成一个多文档的MFC应用程序,选择视图的基类为CScrollView. 其它使用默认值
2) 将CPicture类有头文件及源文件加入至工程中.
3) 在文档类的头文件前包含Picture.h头文件
4) 为文档类增加一个公有变量pic,类型CPicture.
5) 重载文档类的OnOpenDocument虚函数如下:
BOOL CBrowserDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
return pic.LoadPictureFromFile(lpszPathName);
}
6) 在视图类的OnInitUpdaye函数中修改SetScrollSizes的调用处代码:
void CBrewserView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
SetScrollSizes(MM_TEXT, GetDocument()->pic.GetSize());
}
7) 在视图类的OnDraw中增加绘图代码:
void CBrewserView::OnDraw(CDC* pDC)
{
CBrewserDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CSize sz = pDoc->pic.GetSize();
pDoc->pic.Draw(pDC, 0,0,sz.cx,sz.cy,0,0,sz.cx,sz.cy);
}
8) 好了,一个简单的图像浏览器就写好了.编译一下你的程序,然后试着打开一些图像文件.怎么样,呵呵,当然它不支持GIF动画.GIF动画文件只能显示一帧.但是对这么小的一个类来说. 已经难能可贵了.是吧.
********************************************************************************
附:CPicture类的代码:
//////////////////////////////////////////////////////////////////////
// Picture.h: interface for the CPicture class.
// Lounge Stdio 2003
// 作者:边城浪子(QQ:16168666)
// E-mail: krh2001.lpfdiyvbb@163.com
//////////////////////////////////////////////////////////////////////
#ifndef PICTURE_H
#ifndef picture_h
#define PICTURE_H
#define picture_h
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CPicture
{
public:
CPicture();
virtual ~CPicture();
public:
BOOL LoadPicture(UINT nResource, LPCTSTR lpszResType)
{return LoadPicture(MAKEINTRESOURCE(nResource), lpszResType);}
BOOL LoadPictureFromFile(LPCTSTR lpszFileName);
BOOL LoadPicture(LPCTSTR lpszResource,LPCTSTR lpszResType);
BOOL IsValid(){ return m_pPic!=NULL;}
CSize GetSize(){return m_size;}
void Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc);
void Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest ,
int xSrc ,int ySrc ,int cxSrc ,int cySrc);
void Release();
protected:
IPicture* m_pPic;
OLE_XSIZE_HIMETRIC _w_him;
OLE_YSIZE_HIMETRIC _h_him;
CSize m_size;
protected:
void CalcSize();
};
#endif // define picture_h
#endif // define PICTURE_H
//////////////////////////////////////////////////////////////////////
// Picture.cpp: implementation of the CPicture class.
// Lounge Stdio 2003
// 作者:边城浪子(QQ:16168666)
// E-mail: krh2001.lpfdiyvbb@163.com
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Picture.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPicture::CPicture()
:m_pPic(NULL), _h_him(0), _w_him(0), m_size(0,0)
{
}
CPicture::~CPicture()
{
Release();
}
void CPicture::Release()
{
if(m_pPic != NULL)
{
m_pPic->Release();
m_pPic = NULL;
_h_him = _w_him = 0;
m_size.cx = m_size.cy = 0;
}
}
BOOL CPicture::LoadPicture(LPCTSTR lpszResource, LPCTSTR lpszResType)
{
Release();
HINSTANCE hInst = AfxFindResourceHandle(lpszResource, lpszResType);
HRSRC hRsrc = ::FindResource(hInst, lpszResource, lpszResType);
if(hRsrc == NULL) return FALSE;
HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
if(hGlobal == NULL) return FALSE;
DWORD dwSize = SizeofResource(hInst, hRsrc);
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(hMem == NULL) return FALSE;
LPVOID pSrc = ::LockResource(hGlobal);
if(pSrc == NULL) {
::GlobalFree(hMem);
return FALSE;
}
LPVOID pDes = ::GlobalLock(hMem);
if(pDes == NULL){
//::GlobalUnlock(hGlobal);
::GlobalFree(hMem);
return FALSE;
}
memcpy(pDes, pSrc, dwSize);
//GlobalUnlock(hGlobal);
GlobalUnlock(hMem);
::FreeResource(hGlobal);
IStream* pStm = NULL;
CreateStreamOnHGlobal(hMem, TRUE, &pStm);
if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic)))
{
pStm -> Release();
::GlobalFree(hMem);
pStm = NULL;
return FALSE;
}
pStm->Release();
::GlobalFree(hMem);
CalcSize();
return TRUE;
}
BOOL CPicture::LoadPictureFromFile(LPCTSTR lpszFileName)
{
Release();
CFile file;
if(!file.Open(lpszFileName, CFile::modeRead))
return FALSE;
DWORD dwSize = file.GetLength();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if(hMem == NULL) return FALSE;
LPVOID pDes = ::GlobalLock(hMem);
if(pDes == NULL){
::GlobalFree(hMem);
return FALSE;
}
file.ReadHuge(pDes, dwSize);
file.Close();
GlobalUnlock(hMem);
IStream* pStm = NULL;
CreateStreamOnHGlobal(hMem, TRUE, &pStm);
if(!SUCCEEDED(OleLoadPicture(pStm,dwSize,TRUE,IID_IPicture,(LPVOID*)&m_pPic)))
{
pStm -> Release();
::GlobalFree(hMem);
pStm = NULL;
return FALSE;
}
pStm->Release();
::GlobalFree(hMem);
CalcSize();
return TRUE;
}
void CPicture::CalcSize()
{
if(m_pPic == NULL) return;
m_pPic->get_Width(&_w_him);
m_pPic->get_Height(&_h_him);
CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
m_size.cx = _w_him;
m_size.cy = _h_him;
pDC->HIMETRICtoDP(&m_size);
CWnd::GetDesktopWindow()->ReleaseDC(pDC);
}
void CPicture::Draw(CDC* pDC, LPCRECT lprcDest, LPCRECT lprcSrc)
{
if(m_pPic)
{
CSize szOrig(lprcSrc->left, lprcSrc->top);
CSize szSrc(lprcSrc->right - lprcSrc->left, lprcSrc->bottom - lprcSrc->top);
pDC->DPtoHIMETRIC(&szOrig);
pDC->DPtoHIMETRIC(&szSrc);
m_pPic->Render(*pDC, lprcDest->left,lprcDest->top,lprcDest->right-lprcDest->left,
lprcDest->bottom-lprcDest->top, szOrig.cx, _h_him-szOrig.cy, szSrc.cx,
-szSrc.cy, NULL);
}
}
void CPicture::Draw(CDC* pDC, int xDest,int yDest, int cxDest, int cyDest ,
int xSrc ,int ySrc ,int cxSrc ,int cySrc)
{
Draw(pDC, CRect(xDest, yDest, xDest+cxDest, yDest+cyDest), CRect(xSrc, ySrc, xSrc+cxSrc, ySrc+cySrc));
}