//========================================================================
//TITLE:
// CImageMaster轻松显示图片
//AUTHOR:
// norains
//DATE:
// Sunday 26-September-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
虽然IImaging组件可以很简单地显示图片,但如果是更好地显示图片,却又不简单.那有没有什么方法能很简单又能更好地显示图片呢?答案是:有!那就是使用CImageMaster类!
...
... ...
... ... ...
Oh,Forgive me! 原谅我这个自卖自夸的人吧! 原谅我这个无聊的人偶尔发发的牢骚吧!世界多美好!
这篇豆腐块主要是介绍CImageMaster的使用,而代码的主要思想可以参考我另外一篇文章:详聊IImage的图片显示 http://blog.csdn.net/norains/archive/2007/08/26/1759912.aspx
好吧,老样子,让我们看看该类的函数吧:
1.Open(const TCHAR *pcszFile)
打开一个图片文件.如果打开成功,需要调用Close()函数进行资源的释放.
2.Close()
调用Open()成功后需调用该函数进行资源的释放.
3.IsOK()
判断是否已经准备好绘制图档.
4.GetHeight()
获取图片的高度.
5.GetWidth()
获取图片的宽度.
6.DrawIntegrity(HDC hdc, ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect,BOOL bDraw)
绘制原始图档.如果图片过大,可能会绘制失败.
hdc:目标DC
mode:绘制的模式.
IMG_FIT - 按比例拉伸至整个pDstRect区域.
IMG_STRETCH - 填充整个pDstRect区域,而不管其比例.
IMG_NATIVE - 如果pSrcRect区域小于pDstRect,则按pSrcRect的大小在pDstRect居中显示;如果pSrcRect区域大于pDstRect,则效果和IMG_FIT相同.
pDstRect: 目标DC所绘制的区域.
pSrcRect: 源DC所需要绘制的区域.
bDraw: 为TRUE时立刻绘制到hdc;为FALSE不绘制到hdc上.因为在DrawIntegrity()函数中需要从文件中获取文件信息并创建图片DC来保存图片信息,所以第一调用的时候会比较慢,但以后由于是将图片DC直接绘制到hdc中,所以速度会大大加快.
7.DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
绘制缩略图.如果DrawIntegrity()函数失败,调用该函数绘制缩略图可能会成功.
参数的意义和DrawIntegrity()相同.
代码的具体作用和思想请参见:http://blog.csdn.net/norains/archive/2007/08/26/1759912.aspx
CImageMaster的代码如下:
//////////////////////////////////////////////////////////////////////
// ImageMaster.h: interface for the CImageMaster class.
//
//Version:
// 1.1.1
//
//Date:
// 2007.08.13
//////////////////////////////////////////////////////////////////////
#ifndef IMAGEMASTER_H
#define IMAGEMASTER_H
//Enum value
enum ImageDrawMode
{
//Fit to the play window size. How wide (height) the window is, how
//is the move. Keep aspect ratio.
IMG_FIT,
IMG_STRETCH,
//as the video size. If it's bigger , it just like the DISP_FIT mode.
IMG_NATIVE
}; class CImageMaster
{
public:
BOOL DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw);
BOOL DrawIntegrity(HDC hdc, ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect,BOOL bDraw);
BOOL IsOK();
void Close();
UINT GetHeight();
UINT GetWidth();
BOOL Open(const TCHAR *pcszFile);
CImageMaster();
virtual ~CImageMaster(); protected:
void CalculateDrawArea(ImageDrawMode mode,const RECT *pDstRect,const RECT *pSrcRect,RECT *pDrawRect);
BOOL IsOKImagingInterfaces();
void ReleaseImagingInterfaces();
IImage * m_pImage;
IImagingFactory * m_pImagingFactory;
TCHAR m_szFileName[MAX_PATH];
ImageInfo m_ImageInfo;
RECT m_rcLastThumbnail; //The last drawed area for the DrawThumbnail() function.
typedef struct MemoryDCInfo
{
HBITMAP hBitmap;
HDC hdc;
HGDIOBJ hOldSel;
UINT uiWidth;
UINT uiHeight;
}MEMORYDCINFO,*PMEMORYDCINFO;
BOOL CreateMemoryDC(HDC hdc,MEMORYDCINFO *pDCInfo,UINT uiWidth,UINT uiHeight);
BOOL IsOKMemoryDC(const MEMORYDCINFO *pMemDC);
BOOL Draw(HDC hdcDest, const RECT *pDstRect,const MEMORYDCINFO *pSrcDCInfo, const RECT *pSrcRect);
}; #endif // #ifndef IMAGE_H
//////////////////////////////////////////////////////////////////////
// Image.cpp: implementation of the CImageMaster class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "initguid.h"
#include "ImageMaster.h" //======================================================================
//Link the .lib
#pragma comment (lib,"Ole32.lib") //=======================================================================
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageMaster::CImageMaster():
m_pImage(NULL),
m_pImagingFactory(NULL)
{
memset(m_szFileName,0,sizeof(m_szFileName));
memset(&m_ImageInfo,0,sizeof(m_ImageInfo));
memset(&m_IntegrityMemDCInfo,0,sizeof(m_IntegrityMemDCInfo));
memset(&m_ThumbnailMemDCInfo,0,sizeof(m_ThumbnailMemDCInfo));
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
}
{
Close();
} //----------------------------------------------------------------------
//Description:
// Open the image file
//
//Parameters:
// pcszFile : [in] The image file to open
//
//Return Value:
// TRUE -- Succeed in opening the file
// FALSE -- Failed in opening the file
//----------------------------------------------------------------------
BOOL CImageMaster::Open(const TCHAR *pcszFile)
{
BOOL bResult = FALSE;
{
goto END;
}
{
goto END;
}
{
goto END;
}
_tcscpy(m_szFileName,pcszFile);
{
Close();
}
} //----------------------------------------------------------------------
//Description:
// Get the width of the image
//
//Parameters:
// NULL
//
//Return Value:
// 0 -- May be failure.
// others -- succeed
//----------------------------------------------------------------------
UINT CImageMaster::GetWidth()
{
} //----------------------------------------------------------------------
//Description:
// Get the height of the image
//
//Parameters:
// NULL
//
//Return Value:
// 0 -- May be failure.
// others -- succeed
//----------------------------------------------------------------------
UINT CImageMaster::GetHeight()
{
return m_ImageInfo.Height;
} //----------------------------------------------------------------------
//Description:
// Close the opened image to release the resource
//
//Parameters:
// NULL
//
//Return Value:
// NULL
//----------------------------------------------------------------------
void CImageMaster::Close()
{
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
memset(&m_ImageInfo,0,sizeof(m_ImageInfo));
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
} //-----------------------------------------------------------------------------------------------
//Description:
// Check the object is read for operating. If failed in calling the Open() or never call before,
//it will return FALSE.
//
//Parameters:
// NULL
//
//Return Values:
// TRUE - It's all ready for other operating.
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOK()
{
if(IsOKMemoryDC(&m_IntegrityMemDCInfo) == FALSE &&
IsOKMemoryDC(&m_ThumbnailMemDCInfo) == FALSE &&
IsOKImagingInterfaces() == FALSE)
{
return FALSE;
}
} //-----------------------------------------------------------------------------------------------
//Description:
// Release the imaging interfaces resource.
//
//----------------------------------------------------------------------------------------------
void CImageMaster::ReleaseImagingInterfaces()
{
if(m_pImage != NULL)
{
m_pImage->Release();
m_pImage = NULL;
}
{
m_pImagingFactory->Release();
m_pImagingFactory = NULL;
}
//Description:
// Create the memory DC for storing the image data.
//
//Parameters:
// hdc : [in] The source DC
// pDCInfo : [out] The created memory DC
// uiWidth : [in] The memory DC width
// uiHeight : [in] The memory DC height
//
//----------------------------------------------------------------------------------------------
BOOL CImageMaster::CreateMemoryDC(HDC hdc,MEMORYDCINFO *pDCInfo,UINT uiWidth,UINT uiHeight)
{
BOOL bResult = FALSE;
pDCInfo->hBitmap = CreateCompatibleBitmap(hdc,uiWidth,uiHeight);
if(pDCInfo->hBitmap == NULL)
{
goto END;
}
if(pDCInfo->hdc == NULL)
{
goto END;
}
pDCInfo->hOldSel = SelectObject(pDCInfo->hdc,pDCInfo->hBitmap);
pDCInfo->uiHeight = uiHeight;
{
DeleteMemoryDC(pDCInfo);
memset(pDCInfo,0,sizeof(MEMORYDCINFO));
}
} //-----------------------------------------------------------------------------------------------
//Description:
// Delete the memory DC to release resource
//
//Parameters:
// pDCInfo : [out] The created memory DC to be deleted.
//----------------------------------------------------------------------------------------------
void CImageMaster::DeleteMemoryDC(MEMORYDCINFO *pDCInfo)
{
SelectObject(pDCInfo->hdc,pDCInfo->hOldSel);
DeleteObject(pDCInfo->hBitmap);
DeleteDC(pDCInfo->hdc);
} //-----------------------------------------------------------------------------------------------
//Description:
// Check the imaging interfaces whether ready or not.
//
//Parameters:
// NULL
//
//Return Values:
// TRUE - It's ready
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOKImagingInterfaces()
{
if(m_pImage == NULL || m_pImagingFactory == NULL)
{
return FALSE;
}
} //-----------------------------------------------------------------------------------------------
//Description:
// Check the memory whether ready or not.
//
//Parameters:
// pMemDC : [in] The memory DC to checked.
//
//Return Values:
// TRUE - It's ready
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOKMemoryDC(const MEMORYDCINFO *pMemDC)
{
if(pMemDC->hdc == NULL || pMemDC->hBitmap == NULL || pMemDC->hOldSel == NULL)
{
return FALSE;
}
} //-----------------------------------------------------------------------------------------------
//Description:
// Caculate the draw area
//
//Parameters:
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// pDrawRect : [out] The calculated draw area.
//
//-----------------------------------------------------------------------------------------------
void CImageMaster::CalculateDrawArea(ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect, RECT *pDrawRect)
{
RECT rcDraw = {0};
{
LONG lDstWidth = (pDstRect->right > pDstRect->left) ? (pDstRect->right - pDstRect->left) : (pDstRect->left - pDstRect->right);
LONG lDstHeight = (pDstRect->bottom > pDstRect->top) ? (pDstRect->bottom - pDstRect->top) : (pDstRect->top > pDstRect->bottom);
LONG lSrcWidth = (pSrcRect == NULL) ? m_ImageInfo.Width : (pSrcRect->right - pSrcRect->left);
LONG lSrcHeight = (pSrcRect == NULL) ? m_ImageInfo.Height : (pSrcRect->bottom - pSrcRect->top);
{
lDispLeft = (lDstWidth - lSrcWidth) / 2 + pDstRect->left;
lDispTop = (lDstHeight - lSrcHeight) / 2 + pDstRect->top;
lDispWidth = lSrcWidth ;
lDispHeight = lSrcHeight ;
}
else
{
if(lSrcWidth * lDstHeight > lDstWidth * lSrcHeight)
{
lDispWidth = lDstWidth;
lDispHeight = (LONG)((float)lDispWidth / (float)lSrcWidth * lSrcHeight);
lDispLeft = pDstRect->left;
lDispTop = (lDstHeight - lDispHeight) / 2 + pDstRect->top;
}
else if(lSrcWidth * lDstHeight < lDstWidth * lSrcHeight)
{
lDispHeight = lDstHeight;
lDispWidth = (LONG)((float)lDispHeight / (float)lSrcHeight * lSrcWidth);
lDispLeft = (lDstWidth - lDispWidth) / 2 + pDstRect->left;
lDispTop = pDstRect->top;
}
else
{
lDispWidth = lDstWidth;
lDispHeight = lDstHeight;
lDispLeft = pDstRect->left;
lDispTop = pDstRect->top;
}
}
rcDraw.left = lDispLeft;
rcDraw.top = lDispTop;
rcDraw.right = lDispLeft + lDispWidth;
rcDraw.bottom = lDispTop + lDispHeight;
}
else if(mode == IMG_STRETCH)
{
rcDraw = *pDstRect;
}
//Description:
// This method displays the whole image onto the specified area as to the mode value.
//If you call the function first, it may cost a long time because of the initializing, but much quickly next time.
//So you could set the bDraw to FALSE and call the function to intialize before.
//
//Parameters:
// hdc : [in] An HDC value that is the graphics context that receives output from this method.
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// bDraw : [in] If it's true, it will draw to the Dest DC immediately, or it only intializes.
//
//Return Value:
// TRUE -- Succeed
// FALSE -- Failed
//----------------------------------------------------------------------
BOOL CImageMaster::DrawIntegrity(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
{
if(pDstRect == NULL)
{
return FALSE;
}
{
//The imaging interfaces may close before,
//we must open again
if(IsOKImagingInterfaces() == FALSE && Open(m_szFileName) == FALSE)
{
return FALSE;
}
{
return FALSE;
}
HRESULT hr = m_pImage->Draw(m_IntegrityMemDCInfo.hdc,&rcMemDC,NULL);
if(FAILED(hr))
{
ReleaseImagingInterfaces();
DeleteMemoryDC(&m_IntegrityMemDCInfo);
return FALSE;
}
}
BOOL bResult = TRUE;
if(bDraw == TRUE)
{
RECT rcDraw = {0};
CalculateDrawArea(mode,pDstRect,pSrcRect,&rcDraw);
bResult = Draw(hdc,&rcDraw,&m_IntegrityMemDCInfo,pSrcRect);
}
{
ReleaseImagingInterfaces();
}
} //----------------------------------------------------------------------
//Description:
// This method displays the Thumbnail image onto the specified area as to the mode value. If the pDstRect value is larger than the pSrcRect,
//it's the same as the DrawIntegrity() function, or it displayed the thumbnail which is not clarity enough.
//If you call the function first, it may cost a long time because of the initializing, but much quickly next time.
//So you could set the bDraw to FALSE and call the function to intialize before.
//
//Parameters:
// hdc : [in] An HDC value that is the graphics context that receives output from this method.
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// bDraw : [in] If it's true, it will draw to the Dest DC immediately, or it only intializes.
//
//Return Value:
// TRUE -- Succeed
// FALSE -- Failed
//----------------------------------------------------------------------
BOOL CImageMaster::DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
{
if(pDstRect == NULL)
{
return FALSE;
}
m_rcLastThumbnail.right - m_rcLastThumbnail.left != pDstRect->right - pDstRect->left ||
m_rcLastThumbnail.bottom - m_rcLastThumbnail.top != pDstRect->bottom - pDstRect->top)
{
m_rcLastThumbnail = *pDstRect;
//we must open again
if(IsOKImagingInterfaces() == FALSE && Open(m_szFileName) == FALSE)
{
return FALSE;
}
if(IsOKMemoryDC(&m_ThumbnailMemDCInfo) == TRUE)
{
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
}
//The IMG_NATIVE mode is most approximately to the actual image
RECT rcMinImg = {0};
CalculateDrawArea(IMG_NATIVE,pDstRect,NULL,&rcMinImg);
int iImgThumHeight = (rcMinImg.bottom > rcMinImg.top) ? (rcMinImg.bottom - rcMinImg.top) : (rcMinImg.top - rcMinImg.bottom);
if(CreateMemoryDC(hdc,&m_ThumbnailMemDCInfo,iImgThumWidth,iImgThumHeight) == FALSE)
{
return FALSE;
}
IImage *pImgThumbnail = NULL;
m_pImage->GetThumbnail(iImgThumWidth,iImgThumHeight,&pImgThumbnail);
HRESULT hr = pImgThumbnail->Draw(m_ThumbnailMemDCInfo.hdc,&rcMem,NULL);
if(FAILED(hr))
{
ReleaseImagingInterfaces();
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
return FALSE;
}
if(bDraw == TRUE)
{
RECT rcDraw = {0};
RECT rcImg = {0};
{
CalculateDrawArea(mode,pDstRect,NULL,&rcDraw);
bResult = Draw(hdc,&rcDraw,&m_ThumbnailMemDCInfo,NULL);
}
else
{
//Get the width and height with the ratio
rcImg.left = m_ThumbnailMemDCInfo.uiWidth * pSrcRect->left / m_ImageInfo.Width;
rcImg.top = m_ThumbnailMemDCInfo.uiHeight * pSrcRect->top / m_ImageInfo.Height;
rcImg.right = m_ThumbnailMemDCInfo.uiWidth * pSrcRect->right / m_ImageInfo.Width;
rcImg.bottom = m_ThumbnailMemDCInfo.uiHeight * pSrcRect->bottom / m_ImageInfo.Height;
bResult = Draw(hdc,&rcDraw,&m_ThumbnailMemDCInfo,&rcImg);
}
}
{
ReleaseImagingInterfaces();
}
//Description:
// Draw the source DC to dest DC
//
//Parameters:
// hdcDest : [in] Handle to the destination device context.
// pDstRect : [in] The dest area
// hdcSrc : [in] The source memory DC information
// pSrcRect : [in] The source area to be drawed
//
BOOL CImageMaster::Draw(HDC hdcDest, const RECT *pDstRect,const MEMORYDCINFO *pSrcDCInfo, const RECT *pSrcRect)
{
BOOL bResult = FALSE;
if(pSrcRect == NULL)
{
bResult = StretchBlt(hdcDest,
pDstRect->left,
pDstRect->top,
pDstRect->right - pDstRect->left,
pDstRect->bottom - pDstRect->top,
pSrcDCInfo->hdc,
0,
0,
pSrcDCInfo->uiWidth,
pSrcDCInfo->uiHeight,
SRCCOPY);
}
else
{
bResult = StretchBlt(hdcDest,
pDstRect->left,
pDstRect->top,
pDstRect->right - pDstRect->left,
pDstRect->bottom - pDstRect->top,
pSrcDCInfo->hdc,
pSrcRect->left,
pSrcRect->top,
pSrcRect->right - pSrcRect->left,
pSrcRect->bottom - pSrcRect->top,
SRCCOPY);
}
}
//TITLE:
// CImageMaster轻松显示图片
//AUTHOR:
// norains
//DATE:
// Sunday 26-September-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
虽然IImaging组件可以很简单地显示图片,但如果是更好地显示图片,却又不简单.那有没有什么方法能很简单又能更好地显示图片呢?答案是:有!那就是使用CImageMaster类!
...
... ...
... ... ...
Oh,Forgive me! 原谅我这个自卖自夸的人吧! 原谅我这个无聊的人偶尔发发的牢骚吧!世界多美好!
这篇豆腐块主要是介绍CImageMaster的使用,而代码的主要思想可以参考我另外一篇文章:详聊IImage的图片显示 http://blog.csdn.net/norains/archive/2007/08/26/1759912.aspx
好吧,老样子,让我们看看该类的函数吧:
1.Open(const TCHAR *pcszFile)
打开一个图片文件.如果打开成功,需要调用Close()函数进行资源的释放.
2.Close()
调用Open()成功后需调用该函数进行资源的释放.
3.IsOK()
判断是否已经准备好绘制图档.
4.GetHeight()
获取图片的高度.
5.GetWidth()
获取图片的宽度.
6.DrawIntegrity(HDC hdc, ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect,BOOL bDraw)
绘制原始图档.如果图片过大,可能会绘制失败.
hdc:目标DC
mode:绘制的模式.
IMG_FIT - 按比例拉伸至整个pDstRect区域.
IMG_STRETCH - 填充整个pDstRect区域,而不管其比例.
IMG_NATIVE - 如果pSrcRect区域小于pDstRect,则按pSrcRect的大小在pDstRect居中显示;如果pSrcRect区域大于pDstRect,则效果和IMG_FIT相同.
pDstRect: 目标DC所绘制的区域.
pSrcRect: 源DC所需要绘制的区域.
bDraw: 为TRUE时立刻绘制到hdc;为FALSE不绘制到hdc上.因为在DrawIntegrity()函数中需要从文件中获取文件信息并创建图片DC来保存图片信息,所以第一调用的时候会比较慢,但以后由于是将图片DC直接绘制到hdc中,所以速度会大大加快.
7.DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
绘制缩略图.如果DrawIntegrity()函数失败,调用该函数绘制缩略图可能会成功.
参数的意义和DrawIntegrity()相同.
代码的具体作用和思想请参见:http://blog.csdn.net/norains/archive/2007/08/26/1759912.aspx
CImageMaster的代码如下:
//////////////////////////////////////////////////////////////////////
// ImageMaster.h: interface for the CImageMaster class.
//
//Version:
// 1.1.1
//
//Date:
// 2007.08.13
//////////////////////////////////////////////////////////////////////
#ifndef IMAGEMASTER_H
#define IMAGEMASTER_H
#include
"imaging.h" //--------------------------------------------------------------------//Enum value
enum ImageDrawMode
{
//Fit to the play window size. How wide (height) the window is, how
//is the move. Keep aspect ratio.
IMG_FIT,
//Not support.Stretch to the play window size. Don't keep the aspect ratio.
IMG_STRETCH,
//When the size of video is smaller than the play window, it displayes
//as the video size. If it's bigger , it just like the DISP_FIT mode.
IMG_NATIVE
}; class CImageMaster
{
public:
BOOL DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw);
BOOL DrawIntegrity(HDC hdc, ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect,BOOL bDraw);
BOOL IsOK();
void Close();
UINT GetHeight();
UINT GetWidth();
BOOL Open(const TCHAR *pcszFile);
CImageMaster();
virtual ~CImageMaster(); protected:
void CalculateDrawArea(ImageDrawMode mode,const RECT *pDstRect,const RECT *pSrcRect,RECT *pDrawRect);
BOOL IsOKImagingInterfaces();
void ReleaseImagingInterfaces();
IImage * m_pImage;
IImagingFactory * m_pImagingFactory;
TCHAR m_szFileName[MAX_PATH];
ImageInfo m_ImageInfo;
RECT m_rcLastThumbnail; //The last drawed area for the DrawThumbnail() function.
//It's for the memory DC information
typedef struct MemoryDCInfo
{
HBITMAP hBitmap;
HDC hdc;
HGDIOBJ hOldSel;
UINT uiWidth;
UINT uiHeight;
}MEMORYDCINFO,*PMEMORYDCINFO;
MEMORYDCINFO m_IntegrityMemDCInfo;
MEMORYDCINFO m_ThumbnailMemDCInfo;
BOOL CreateMemoryDC(HDC hdc,MEMORYDCINFO *pDCInfo,UINT uiWidth,UINT uiHeight);
BOOL IsOKMemoryDC(const MEMORYDCINFO *pMemDC);
BOOL Draw(HDC hdcDest, const RECT *pDstRect,const MEMORYDCINFO *pSrcDCInfo, const RECT *pSrcRect);
}; #endif // #ifndef IMAGE_H
//////////////////////////////////////////////////////////////////////
// Image.cpp: implementation of the CImageMaster class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "initguid.h"
#include "ImageMaster.h" //======================================================================
//Link the .lib
#pragma comment (lib,"Ole32.lib") //=======================================================================
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageMaster::CImageMaster():
m_pImage(NULL),
m_pImagingFactory(NULL)
{
memset(m_szFileName,0,sizeof(m_szFileName));
memset(&m_ImageInfo,0,sizeof(m_ImageInfo));
memset(&m_IntegrityMemDCInfo,0,sizeof(m_IntegrityMemDCInfo));
memset(&m_ThumbnailMemDCInfo,0,sizeof(m_ThumbnailMemDCInfo));
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
}
CImageMaster::
~CImageMaster(){
Close();
} //----------------------------------------------------------------------
//Description:
// Open the image file
//
//Parameters:
// pcszFile : [in] The image file to open
//
//Return Value:
// TRUE -- Succeed in opening the file
// FALSE -- Failed in opening the file
//----------------------------------------------------------------------
BOOL CImageMaster::Open(const TCHAR *pcszFile)
{
BOOL bResult = FALSE;
HRESULT hr;
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
goto END;
}
if(FAILED(hr = CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_IImagingFactory,(void**) &m_pImagingFactory)))
{
goto END;
}
if(FAILED(hr = m_pImagingFactory->CreateImageFromFile(pcszFile, &m_pImage)))
{
goto END;
}
m_pImage
->GetImageInfo(&m_ImageInfo);_tcscpy(m_szFileName,pcszFile);
bResult
= TRUE;END:
{
Close();
}
return bResult;
} //----------------------------------------------------------------------
//Description:
// Get the width of the image
//
//Parameters:
// NULL
//
//Return Value:
// 0 -- May be failure.
// others -- succeed
//----------------------------------------------------------------------
UINT CImageMaster::GetWidth()
{
return m_ImageInfo.Width;
} //----------------------------------------------------------------------
//Description:
// Get the height of the image
//
//Parameters:
// NULL
//
//Return Value:
// 0 -- May be failure.
// others -- succeed
//----------------------------------------------------------------------
UINT CImageMaster::GetHeight()
{
return m_ImageInfo.Height;
} //----------------------------------------------------------------------
//Description:
// Close the opened image to release the resource
//
//Parameters:
// NULL
//
//Return Value:
// NULL
//----------------------------------------------------------------------
void CImageMaster::Close()
{
ReleaseImagingInterfaces();
DeleteMemoryDC(
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
memset(m_szFileName,
0,sizeof(m_szFileName));memset(&m_ImageInfo,0,sizeof(m_ImageInfo));
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
} //-----------------------------------------------------------------------------------------------
//Description:
// Check the object is read for operating. If failed in calling the Open() or never call before,
//it will return FALSE.
//
//Parameters:
// NULL
//
//Return Values:
// TRUE - It's all ready for other operating.
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOK()
{
if(IsOKMemoryDC(&m_IntegrityMemDCInfo) == FALSE &&
IsOKMemoryDC(&m_ThumbnailMemDCInfo) == FALSE &&
IsOKImagingInterfaces() == FALSE)
{
return FALSE;
}
return TRUE;
} //-----------------------------------------------------------------------------------------------
//Description:
// Release the imaging interfaces resource.
//
//----------------------------------------------------------------------------------------------
void CImageMaster::ReleaseImagingInterfaces()
{
if(m_pImage != NULL)
{
m_pImage->Release();
m_pImage = NULL;
}
if(m_pImagingFactory != NULL)
{
m_pImagingFactory->Release();
m_pImagingFactory = NULL;
}
CoUninitialize();
}
//Description:
// Create the memory DC for storing the image data.
//
//Parameters:
// hdc : [in] The source DC
// pDCInfo : [out] The created memory DC
// uiWidth : [in] The memory DC width
// uiHeight : [in] The memory DC height
//
//----------------------------------------------------------------------------------------------
BOOL CImageMaster::CreateMemoryDC(HDC hdc,MEMORYDCINFO *pDCInfo,UINT uiWidth,UINT uiHeight)
{
BOOL bResult = FALSE;
//Create a DC that matches the device
pDCInfo->hBitmap = CreateCompatibleBitmap(hdc,uiWidth,uiHeight);
if(pDCInfo->hBitmap == NULL)
{
goto END;
}
pDCInfo
->hdc = CreateCompatibleDC(hdc);if(pDCInfo->hdc == NULL)
{
goto END;
}
//Select the bitmap into to the compatible device context
pDCInfo->hOldSel = SelectObject(pDCInfo->hdc,pDCInfo->hBitmap);
pDCInfo
->uiWidth = uiWidth;pDCInfo->uiHeight = uiHeight;
bResult
= TRUE;END:
{
DeleteMemoryDC(pDCInfo);
memset(pDCInfo,0,sizeof(MEMORYDCINFO));
}
return TRUE;
} //-----------------------------------------------------------------------------------------------
//Description:
// Delete the memory DC to release resource
//
//Parameters:
// pDCInfo : [out] The created memory DC to be deleted.
//----------------------------------------------------------------------------------------------
void CImageMaster::DeleteMemoryDC(MEMORYDCINFO *pDCInfo)
{
SelectObject(pDCInfo->hdc,pDCInfo->hOldSel);
DeleteObject(pDCInfo->hBitmap);
DeleteDC(pDCInfo->hdc);
memset(pDCInfo,
0,sizeof(MEMORYDCINFO));} //-----------------------------------------------------------------------------------------------
//Description:
// Check the imaging interfaces whether ready or not.
//
//Parameters:
// NULL
//
//Return Values:
// TRUE - It's ready
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOKImagingInterfaces()
{
if(m_pImage == NULL || m_pImagingFactory == NULL)
{
return FALSE;
}
return TRUE;
} //-----------------------------------------------------------------------------------------------
//Description:
// Check the memory whether ready or not.
//
//Parameters:
// pMemDC : [in] The memory DC to checked.
//
//Return Values:
// TRUE - It's ready
// FALSE - It's not ready.
//
//---------------------------------------------------------------------------------------------------------
BOOL CImageMaster::IsOKMemoryDC(const MEMORYDCINFO *pMemDC)
{
if(pMemDC->hdc == NULL || pMemDC->hBitmap == NULL || pMemDC->hOldSel == NULL)
{
return FALSE;
}
return TRUE;
} //-----------------------------------------------------------------------------------------------
//Description:
// Caculate the draw area
//
//Parameters:
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// pDrawRect : [out] The calculated draw area.
//
//-----------------------------------------------------------------------------------------------
void CImageMaster::CalculateDrawArea(ImageDrawMode mode,const RECT *pDstRect, const RECT *pSrcRect, RECT *pDrawRect)
{
RECT rcDraw = {0};
if(mode == IMG_FIT || mode == IMG_NATIVE)
{
LONG lDstWidth = (pDstRect->right > pDstRect->left) ? (pDstRect->right - pDstRect->left) : (pDstRect->left - pDstRect->right);
LONG lDstHeight = (pDstRect->bottom > pDstRect->top) ? (pDstRect->bottom - pDstRect->top) : (pDstRect->top > pDstRect->bottom);
LONG lSrcWidth = (pSrcRect == NULL) ? m_ImageInfo.Width : (pSrcRect->right - pSrcRect->left);
LONG lSrcHeight = (pSrcRect == NULL) ? m_ImageInfo.Height : (pSrcRect->bottom - pSrcRect->top);
LONG lDispLeft,lDispTop,lDispWidth,lDispHeight;
if(mode == IMG_NATIVE && lDstWidth >= lSrcWidth && lDstHeight >= lSrcHeight)
{
lDispLeft = (lDstWidth - lSrcWidth) / 2 + pDstRect->left;
lDispTop = (lDstHeight - lSrcHeight) / 2 + pDstRect->top;
lDispWidth = lSrcWidth ;
lDispHeight = lSrcHeight ;
}
else
{
if(lSrcWidth * lDstHeight > lDstWidth * lSrcHeight)
{
lDispWidth = lDstWidth;
lDispHeight = (LONG)((float)lDispWidth / (float)lSrcWidth * lSrcHeight);
lDispLeft = pDstRect->left;
lDispTop = (lDstHeight - lDispHeight) / 2 + pDstRect->top;
}
else if(lSrcWidth * lDstHeight < lDstWidth * lSrcHeight)
{
lDispHeight = lDstHeight;
lDispWidth = (LONG)((float)lDispHeight / (float)lSrcHeight * lSrcWidth);
lDispLeft = (lDstWidth - lDispWidth) / 2 + pDstRect->left;
lDispTop = pDstRect->top;
}
else
{
lDispWidth = lDstWidth;
lDispHeight = lDstHeight;
lDispLeft = pDstRect->left;
lDispTop = pDstRect->top;
}
}
rcDraw.left = lDispLeft;
rcDraw.top = lDispTop;
rcDraw.right = lDispLeft + lDispWidth;
rcDraw.bottom = lDispTop + lDispHeight;
}
else if(mode == IMG_STRETCH)
{
rcDraw = *pDstRect;
}
*pDrawRect = rcDraw;
}
//----------------------------------------------------------------------//Description:
// This method displays the whole image onto the specified area as to the mode value.
//If you call the function first, it may cost a long time because of the initializing, but much quickly next time.
//So you could set the bDraw to FALSE and call the function to intialize before.
//
//Parameters:
// hdc : [in] An HDC value that is the graphics context that receives output from this method.
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// bDraw : [in] If it's true, it will draw to the Dest DC immediately, or it only intializes.
//
//Return Value:
// TRUE -- Succeed
// FALSE -- Failed
//----------------------------------------------------------------------
BOOL CImageMaster::DrawIntegrity(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
{
if(pDstRect == NULL)
{
return FALSE;
}
if(IsOKMemoryDC(&m_IntegrityMemDCInfo) == FALSE)
{
//The imaging interfaces may close before,
//we must open again
if(IsOKImagingInterfaces() == FALSE && Open(m_szFileName) == FALSE)
{
return FALSE;
}
if(CreateMemoryDC(hdc,&m_IntegrityMemDCInfo,m_ImageInfo.Width,m_ImageInfo.Height) == FALSE)
{
return FALSE;
}
RECT rcMemDC
= {0,0,m_ImageInfo.Width,m_ImageInfo.Height};HRESULT hr = m_pImage->Draw(m_IntegrityMemDCInfo.hdc,&rcMemDC,NULL);
if(FAILED(hr))
{
ReleaseImagingInterfaces();
DeleteMemoryDC(&m_IntegrityMemDCInfo);
return FALSE;
}
}
BOOL bResult = TRUE;
if(bDraw == TRUE)
{
RECT rcDraw = {0};
CalculateDrawArea(mode,pDstRect,pSrcRect,&rcDraw);
bResult = Draw(hdc,&rcDraw,&m_IntegrityMemDCInfo,pSrcRect);
}
if(IsOKImagingInterfaces() == TRUE)
{
ReleaseImagingInterfaces();
}
return bResult;
} //----------------------------------------------------------------------
//Description:
// This method displays the Thumbnail image onto the specified area as to the mode value. If the pDstRect value is larger than the pSrcRect,
//it's the same as the DrawIntegrity() function, or it displayed the thumbnail which is not clarity enough.
//If you call the function first, it may cost a long time because of the initializing, but much quickly next time.
//So you could set the bDraw to FALSE and call the function to intialize before.
//
//Parameters:
// hdc : [in] An HDC value that is the graphics context that receives output from this method.
// mode : [in] The image display mode.
// pDstRect : [in] A pointer to a RECT value defining the portion of the display area within the graphics context that receives the output from this method.
// psrcRect : [in] An optional pointer to a RECT that specifies, in 0.01mm units, the portion of the image to be drawn in dstRect.
// To display the entire image, set this value to NULL.
// bDraw : [in] If it's true, it will draw to the Dest DC immediately, or it only intializes.
//
//Return Value:
// TRUE -- Succeed
// FALSE -- Failed
//----------------------------------------------------------------------
BOOL CImageMaster::DrawThumbnail(HDC hdc, ImageDrawMode mode, const RECT *pDstRect, const RECT *pSrcRect, BOOL bDraw)
{
if(pDstRect == NULL)
{
return FALSE;
}
if(IsOKMemoryDC(&m_ThumbnailMemDCInfo) == FALSE ||
m_rcLastThumbnail.right - m_rcLastThumbnail.left != pDstRect->right - pDstRect->left ||
m_rcLastThumbnail.bottom - m_rcLastThumbnail.top != pDstRect->bottom - pDstRect->top)
{
m_rcLastThumbnail = *pDstRect;
//The imaging interfaces may close before,
//we must open again
if(IsOKImagingInterfaces() == FALSE && Open(m_szFileName) == FALSE)
{
return FALSE;
}
//Delete the memory DC created before
if(IsOKMemoryDC(&m_ThumbnailMemDCInfo) == TRUE)
{
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
}
//Caculate the minimun thumbnail width and height for creating memory DC.
//The IMG_NATIVE mode is most approximately to the actual image
RECT rcMinImg = {0};
CalculateDrawArea(IMG_NATIVE,pDstRect,NULL,&rcMinImg);
int iImgThumWidth = (rcMinImg.right > rcMinImg.left) ? (rcMinImg.right - rcMinImg.left) : (rcMinImg.left - rcMinImg.right);
int iImgThumHeight = (rcMinImg.bottom > rcMinImg.top) ? (rcMinImg.bottom - rcMinImg.top) : (rcMinImg.top - rcMinImg.bottom);
if(CreateMemoryDC(hdc,&m_ThumbnailMemDCInfo,iImgThumWidth,iImgThumHeight) == FALSE)
{
return FALSE;
}
IImage *pImgThumbnail = NULL;
m_pImage->GetThumbnail(iImgThumWidth,iImgThumHeight,&pImgThumbnail);
RECT rcMem
= {0,0,iImgThumWidth,iImgThumHeight};HRESULT hr = pImgThumbnail->Draw(m_ThumbnailMemDCInfo.hdc,&rcMem,NULL);
if(FAILED(hr))
{
ReleaseImagingInterfaces();
DeleteMemoryDC(&m_ThumbnailMemDCInfo);
memset(&m_rcLastThumbnail,0,sizeof(m_rcLastThumbnail));
return FALSE;
}
}
BOOL bResult
= TRUE;if(bDraw == TRUE)
{
RECT rcDraw = {0};
RECT rcImg = {0};
if(pSrcRect == NULL)
{
CalculateDrawArea(mode,pDstRect,NULL,&rcDraw);
bResult = Draw(hdc,&rcDraw,&m_ThumbnailMemDCInfo,NULL);
}
else
{
//Get the width and height with the ratio
rcImg.left = m_ThumbnailMemDCInfo.uiWidth * pSrcRect->left / m_ImageInfo.Width;
rcImg.top = m_ThumbnailMemDCInfo.uiHeight * pSrcRect->top / m_ImageInfo.Height;
rcImg.right = m_ThumbnailMemDCInfo.uiWidth * pSrcRect->right / m_ImageInfo.Width;
rcImg.bottom = m_ThumbnailMemDCInfo.uiHeight * pSrcRect->bottom / m_ImageInfo.Height;
CalculateDrawArea(mode,pDstRect,
&rcImg,&rcDraw);bResult = Draw(hdc,&rcDraw,&m_ThumbnailMemDCInfo,&rcImg);
}
}
if(IsOKImagingInterfaces() == TRUE)
{
ReleaseImagingInterfaces();
}
return bResult;
}
//----------------------------------------------------------------------//Description:
// Draw the source DC to dest DC
//
//Parameters:
// hdcDest : [in] Handle to the destination device context.
// pDstRect : [in] The dest area
// hdcSrc : [in] The source memory DC information
// pSrcRect : [in] The source area to be drawed
//
BOOL CImageMaster::Draw(HDC hdcDest, const RECT *pDstRect,const MEMORYDCINFO *pSrcDCInfo, const RECT *pSrcRect)
{
BOOL bResult = FALSE;
if(pSrcRect == NULL)
{
bResult = StretchBlt(hdcDest,
pDstRect->left,
pDstRect->top,
pDstRect->right - pDstRect->left,
pDstRect->bottom - pDstRect->top,
pSrcDCInfo->hdc,
0,
0,
pSrcDCInfo->uiWidth,
pSrcDCInfo->uiHeight,
SRCCOPY);
}
else
{
bResult = StretchBlt(hdcDest,
pDstRect->left,
pDstRect->top,
pDstRect->right - pDstRect->left,
pDstRect->bottom - pDstRect->top,
pSrcDCInfo->hdc,
pSrcRect->left,
pSrcRect->top,
pSrcRect->right - pSrcRect->left,
pSrcRect->bottom - pSrcRect->top,
SRCCOPY);
}
return bResult;
}