原文地址:http://blog.csdn.net/norains/archive/2007/09/09/1777823.aspx
//============================================================
//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; void DeleteMemoryDC(MEMORYDCINFO *pDCInfo); 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: if(bResult == FALSE) { 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(&m_IntegrityMemDCInfo); 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: if(bResult == FALSE) { 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; }