Introduction
This article introduces WTLIPicture
Viewer, an updated version of the WTL BmpView
sample application. WTLIPicture
Viewer uses a wrapper for the OLE Picture
object and handles multiple image types, including bitmap, cursor, enhanced metafile, icon, gif, jpeg, and windows metafile. Image files can be opened and zoomed in or out, copied from or pasted to the clipboard, and previewed and printed.
The Picture
object wrapper is contained in the source file WTLIPicture.h and provides all needed code for using a Picture
object with an image viewer like the sample WTLIPicture
Viewer. It contains a WTL port and extension of the CPictureHolder
class from MFC and also contains classes that provide support for multiple clipboard image formats. In addition, it provides a set of semi-standardized structures, similar to BITMAPFILEHEADER
and BITMAPINFOHEADER
, for most of the supported image formats.
A Note About PNG
WTLIPicture
Viewer does not support PNG images because IPicture
predates PNG.
Picture Object
OLE Picture
objects provide a language-neutral abstraction for bitmaps, icons, and metafiles. The primary interfaces are IPicture
and IPictureDisp
. The IPicture
interface allows the caller to manage picture properties and to use the picture in graphical rendering. The IPictureDisp
interface is derived from IDispatch
to provide access to the picture's properties through automation.
The following subsections explain the various methods provided by the CPixT
template to simplify use of a Picture
Object. Member variable m_pPix
is an IPicture
pointer.
Create Methods
CreateEmpty()
is the basic method provided by CPixT
to initialize a Picture
object. All other create
methods call it, passing a pointer to a filled in PICTDESC
structure containing information about the picture.
BOOL CreateEmpty(LPPICTDESC lpPictDesc = NULL, BOOL bOwn = FALSE)
{ if (lpPictDesc == NULL)
{
PICTDESC pdesc;
pdesc.cbSizeofstruct = sizeof(pdesc);
pdesc.picType = PICTYPE_NONE;
lpPictDesc = &pdesc;
}
return SUCCEEDED(::OleCreatePictureIndirect(lpPictDesc, IID_IPicture, bOwn,
(LPVOID*)&m_pPix)); }
CreateFromBitmap()
is a set of three methods that allow initialization of a Picture
object from a bitmap resource, a CBitmap
pointer, or a bitmap handle. The following code shows the version that accepts a bitmap handle, an optional palette, and a flag indicating whether or not to transfer ownership of the bitmap to the Picture
object.
BOOL CreateFromBitmap(HBITMAP hbm, HPALETTE hpal, BOOL bTransferOwnership)
{ PICTDESC pdesc;
pdesc.cbSizeofstruct = sizeof(pdesc);
pdesc.picType = PICTYPE_BITMAP;
pdesc.bmp.hbitmap = hbm;
pdesc.bmp.hpal = hpal;
return CreateEmpty(&pdesc, bTransferOwnership); }
CreateFromEnhancedMetafile()
supports creation of a Picture
object from an Enhanced Metafile.
CreateFromIcon()
provides methods that create a Picture
object from either an icon resource or an icon handle. It supports both icon and cursor images.
CreateFromMetafile()
provides initialization of a Picture
object from a Windows Metafile.
Load Methods
These methods provide mechanisms for loading a Picture
object from various input sources such as files and streams.
LoadFromDispatch
loads a Picture
object from an image file and sets the IPictureDisp
interface.
BOOL LoadFromDispatch(LPTSTR szFilePath)
{ VARIANT varFileName;
varFileName.vt = VT_BSTR;
varFileName.bstrVal = CComBSTR(szFilePath);
LPDISPATCH lpDisp = NULL;
BOOL bResult = SUCCEEDED(::OleLoadPictureFile(varFileName, &lpDisp));
if (bResult) lpDisp->QueryInterface(IID_IPicture, (LPVOID*)&m_pPix);
return bResult; }
LoadFromFile()
loads a Picture
object from an image file using standard file i/o.
LoadFromIStream()
loads from an IStream
.
LoadFromISequentialStream()
loads the Picture
object using an ISequentialStream
pointer such as those from an OLE DB provider.
LoadFromPath()
loads from a file name or URL. This is the simplest method of loading an image but it is rumored to leak resources.
BOOL LoadFromPath(LPCTSTR szFilePath)
{ return SUCCEEDED(::OleLoadPicturePath(CComBSTR(szFilePath), NULL, 0, 0,
IID_IPicture, (LPVOID *)&m_pPix)); }
Save Methods
These methods provide mechanisms for saving a Picture
object to a file.
SaveToDispatch()
saves a Picture
object to an image file using the IPictureDisp
interface.
BOOL SaveToDispatch(LPTSTR szFilePath)
{ BOOL bResult = FALSE;
LPPICTUREDISP pDisp = NULL;
if (SUCCEEDED(m_pPix->QueryInterface(IID_IPictureDisp, (LPVOID*)&pDisp)))
BOOL bResult = SUCCEEDED(::OleSavePictureFile((LPDISPATCH)pDisp,
CComBSTR(szFilePath)));
return bResult; }
SaveToFile()
saves a Picture
object to an image file using standard file I/O.
Render Method
Draws the image that was created or loaded into the IPicture
onto a device context. You can pass in a rectangle with values less than the image size to scale down or with values greater than the image size to scale up.
void Render(CDCHandle dc, const CRect& rcRender)
{ long hmWidth;
long hmHeight;
m_pPix->get_Width(&hmWidth);
m_pPix->get_Height(&hmHeight);
m_pPix->Render(dc, rcRender.left, rcRender.top, rcRender.Width(),
rcRender.Height(), 0, hmHeight-1, hmWidth, -hmHeight, NULL); }
Properties
GetAttributes()
- returns a DWORD
containing transparency and scalability flags
GetDescription()
- returns the textual description of the image type
GetHandle()
- returns an OLE_HANDLE
to the image
GetHandle()
- takes a reference to an OLE_HANDLE
and sets the value
GetPixInformation()
- returns a structure with image information such as size, type, and the first 256 bytes of the image
GetSizeInHiMetric()
- takes a SIZE
reference and returns height and width in HiMetric
GetSizeInPixels()
- as above, but in Pixels
GetType()
- returns the numeric image type, such as PICTYPE_BITMAP
Tests
These methods return a BOOL
value indicating what type of image the IPicture
contains.
IsNull()
- m_pPix
is null
IsBitmap()
- image is a bitmap, GIF, or JPEG
IsMetafile()
- image is a windows metafile
IsIcon()
- image is an icon or cursor
IsEnhMetafile()
- image is an enhanced metafile
Clipboard Helper Classes
WTLIPicture.h contains two classes that help when getting or setting clipboard images. CClipboardFormatDlg
is a small dialog to prompt image type selection when more than one type is available on the clipboard. It supports bitmap, enhanced metafile, and windows metafile. CWTLIPictureClipboard
provides the copy function for bitmap, icon (converted to bitmap), and both metafile types. It also provides the paste function for bitmap and both types of metafiles.
Semi-standard Structures
WTLIPicture.h provides a set of semi-standardized structures, similar to BITMAPFILEHEADER
and BITMAPINFOHEADER
. Structures are provided for cursors and icons, jpegs, and enhanced and windows metafiles. The intent of these structures is to provide access to commonly referenced values contained in image file headers. For example, here is the definition of METAFILEHEADER
for windows metafiles.
#include < pshpack2.h >
typedef struct tagMETAFILEHEADER {
DWORD mfKey; WORD mfHandle; WORD mfLeft; WORD mfTop; WORD mfRight; WORD mfBottom; WORD mfInch; DWORD mfReserved; WORD mfChecksum; } METAFILEHEADER, FAR *LPMETAFILEHEADER;
#include < poppack.h >
The include files pshpack2.h and poppack.h are required to byte align the structure because it does not end on a four byte boundary.
Known Issues
- PNG images are not supported as
IPicture
doesn't support PNG
- EMF images that are copied to the clipboard and pasted back in WMF format are misaligned
SaveToDispatch()
may cause a system crash with large images (> 5 MB)
- Slight flickering may occur when a zoomed image is scrolled
Acknowledgements
The CWTLIPictureT
template class is a WTL port and extension of CPictureHolder
from the Microsoft Foundation Class library. The WTLIPictureViewer
application is based on the BmpView
sample application distributed with the Windows Template Library.
Terms Of Use
The sample application available with this article is free but is subject to any restrictions placed on the original BmpView
sample application and CPictureHolder
. The source code provided in WTLIPicture.h is free to use for any purpose as long as CPOL requirements are observed.
THIS SOFTWARE IS DISTRIBUTED AS-IS, WITHOUT WARRANTIES OF ANY KIND.