There is a fairly "standard" interface for importing diverse graphics formats into Windows applications. Only problem is, nobody bothered to document it until now.
Years ago, back in the early days of 16-bit Windows, I found several references to graphic import filters. I originally stumbled across them while using BitEdit, a small but useful image-editing utility program that shipped with the Windows Multimedia Extensions toolkit. I searched available resources at the time, but I was unable to find any references to the installation and use of such graphic import filters.
Some time later, after Windows 3.1 had shipped, I once again noticed graphic import filters, this time in relation to Microsoft Word. I presumed that there was some sort of defined API for the installation and use of import filters, and once again searched available resources. Through MSDN (the Microsoft Developer Network Library), I located an archived issue of Microsoft Systems Journal that discussed the development of graphic import filters [1]. Not having specific needs for graphics importing at the time, I filed a copy of the article and returned to more pressing matters.
Years later, after the Microsoft 32-bit migration blitz and the release of Windows 95, I was working on a project that required graphic file importing and conversion capabilities. I decided to once again look into graphic import filters to determine if they could suit my needs. Although I never incorporated these filter capabilities into the project, I was interested enough to spend additional time further investigating and using the import filter API.
I have spent a considerable amount of time disassembling various filters and programs that use filters, as well as searching though old documentation to try to decipher and define the 32-bit implementation of Aldus Type 2 graphic import filters. In this article I present enough information to get you started in using import filters in your own Windows programs.
History of Import Filters
The following "history" is what I have been able to piece together from various sources regarding the filter interface.
Originally I was aware of only Microsoft products that used graphic import filters, yet the available Microsoft resources gave no details about a filter API. Usually such lack of detail means that either the API is undocumented and for Microsoft-internal use only, or that the API originates outside of Microsoft. The latter is the case: graphic import filters and their associated API were originally designed and developed by Aldus for their PageMaker product. (Aldus has since merged with Adobe [2], which now maintains the product line and APIs.)
There have been three major versions of the filter interface: Type 1, Type 2, and Type 3. Type 2 filters were initially designed to be a 16-bit interface primarily supported by Windows 3.x. From what I can determine, about a year after Windows 95 was released, the filter interface was revved to Type 3 to include 32-bit capabilities as well as to expand and enhance the API [3].
The new Type 3 interface was targeted to replace Type 2, yet does not maintain backward compatibility. I suspect that because of the lack of such legacy support, as well as the delay involved in rewriting code to a 32-bit interface, most filter developers at the time decided to maintain the Type 2 interface definition while making use of 32-bit types. Unfortunately, this lead to a detached API that is neither standardized nor formally documented.
By reverse engineering the methods used by Microsoft Word in conjunction with scant 16-bit Type 2 documentation, I have been able to define the 32-bit Type 2 filter interface. Although it is under-documented/undocumented, I have used this filter interface in several applications without problem under Windows 95, Windows 98, Windows NT, and Windows 2000.
Filter Libraries
Type 2 filter libraries are essentially DLLs (dynamic link libraries) with a defined set of exported functions. Although the filter libraries are DLLs, they typically have a .flt extension. Such filter libraries are loaded via the standard Win32 LoadLibrary function followed by GetProcAddress to locate the various export entry points.
Although other applications and utilities install graphic import filters, the most common installer of such filters is Microsoft Office. Table 1 illustrates the available Office 97 import filter libraries, as well as those that are installed by default during a typical install.
Locating Import Filters
Properly installed import filters are specified by various Windows registry entries. These entries define the name of the import filter, supported formats (based on file extension), and the full path of the import filter.
During installation, filters are registered in the Windows registry under the HKEY_LOCAL_MACHINE key, Software\Microsoft\Shared Tools\Graphics Filters\Import sub-key. Under this sub-key is a list of installed import filters, as well as the specifics of each import filter. See Figure 1 for an example of the registry keys and values. The actual quantity and types of registered filters is dependent on the software components installed on the target machine. Additionally, under the Graphics Filters key is a similar Export section of entries. I have not done any investigation into graphic exporting capabilities and will therefore limit the remainder of the discussion to importing.
To locate import filters, simply enumerate the sub-keys of the Import key defined above. Each enumerated key has several values as defined in Table 2.
The process of enumerating supported file types and locating a particular filter library is straightforward yet mundane and is not discussed further. Refer to the accompanying Filter.cpp source listing (Listing 2) for an example of this process.
The Import Interface
A graphic import filter library must export at least two entry points: GetFilterInfo and ImportGR. Most filters also export additional functions that allow for the control of import preferences and other settings (see Figure 2), however the two listed above are those that are primarily used during import. See the "Import Filter API" sidebar for details on the functions, parameters, and structure definitions.
Largely due to the lack of standards and documentation, the names of the actual exported functions varies among the various filters. For example, I have observed the ImportGR function exported as ImportGR, ImportGr, ImportGR@16, ImportGr@16, or IMPORTGR. To successfully locate the exported entry points, an application must try each of the variations until the actual export is found.
Importing
Of the available entry-points, the ImportGR function performs the actual graphic import and conversion process. On success, the results are stored in a PICTINFO structure. Unfortunately, import filters convert source image formats into old-style Windows metafiles (not to be confused with enhanced or placeable metafiles). Although useful in their own right, metafiles are generally difficult to manage and are best suited for vector-based graphics and drawing. Drawing the metafile or extracting the embedded raster bitmap image turns out to be the most difficult process after the import. Rather than digress into a discussion on the use of Windows metafiles, I recommend reading the various Windows API reference manuals that discuss metafiles in detail [4]. I will, however, detail some of the problems that I have encountered processing the resultant metafile.
It turns out that import filters return either a global handle (HGLOBAL) to an in-memory image of a metafile or a handle to a metafile (HMETAFILE). I have found that using the Win32 GetObjectType function provides a fairly reliable method to determine the actual handle type: it returns OBJ_METAFILE if the handle is a metafile, 0 if it is a global handle. (If desired, the GlobalFlags function can be used to further validate the global handle.)
I have experienced marginal results playing imported metafiles via PlayMetaFile and recommend converting it to an enhanced metafile using the appropriate Win32 APIs. For standard metafiles, extract the metafile bits using GetMetaFileBitsEx; for global handles, use GlobalLock to obtain a pointer to the metafile bits. SetWinMetaFileBits is used to convert the bits to an enhanced metafile and PlayEnhMetaFile can then be used to display the enhanced metafile.
Since most popular image formats are raster-based, I have noticed that import filters typically convert the graphic to a standard Windows bitmap which is embedded into the metafile. Armed with a little knowledge regarding metafiles, it is possible to enumerate the embedded metafile operations and directly extract the bitmap handle [5]. Again I refer you to the Windows API reference, specifically EnumMetaFile for details on this process.
Of the above choices, I recommend enumerating the metafile and directly extracting the bitmap. Be forewarned that not all metafiles contain an embedded bitmap and therefore it may be necessary to revert to using the PlayMetaFile or conversion techniques described above.
Source Code
The accompanying source files, Filter.h and Filter.cpp, are shown in Listing 1 and 2 respectively. They demonstrate the process of locating a suitable filter and then importing a graphic file [6]. The primary exposed interface is provided through the function ImportGraphic.
The ImportGraphic function takes several parameters: the name of the file to import, the address of a PICTINFO structure (see sidebar) to populate with the results of the import, a Boolean flag to control the display of filter preferences, and an optional parent window handle for the preferences dialog.
Internally, the ImportGraphic function uses the FindGraphicImportFilter function also located in Filter.cpp. This function locates a filter that can process the specified graphic file type (based on the file extension). FindGraphicImportFilter demonstrates the process of opening the registry and enumerating the installed filters until a suitable filter is found. Refer to the source comments for further details on its usage and operation.
Conclusion
Although the actual filter interface is somewhat archaic in its use of metafiles, graphic import filters allow applications to leverage import technology from a centralized shared pool of available filters. Hopefully the information I have provided in this article information will be useful and create a better understanding regarding these available shared components.
Notes and References
[1] Kevin P. Welch. "Creating Graphics Import Filter Libraries for Windows Applications," Microsoft Systems Journal, January-February issue, 1992. Pages 101-107. M&T Press.
[2] Details of the merger can be found on Adobes website at http://www.adobe.com.
[3] Information regarding Adobe SDKs, documentation, and other developer resources can be found at the Adobe Developer Relations website at http://partners.adobe.com/ash/developer/.
[4] I have found the best metafile reference located in the Windows 3.1 SDK documentation, Volume IV.
[5] It appears that Microsoft Word primarily uses this technique of directly extracting the bitmap from the metafile.
[6] The source code was developed and compiled with Microsoft Visual C++ 6.0 and tested on Windows 2000, Windows NT 4.0, Windows 95, and Windows 98.
[7] See the Win32 GetShortPathName function for details on the conversion of long file names to their short name representation.
Bret S. Pehrson started professionally programming educational software back in the days of Windows 3.0. Since then, he has worked on Multimedia authoring packages and 3-D rendering applications. He currently works as a professional consultant writing Windows NT and CE applications.