Vous êtes sur la page 1sur 50

Image Color Matching

in
Win32

ver 1.01

10 July 1996

MICROSOFT CONFIDENTIAL
Prolog
..............................................................................................................................................................

Background
..............................................................................................................................................................

Windows users want color WYSIWYG.


................................................................................................................................................

Windows users want colors to match across output devices.


................................................................................................................................................

Color matching is not a trivial mathematical exercise.


................................................................................................................................................

Windows users do not want all objects to be color matched.


................................................................................................................................................

Control of color matching belongs in applications.


................................................................................................................................................

Users should be shielded from picking profiles.


................................................................................................................................................

Requirements to meet the goals.


................................................................................................................................................

Windows 3.1 Color Architecture


..............................................................................................................................................................

Logical Color Space


..............................................................................................................................................................

Calibrated RGB
................................................................................................................................................

Device Color Coordinates


................................................................................................................................................

CMYK space
................................................................................................................................................

Color Communication
..............................................................................................................................................................

Color Communication Model


................................................................................................................................................

Color Communication Architecture


................................................................................................................................................

User Interface
..............................................................................................................................................................

Implementation details

Microsoft Confidential
2
..............................................................................................................................................................

Application APIs
................................................................................................................................................

Color Profiles
................................................................................................................................................

Image Color Matching DLL


................................................................................................................................................

Gamut Matching
................................................................................................................................................

Enhanced Metafiles
................................................................................................................................................

DIBs and device independent color


................................................................................................................................................

Tracking installed ICC profiles


................................................................................................................................................

Device Characterization Utilities


................................................................................................................................................

Support for multiple color matching DLL’s


................................................................................................................................................

Writing an Image Color Matcher DLL


................................................................................................................................................

Writing a Device Driver to Implement Image Color Matching


................................................................................................................................................

A note about 8-bit display adapters


................................................................................................................................................

API, flags, #defines, and structures


..............................................................................................................................................................

Flags
.................................................................................................................................

#define's
.................................................................................................................................

Structures
.................................................................................................................................

Application APIs
................................................................................................................................................

SetICMMode
.................................................................................................................................

CreateColorSpace

Microsoft Confidential
3
.................................................................................................................................

SetColorSpace
.................................................................................................................................

GetColorSpace
.................................................................................................................................

GetLogColorSpace
.................................................................................................................................

DeleteColorSpace
.................................................................................................................................

GetICMProfile
.................................................................................................................................

SetICMProfile
.................................................................................................................................

EnumICMProfiles
.................................................................................................................................

EnumICMProfilesProc
.................................................................................................................................

CheckColorsInGamut
.................................................................................................................................

ColorMatchToTarget
.................................................................................................................................

UpdateICMRegKey
.................................................................................................................................

GetDeviceGammaRamp
.................................................................................................................................

SetDeviceGammaRamp
.................................................................................................................................

API for Color Matching DLL


................................................................................................................................................

CMGetInfo
.................................................................................................................................

CMCreateTransform
.................................................................................................................................

CMDeleteTransform
.................................................................................................................................

CMTranslateRGB
.................................................................................................................................

CMTranslateRGBs

Microsoft Confidential
4
.................................................................................................................................

CMCheckColorsInGamut
.................................................................................................................................

DDI, flags, #defines, and structures


..............................................................................................................................................................

Flags
.................................................................................................................................

Structures
.................................................................................................................................

DDI
................................................................................................................................................

DDIGammaRamp
.................................................................................................................................

ICMColorInfo
.................................................................................................................................

Microsoft Confidential
5
Prolog
This document answers the question, "What did we do about device independent color in Windows 95?" It
starts off with a quick discussion of the problem, goes through the color architecture and winds up with
the color API. This API covers different sets of functionality: color matching API's for applications, API's
for installable color matchers, and API's for color utility programs. This document assumes familiarity
with the GDI model of DC's and objects. The phrase “Image Color Matching” is used to denote the
architecture of color communication and color matching between devices; it does not imply that only
natural images, such as photographs, are color matched. All output generated by all primitives can be
color matched. The ICC is the consortium that has defined the industry standard color profile format.

Background

Windows users want color WYSIWYG.


WYSIWYG is an important goal of the graphics layer in Windows. Traditionally WYSIWYG is achieved
when objects on the screen end up 'in the same place' on the printer and spatial relationships between
objects are preserved. In order to format a printed document it is important that the display accurately
represent the printed page; otherwise a tedious and error prone process is required of tweaking the display
image and printing out test pages. The more exact the match the happier our customers are. However in
the case of color Windows 3.1 was not WYSIWYG. When users scanned in images the colors on the
screen probably did not match the colors on the printer, and neither was necessary a good match to the
original. Please note that this is a stricter requirement than just great looking output from a printer. There
are a few Windows 3.1 color printer drivers that deliver great looking output, even on some of the inkjets;
these printer drivers assume match to an idealized display of given color characterizations. However they
cannot do best color matching because these printer drivers do not know the exact capabilities of the
display device.
Windows users want colors to match across output devices.
But color WYSIWIG is not sufficient for Windows users in the same way that spatial WYSIWIG is not
sufficient. WYSIWIG means that the image on the screen matches the image on the printer, but it does not
mean that the same image will produced on different printers, say with different pixels per inch. A
document is not allowed to reflow just because the user changed monitors! Objects are not allowed relative
motion and colors are not allowed to change. For example, if multimedia shopping catalogs are to be a
success then advertisers will need assurance that the ads they design will be accurately reproduced on the
screen. We can also expect graphic designers to work cooperatively on a project, this implies that the
displayed colors must be the same across all their machines.

Color matching is not a trivial mathematical exercise.


Now an important point must be made. The perception of color involves a viewer with a very complicated
neuron based information filter. For example the white on the screen is generally bluish, but the wonderful
filtering going on in our brain interprets it as white. Having the color on the printed page match spectrally
would be the wrong thing to do, compared to the white of the blank paper the printed screen white would
appear blue. Color matching is not just mathematical transformations blindly applied. A better term than
color matching is 'image color matching' (ICM) which makes explicit that it is the image as a whole, and
not pixels, that need matching. Defining and passing around a standard color space, and reproducing
those colors as accurately as possible is not sufficient for device independent color. The human perception
of color is weird, not intuitive, and hard. And it only gets harder, different devices have areas of non-
overlapping color. For example the screen can display blues that no printer will be able to produce,
likewise there are magentas on a page you will never get on a display. The range of colors a specific
device can produce is called its gamut. What should the system do when it can't spectrographically
reproduce the color asked for? What should the system do when the image you designed on the screen
contains many colors that the printer cannot accurately reproduce? The system does gamut matching. This

Microsoft Confidential
6
can range from the simple (such as truncating to the surface of the printer gamut), to the sophisticated
(such as moving all colors a bit to maintain contrasts). Accurate color reproduction is an active research
topic, and there are many different, sophisticated, evolving methods. Furthermore the techniques used are
usually closely tied to specific printer technology.

It must also be stressed that we can only approximate incontrovertible ICM. Each output technology has
its own advantages, disadvantages, and color characteristics and gamuts. No image will appear exactly the
same across different technologies. We cannot solve this problem; it is the usual dichotomy between a
device independent representation, and the fact that printers do not have infinite spatial or color
resolution. Approximations must be made to the ideal, and different printers require different
compromises.

Windows users do not want all objects to be color matched.


As a simple example imagine the most natural use of color in bar charts in presentation packages. Users
like these to be saturated, undithered colors. In essence they want to use the device colors in specific ways.
They don't want the device to dither together lots of primaries and produce ugly patterns, they don't want
color matching to get in the way. Please note that this choice is not on a per application basis, or even a
per DC basis, a Windows Word document might want color matching for bitmap images and device colors
for charts and highlights. It's still going to take time, education, and experience for users and ISV's to
figure out where color matching makes sense for them, and when it should and should not be used.

Control of color matching belongs in applications.


Let us focus on the user for a moment. How does the user use and interact with color matching? Should
the screen's colors be manipulated to match the printer's, or should the printer's colors be manipulated to
match the screen, or should both be manipulated to match the logical color space? Different users will
want different approaches. Transforming from the logical color space to the device color space is not
necessarily fast, taking the speed hit when going to the screen 1 may not be acceptable. In addition, current
DIBs are not defined in a logical color space, they are generally defined against the current display. So it
is reasonable to expect that some users will want the device colors to match the logical colors and some
won't. For all of these reasons, and the reasons listed in the sections above, the control of the details of
color matching must reside in applications, not in an application independent component of Windows.
However in Windows 95 we do allow users to enable ICM for a printer job. This is discussed in detail in a
further section.

Users should be shielded from picking profiles.


Imagine if you will that a user has many color printers and many color profiles for these many devices.
When the user starts a print job the system should find the profile that matches the print environment. The
environment encompasses the manufacturer of the device, the model of the device, the type of paper
printed on, the dithering techniques, the resolution of the device, the viewing conditions, line angle, line
frequency, etc. Windows makes a best effort to hide these complications from the user: the ICC profiles
have tags in them that describe the printing environment and device drivers communicate back to GDI the
setup of the printer. Windows uses this information to pick the best ICC profile for the printer setup.
Requirements to meet the goals.
In order for colors to be constant across all devices means that there must be some device independent way
of specifying color. In the Windows nomenclature what are needed are 'logical colors' 2. A logical color has

1 The speed hit depends on the pixel depth and whether a color lookup table (CLUT) is used. For VGAs,
an 8-bit CLUT, the hit should not be noticeable.
2 I am being somewhat subtle here. The RGB triplet used to specify color in Windows today is not really
'logical', although it may be refered to as such. This is because there is no independent measure of what,
say, (255,0,0) means. There is no definition of 'red' in terms of any colormetric measures. Contrast this to,

Microsoft Confidential
7
an objective meaning independent of any output device. There also must be plumbing in the system to get
logical colors communicated between devices, input devices, such as scanners, included. These output
devices, or GDI on behalf of the devices, must then be able to accurately realize the logical color asked for.
Devices that do not respect the input logical color space do *not* do color matching, regardless of the
quality of the output, or their match to a theoretical monitor space. These three items, logical colors,
plumbing, image color matching support (by device drivers or the system), must be satisfied to get device
independent color.

Windows 3.1 Color Architecture


Windows 3.1 didn't have one, or rather it had a minimalist one. Applications specify the color of objects
(pens, brushes, text, and pixels), through a 24 bit triplet RGB. This triplet is passed as the lower 24 bits of
a 32 bit quantity. This 32 bit quantity is called a ColorRef, the high byte can be flags or other stuff. GDI
does not look at or process RBG triplets in any way. It merely passes them on through, from the
application to the device. See diagram below. There are 8 bits per channel, where the 'R' represents red,
the 'G' green, and the 'B' blue. There are no exact definitions for red, green, and blue. The color that gets
produced is totally under the whim of the device. The red of the display does not necessarily (and almost
never does) look like the red of an inkjet printer, the red of a thermal wax printer, or the red of a film
recorder; of course, these devices do not match among themselves. Not only are the endpoints of the RGB
channels not defined, the scale of 0 to 255 is not defined either. A value of 127 does not mean that color
has half the intensity of the 255 color. Some devices interpret it that way, some don't. The interpretation of
a linear ramp in perceived intensity is known as gamma correction. 3 Some Windows display drivers do
gamma correction, some don't; this means that just by changing drivers the images on a user's display can
change.
Display
RGB Display Display
Driver RGB
RGB
App
GDI
Printer
RGB Printer Printer
Driver CMY(K)

Logical Color Space


All standard color spaces are based on the 1931 CIEXYZ standard. Various permutations are used for
various reasons. Calibrated RGB is popular because displays work that way. L*a*b* is technically cool
because it models the human visual system better and fits into 8 bits without producing artifacts. HSV is
used in UI because it is somewhat intuitive. But again, all of these spaces are mathematically equivalent.
For simplicity Windows will allow only device color coordinates and calibrated RGB across the API.
Applications will be able to set their color space on a per DC basis.
Calibrated RGB
The logical color space will be calibrated RGB. The RGB endpoints will be defined by CIEXYZ triplets,
these are equivalent to chromaticity doublets and the white point. The triplets will be 3 32 bit words. A
gamma will set the response curves of each of the primaries. Obviously if an application just wanted to
work in CIEXYZ space it could set the endpoints of its RGB to match.
Device Color Coordinates

say, lines, where if the application asked for a two inch line there is independent verification if the printer
satisfied the request correctly.
3This is a bit of a simplification, but it is a good working model.

Microsoft Confidential
8
At various times applications may wish to work in the device color space of an arbitrary output device. In
this case applications can set the characterization of the device as the color space.
CMYK space
Many ISV's have asked for the capability of using CMYK instead of RGB as the color indicator. These
applications do their own color separation and wish to pass device color coordinates to CMYK printers.
We will define a color space and new ColorRef for device CMYK. These values will always be sent to the
device driver without color transformations. 4

Color Communication

Color Communication Model


Before diving into implementation details, and constructing API's, we build a conceptual model of color
communication flow that builds a simple framework in which to place these different topics.

So far we have concentrated on physical output devices and the colors that the physical phosphors and
inks limit them to. But applications can also write to bitmaps and DIBs. Anything that an application can
perform graphics operations on we define to be a surface. This includes bitmaps and DIBs in addition to
printers, plotters, displays, film recorders, and other output devices (but not GDI metafiles). A surface has
immutable properties. Some of the currently defined properties are size, color capabilities, resolution, dot
size, and palette capabilities. To this list we add color characterization. The color characterization of a
surface is the mapping from CIEXYZ space to the color coordinates of the surface. For physical output
devices the meaning is clear, the color coordinates are the amounts of R or B or G, or C or Y or M or K.
But what about bitmaps, DIBs, and somesuch?

Note that bitmaps are distinguished from DIBs, and the distinguishing factor is that bitmaps are device
driver specific and DIBs are, well, Device Independent Bitmaps. To make the distinction clearer let us call
bitmaps by their proper name, compatible bitmaps; they are created by CreateCompatibleBitmap().
CreateContemptibleBitmap() is a call to the driver of a physical device to create an offscreen bitmap. This
bitmap can be in offscreen device memory or system memory. It is inaccurate to call a compatible bitmap a
'memory bitmap' even though it may reside in system memory; the fact that it is in system memory is
irrelevant and implies things it shouldn't. A compatible bitmap is an extension of a physical device -
except for its size it has the same properties as the device. The architecture of the palette manager in
Windows follows this model. There is no color table tied to the bits in a compatible bitmap because the
bits can only be interpreted against the device hardware palette. Specifically it has the same immutable
color characterization. This is why in the diagram below compatible bitmaps are drawn in the same box as
the originating device.

DIBs are a surface. Currently they have no color characterization associated with them. Device
independence means that on all devices the output must be the same, including the colors. To meet this
goal we will add to the DIB header color characterization. Unlike other surfaces however the
characterization can be under application control.

On the application side is the definition of a color space. This is on a per DC basis, every DC will have
associated with it an application definable color space. The definition of a color space communicates two
items. The first is the form of the color information passed in the DWORD that traditionally has held an
RGB triplet. We will allow for device CMYK to be used in addition to RGB's. The second item is how
RGB triplets are to be interpreted in terms of CIEXYZ. Or to be redundant, the color space is a mapping
from RGB to CIEXYZ.

4In Windows 95 only Win32 bitmaps will be able to be defined in a CMYK color space. And the output
device must be able to accept that input. A new capability bit has been added to reflect this.

Microsoft Confidential
9
The following diagram shows the framework. The color converters in the middle do not necessarily
represent separate components. One or both could be in GDI or in the device driver. The next section
discusses this.

GDI
Display Color
DC display Char
Comp. Bitmap
Clr Space 1

Printer 1
DC comp. bit Color
App 1
Clr Space 2 Char
Comp. Bitmap

DC printer 1
Clr Space 3 Printer 2 Color
Char
Comp. Bitmap
DC display Color
Clr Space 4 DIB Section Char

DC printer 2
App 2 Device Color
Clr Space 5
Char
Comp. Bitmap
DC DIB
Clr Space 6

Color Space to CIEXYZ CIEXYZ to Device Coordinates


Color Communication Architecture
The model above stressed the difference between the color space applications work in and the color
characterization of the device. But now we are forced to implementation details and the question becomes,
'Where is the DDI line in the color model? What gets passed across the DDI 1) device color coordinates,
2) CIEXYZ, 3) the application defined color space, or 4) some combination of the above?' For
compatibility, application control, and having GDI perform image color matching at a minimum device
color coordinates must be passed across. Since CIEXYZ and the application's color space are related, it
seems redundant to have the choice to pass either. In order to keep mathematical operations, which could
lead to rounding error accumulations, to a minimum CIEXYZ will not be passed through. The
applications color space coordinates also will be passed through.

Microsoft Confidential
10
RGB
RGB GDI RGB' Device
App CMYK CMYK Driver Device
CMYK'

Log
Colorspace
ICC Profile

Transform ColorQuad
Management Transformations

Generic
Image Color
Matcher

Basically the change from the model diagram is a DDL that transforms from the logical color space to
device color coordinates in place of the two operations with CIEXYZ as an intermediary.

In order for Windows to do color matching, output devices must ship with characterization files that map
between device color coordinates and a logical color space. If the device driver wishes to do its own
matching that is allowed. Windows will check to see if the driver has implemented color matching DDI, if
it does then GDI will pass through the ColorRef unaltered.

Some 24 (and higher) bit display adapters support downloadable gamma correction tables. It is assumed
that any utilities that set these tables will also update the profile for the screen.

User Interface

As mentioned in a section above, there is a simple amount of exposed support for application independent
color support. There is a property sheet in the printer setup dialog to enable ICM on a print job basis if an
ICC color profile is present for the given configuration 5. In order to address the hard issues of what to do
with natural images versus bar charts color correction is applied only to DIBs and bitmaps, not to pens,
brushes, text, and pixels. This is the wrong thing to do for applications that construct images out of
polygons, such as CorelDraw, but that’s the compromise that was made 6. The property sheet also allows
for selecting the gamut matching method, somewhat odd considering only natural images are color
matched.

Implementation details
The device independent API's can be broken down into three areas, application support, third party
ICMDLLs, and color utilities to create ICC color profiles.

Application APIs
5 This was the orginal design for Windows. However in the shipping versions of both the universal printer
driver and the PostScript driver the choice is always given. This will be fixed in a future version.
6 For the universal printer driver this is the only practical choice, different dithering techniques are used
to generate brushes and dithering natural images and the ICC profiles we ship are tuned for the natural
image dithering method.

Microsoft Confidential
11
An application does not have to do much in order to put device independent color into motion. It only has
to use one API, SetICMMode() to turn image color matching on and off to a device. If a profile does not
exist for the configuration of the device then SetICMMode will fail. Windows will keep track of the
characterizations of all devices, use a default gamut matching method, and choose the monitor as the
default color space. This allows the screen output to be fast and the printer to match the screen.

If an application wishes to work in a color space different from the default, then it can change the color
space through the API's CreateColorSpace() and SetColorSpace(). CreateColorSpace takes a pointer to a
logical color space structure. It then sets the color space into a DC. When the application is done with the
color space it destroys it with DeleteColorSpace(). To retrieve the color space selected into a DC
GetColorSpace() is used. To get the logical definition or characterization file GetLogColorSpace() is
your friend. This is very similar to the object manipulation of SelectObject, DeleteObject, and GetObject
for other GDI objects. For validation reasons separate APIs have replaced the object calls. One of the
advantages of objects, knowing their lifetime, is important when caching color transforms.

There are three standard gamut matching methods supported in profiles: maintaining saturation,
maintaining contrast, and colorimetric. For business charts and a lot of computer generated presentations
saturation should be preserved when the requested color is out of gamut. Colorimetric matching is
important when named colors, such as Pantone®, are wanted. Maintaining contrast allows for the best
perceptual match between devices, the entire gamuts are smershed around so that the destination white
point is used and there are a minimum of many to one color mappings. This is best for photographic
images.

To determine if colors are within the gamut of a device, CheckColorsInGamut() is the API of choice. For
example a user could be creating an image on the screen, which allows for a larger gamut than printers.
Before the user prints the image the application can provide a service that shows what colors will not
reproduce exactly when printed. The user can then select other colors that will print.

To do color preview of, say, a print job on the screen, ColorMatchToTarget() is provided. A DC for the
target device is used in an intermediate step in the color transformation pipeline. First the image is
transformed into the target's color space, with appropriate gamut matching. Then that output is
transformed, and displayed, on the preview device. This call cannot be nested.

Although GDI will attempt to manage profiles on behalf of the application, there are limitations. For
example GDI will not be able to track all device configurations that might affect characterization. For this
reason applications will be able to enumerate all profiles that could be used on a device with a given
subsetted configuration with EnumICMProfiles(). This enumerates profiles by attributes and filename of
profile with those attributes. EnumICMProfilesProc() is the associated callback routine.
GetColorProfile() returns the filename of the current profile GDI is using for image color matching for a
given DC. SetColorProfile() allows an application to set a profile for the destination device.

UpdateICMRegKey() reads and writes the registry keys that control the matching of ICC profiles to
color matching DLL’s and output devices. UpdateICMRegKey() allows for the installation and
deinstallation of ICC profiles and for the querying of printer profiles to match device settings.

Color Profiles
Color profiles are referred to as device characterizations, and also as characterization tables, throughout
this document. The ICC color profile format is used. The ICC color profile format is described in a
separate document. Windows 95 ships characterization information for some of the best selling printers
for coated paper. It is also expected that IHV's that presently have color expertise will put screen and
scanner color matching support into their drivers.

Image Color Matching DLL


Windows 95 uses licensed code.

Microsoft Confidential
12
Gamut Matching
Win32 supports 3 different types of gamut matching, also called rendering intents, these methods follow
the ICC spec. The first is colorimetric. The color is to be reproduced as physcometrically accurate as
possible. This is used mostly for spot colors and named color. Colors out of gamut get sent to the surface
of the gamut, but colors in gamut do not move. The second is termed photographic matching. The image
as a whole has to look good. So what happens in practice is that the contrast is preserved. The causes
colors outside and inside the gamut to move. The last is saturation or business graphics. The user is
printing bar charts and stuff like that and wants vivid colors. The ICC profiles can have up to these three
gamut matching methods in them, but they may have less. It could happen that a profile only has
photographic gamut matching. 7 It is fully expected that applications would mix objects with different
rendering intents on the same page. For example the company logo could use colorimetric intent, a bar
chart would use business intent, text would have no color matching, and a picture would use photographic
intent. The intent wanted is part of the LogColorSpace 8.

Enhanced Metafiles
All color matching API’s added are Win32 API’s, and none of these API’s are exposed to 16 bit
applications, and so none of these API’s get recorded into 16 bit metafiles. The color matching API’s are
recorded only into Enhanced Metafiles. Enhanced Metafiles are an interesting philosophical mixture of
device independence and device dependence. The image recorded in an enhanced metafile is able to be
displayed on any printer or monitor (which is the device independent part) with very good fidelity to the
original, as the original would look on the original machine on the target surface (which is the device
dependent part). For example the pixel width of glyphs varies as the resolution of the output device varies.
(A 10 point ‘W’ might have a pixel width of 21 at 600 DPI, and 10 at 300 DPI) The text must be relayed
out, the original placement of the glyphs are preserved without regards to aesthetics. We are therefore led
to two different ways to support color matching in Enhanced Metafiles. 1) Enhanced Metafiles could have
their own color characterization, all colors would be transformed to that color space before being recorded.
At playback time the Enhanced Metafile color characterization would be set as the LogColorSpace. This
would give a better match to the way the Enhanced Metafile would look on the original target. 2) Do no
color matching of the records in the Enhanced Metafile; do record the relevant color matching API’s. At
playback time the color matching is done between recorded LogColorSpaces and the output device. This is
probably more what the user expects. Also because there are fewer color transformations the colors match
better the original scanned image. The color matching API's that are device independent and therefore
metafileable are:

SetICMMode
CreateColorSpace
DeleteColorSpace
SetColorSpace.

The following API's are not recorded in enhanced metafiles:

GetColorSpace
GetLogColorSpace
CheckColorsInGamut
ColorMatchToTarget
GetColorProfile
SetColorProfile
EnumICMProfiles
EnumICMProfilesProc
7 As is the case for the printer profiles that ship with Windows 95. Other than looking into the profile
directly there is no way for an application to determine what gamut matching methods are supported. If a
color matching DLL gets a gamut request it cannot satisfy it can use one that it can.
8 Conceptually it’s a little muddy to put rendering intent on the input side of things, but it works.

Microsoft Confidential
13
UpdateICMRegKey
GetDisplayGammaRamp
SetDisplayGammaRamp

LogColorSpaces can point to an ICC profile to be used instead of the CIEXYZ information in the
structure. This profile does not get embedded in the enhanced metafile. This is similar to the way fonts are
handled in enhanced metafiles, TrueType files are not embedded by the system into enhanced metafiles.
This might be handled differently in a future version of Windows.
DIBs and device independent color
A new bitmap header has been defined for Windows 95. This allows applications to keep color definitions
with the DIB. It is an extension of the BITMAPINFOHEADER. The masks which follow the
BITMAPINFOHEADER are part of the BITMAPV4HEADER. An alpha mask has also been added. After
that is a field, bV4CSType that denotes if the pixels in the DIB are RGB or CMYK. Then the CIEXYZ of
the primaries are given, and then the Gammas.

typedef struct {
DWORD bV4Size;
LONG bV4Width;
LONG bV4Height;
WORD bV4Planes;
WORD bV4BitCount;
DWORD bV4V4Compression;
DWORD bV4SizeImage;
LONG bV4XPelsPerMeter;
LONG bV4YPelsPerMeter;
DWORD bV4ClrUsed;
DWORD bV4ClrImportant;
DWORD bV4RedMask;
DWORD bV4GreenMask;
DWORD bV4BlueMask;
DWORD bV4AlphaMask;
DWORD bV4CSType;
CIEXYZTRIPLE bV4Endpoints;
DWORD bV4GammaRed;
DWORD bV4GammaGreen;
DWORD bV4GammaBlue;
} BITMAPV4HEADER, FAR *LPBITMAPV4HEADER, *PBITMAPV4HEADER;

The values for bV4CSType are the following:

Constant Meaning

CS_DEVICE_RGB RGB's are to be interpreted as device RGB's.


In effect this implies no color matching is to
be done.
CS_DEVICE_CMYK RGB's are to be interpreted as device CMYK.
No translation of these values are allowed.
The CIEXYZTriplet is ignored in this case.
CS_CALIBRATED_RGB The given CIEXYZTriplet defines the
endpoints of the RGB's.

There is no corresponding structure to either the BITMAPINFO or BITMAPCOREINFO. In fact those


structures should never be used. The correct way to get to the bits that follow the header is to use the first
field of the structure that has the size. Add the size to the start of the bitmap header to get to the bits. This
will work for all past and future bitmap header versions. (Some API parameters may need a cast here or
there due to this, but it’s the right thing to do.

Microsoft Confidential
14
In Windows 95 the only color field GDI or drivers look at is the bV4CSType. The rest of the color fields
are ignored by GDI, they are for application use only.

There is no way to embed an ICC color profile into a DIB. It is expected that applications that wish to
carry ICC profiles with bitmaps will use the TIFF format. TIFF has been expanded with a tag for ICC
color profiles.

For DIBs that do not have the BITMAPV4HEADER, which means all current DIBs, it is recommended
that the color space for the NEC 4FG be used. These values are *****.

Tracking installed ICC profiles


As mentioned in the Background section Windows attempts to find the best ICC to match the setup of the
printer. Some of the variables are manufacturer, model, paper, dither, resolution, viewing conditions, line
angle, and line frequency. Many of these variables the user actually sets in the printer setup dialog, and
these settings are communicated back to GDI through the DevMode. In particular the paper, dither, and
resolution of the device are public fields of the DevMode in Windows 95. The manufacturer and model are
retrieved from the driver through DeviceCapabilities 9. Two new indices have been added,
DC_ICC_MANUFACTURER (23) and DC_ICC_MODEL (24). These return the DWORD of interest, and
0 if not implemented. (These are interpreted as 4 byte strings, so they are returned big-endian.) If the
driver does not return this information through DeviceCapabilities then GDI derives a set through the
(unfriendly) printer name. All other variables are ignored.

The ICM branch in the registry10 is under the key


\\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ICM.

The ICM key can have two values. 1) ICMInitialized. This is set at first boot after GDI populates this
branch by reading all files in the color directory and attempting to install all of them as ICC profiles.
Deleting this value causes GDI to delete the ICM branch and reinstall all profiles in the color directory
again. If any profiles on the net had been installed they get lost. 2) SubstList. This is an array of pairs of
pairs of manufacturer and model idents. Something like HP 7F5DHP F674HP B08EHP F674,
the way this gets used will be discussed in a bit.

The ICM key has the following subkeys:

\ICM\ICMatchers - color matcher ID to color matcher DLL file names


\mntr - monitor profiles reside here in comfort
\ptrt - printer profiles reside here in splendor
\scnr - scanner profiles reside here in poverty
\link - read the ICC spec
\spac - read the ICC spec
\abst - read the ICC spec

The last three keys are not used by GDI to find matching profiles for output devices. There is no
substructure for these keys, they contain the names of profiles only. The scnr key has the substructure of
manufacturer and model. The names of the profiles are in the model key. Windows installs profile names
here but does not look in the key for any reason

The mntr key is structured by manufacturer and model idents. If the manufacturer is none then there is no
model subkey. So for example one might have

9 In an earlier version of this spec the manufacturer and model were passed through the DevMode. This
has changed. The right way to have done this was through the GDIINFO structure, maybe next version.
10 To see this yourself install either the Canon BJC-800, Canon BJC-600, or Epson Color Stylus printers
and look at the registry using RegEdit. The ICC profiles are installed when the printer is installed. Other
profiles may not yet have complete information in them.

Microsoft Confidential
15
\mntr\NEC \4FG \profile00 = c:\windows\system\color\nec.icm
\profile01 = c:\windows\system\color\nec1.icm
\5FG \profile00 = c:\windows\system\color\nec5fg.icm
\HITA\34YU\profile00 = c:\windows\system\color\hitachi.icm
\none\profile00 = c:\windows\system\color\mnebu18.icm
\profile01 = c:\windows\system\color\mnebu21.icm

The \prtr key has more subkeys in order to track more printing variables. The subkeys, in order, are
manufacturer, model, media, dither, and resolution. So the key might look something like

\prtr\EPSO\788D\107\ErrorDiffusion\00360x00360\profile00=epsonsty.icm
\HP \7645\MediaUnknown\DitherUnknown\ResolutionUnknown\profile00=hp.icm

These entries get built from information in the ICC profiles when they are installed. Let us go through the
process quickly. The profile is opened and memory mapped in. First the class of the profile is read, this
determines what kind of device the profile is for, such as prtr or link. Let us assume for the rest of this
discussion that a prtr is being installed. This key is created. The 4 byte deviceManufacturer field is then
read, and a key created for it. A value is added to this key which is the text equivalent of this key, e.g.
ManufacturerTag = Epson, this string is also pulled from the profile. The 4 byte deviceModel field is read,
a key created for it, and the text string corresponding added as a value, e.g. ModelTag = Color Stylus, this
string is also pulled from the profile. The 4 byte MS01 tag 11 is read which tells the media type. ( We will
return shortly to where this value, and others, comes from.) For standard media types the corresponding
name is used, else a text string for the value is used. A key is created for it, but no values are added. If this
tag does not exist the default is MediaUnkown. The 4 byte MS02 tag is read which tells the dither type.
For standard dither types the corresponding name is used, else a text string for the value is used. A key is
created for it, but no values are added. If this tag does not exist the default is DitherUnknown. The 8 byte
MS03 tag is read which tells the X and Y resolution in pixels per inch. A key is created for it. If this tag
does not exist the default is ResolutionUnknown. Finally the name of the ICC profile is added as a value
of the kind profileXX=profilename.icm. Of course profiles could exist that match in these tags and yet
differ in additional tags, such as lighting conditions or line frequency. This is why one might expect
multiple profiles at the end of the chain. There might be one more value here as well, default=profileXX,
in the case of multiple profiles this is the one GDI should pick to match.

Let’s work from the other end, again let’s use a printer as the example. GDI has an hDC to try to find a
matching ICC color profile. GDI opens the ICM\prtr key. GDI calls DeviceCapabilities to retrieve the 4
byte manufacturer ident and 4 byte model ident. (Let us assume that these exist, we will return shortly to
the case it doesn’t.) GDI attempts to open the manufacturer key and then the model key as a subkey of the
manufacturer key. If these keys do not exist then the substitution list mentioned above is searched. It is
arranged as pairs of pairs. The first pair is the pair to search for. The second pair is the replacement. So
for example the HP DeskJet 550C and 560C can use the same ICC color profile, and the substitution list
gives us a way to do so. If the substitution list in the ICM branch of the registry does not get a match then
there is an internal substitution list in GDI that gets searched. If there are no substitutions for the
manufacturere/model pair there is no match and GDI fails the find. If they do exist then GDI looks in the
DevMode for dmMediaType and tries to open the associated key as a subkey of the model key. If the key
does not exist GDI does an EnumRegValues to find any media type, and opens the first key enum’ed. GDI
then looks in the DevMode for dmDitherType and tries to open the associated key as a subkey of the media
key. If the key does not exist GDI does an EnumRegValues to find any dither type, and opens the first key
enum’ed. GDI then looks in the DevMode for dmResolution and tries to open the associated key as a
subkey of the dither key. If the key does not exist GDI does an EnumRegValues to find any resolution, and
opens the first key enum’ed. Now we are at the level where profiles names are stored. GDI first looks for
the “default” value, if that doesn’t exist it starts looking for values of the form profile00 to profile99. GDI
uses the first profile it finds.

11 These MSXX tags are private tags in the ICC sense. Unfortunately there were no public keys to give
this information at the time the code was written.

Microsoft Confidential
16
Now things aren’t quite so serendipitous as it seems for the matches between the values in the DevMode
and the values in the ICC profile. Printers are not characterized independently of a driver, after all the
driver is needed to tell the printer to put ink on the page. If one is characterizing a printer to be used with
Windows then one has to be using a Windows printer driver. (PostScript devices might be excluded from
this discussion, since one can characterize them independently of Windows.) If one is using a Windows
printer driver then one has access to the relevant values and can construct the ICC profile correctly.

One could make the argument that picking a profile that doesn’t match media, dither, or resolution is the
wrong thing to do, but that’s the decision that was made.

If the driver does not return the manufacturer and model to the DeviceCapabilities call then GDI
constructs these form the (unfriendly) printer name. The first four letters become the manufacturer ident.
Spaces and hyphens turn to spaces and then spaces are used to fill after if necessary. A CRC is applied to
the whole name to get the model ident. The CRC is given by

WORD wCRC16a[16]={
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
WORD wCRC16b[16]={
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};

void Get_CRC_CheckSum(PVOID pBuffer, ULONG ulSize, PULONG pulSeed)


{
PBYTE pb;
BYTE bTmp;

for (pb=(BYTE *)pBuffer; ulSize; ulSize--, pb++)


{
bTmp=(BYTE)(((WORD)*pb)^((WORD)*pulSeed)); // Xor CRC with new char
*pulSeed=((*pulSeed)>>8) ^ wCRC16a[bTmp&0x0F] ^ wCRC16b[bTmp>>4];
}
}

A list of all printers supported by Windows 95 was used to generate idents; this list is the one the ICC uses
to assign idents, so if profile makers follow the ICC spec and accompanying docs then this all works.

For monitors this isn’t quite so easy since monitors are decoupled from drivers. Drivers know all about the
display adapter, but nothing from the monitor attached to the adapter. However two items in Windows 95
help GDI identify the monitor, Plug and Play monitors and the display settings. In the control panel applet
for display settings (which can be brought up just by right clicking on the desktop) the user can specify the
monitor 12. Plug and Play monitors return an EDID, which has lots of information, such as frequencies,
manufacturer and model idents, chromaticities and gammas. In Windows 95 GDI ignores the
chromaticities and gammas and does not use them in color matching, this should be fixed in the next
version.

12 Knowing the monitor allows Windows to determine what resolutions it supports in order not to present,
in the display settings applet, the user with resolutions that the adapter can do but the monitor cannot.

Microsoft Confidential
17
The default is the ICC profile for the NEC 4FG monitor. The search path starts at the registry driver
section for the monitor. We see if we have already determined a profile for the monitor, the value
ICMProfile is the value we are looking for. This can have either one of two meanings. 1) It gives us the
name of a profile to use. In this case if the profile still exists or/and is accessible (think of the net case)
then we are done. 2) This is an index (1 based) into the set of generic monitor profiles shipped in the box.
This set in order, is:

char *DispProfs[] =
{"mnB22G15.icm",
"mnB22G18.icm",
"mnB22G21.icm",
"mnEBUG15.icm",
"mnEBUG18.icm",
"mnEBUG21.icm",
"mnP22G15.icm",
"mnP22G18.icm",
"mnP22G21.icm"};

The first two letters, ‘mn’, of the name means the profile is for a monitor. The next three letters give the
phosphor set. The last two numbers give the gamma.

Monitors.inf has some default values for some monitors which get set at setup time. Or third party utilities
can pick a different default. This index is used as a fallback, we still check to see if there are more robust
methods of determining which profile to use. Note that GDI does not set a value for ICMProfile, basically
due to paranoia. GDI does not wan t to deal with the different scenarios of profiles coming and going. In
the future perhaps. For now it is up to third party utilities which construct or provide great profiles to set
this to the name of the great profile. Now we look for the EDID. If we find the EDID, we pull out the
manufacturer and model idents and look in the registry, If we have a match we are done. If no EDID
section we see if the user specified the monitor with the display settings applet. We use the same technique
to derive idents as for printers. If the user did then we check the registry. If no find in the registry we look
at the substitution lists. If not there it is time to use the default.

Device Characterization Utilities


Due to drifts in devices, changing viewing conditions, etc., the characterization of devices changes. When
this spec was first written it was expected that third parties will supply tools to create and update profiles.
This expectation will be met. Due to the success of the ICC in creating a platform neutral characterization
everybody will be supporting this format. All profile tool makers will be supporting the ICC format. There
will be easy to use tools for monitors and scanners. Profiles will be kept in a color directory below the
Windows system directory. Calibration utilities need to copy new profiles to the directory and then call
UpdateICMRegKey() for GDI to find them. To change a profile the current profile should be deleted and
then the new one installed.

Some 24 (and higher) bit display adapters allow for the downloading of a gamma ramp for hardware
gamma correction. We have added a new set of APIs to support this, GetDisplayGammaRamp() and
SetDisplayGammaRamp(). The hardware gamma ramp is a global property, it affects all running
applications, it is not changed on a per DC basis.
Support for multiple color matching DLL’s
Windows 95 allows multiple color matching DLL’s to be installed at the same time. (Windows 95 does not
allow for the replacement of the system supplied color matching DLL.) GDI uses the ICC profile for the
destination device to determine which DLL to use. There is a field in the header of an ICC profile that
denotes the manufacturer of the profile. GDI looks in the registry to match this tag to the name of the DLL
to use. (UpdateICMRegKey() is used to write this registry key.) The DLL is loaded and queried for its
manufacturer ident. This tag must match the field in the ICC profile. If the given color matching DLL
does not exist, or the manufacturer idents do not match, then the system color matcher is used.

Microsoft Confidential
18
RGB
RGB GDI RGB' Device
App Device
CMYK CMYK Driver
CMYK'

Log
Colorspace
ICC Profile
CMMType
=
KCMS

System Third Fourth


Kodak Party Party
ICM ICM ICM

IDENT = KCMS IDENT = ASDF IDENT = ZXCV

Writing an Image Color Matcher DLL


An installable ICMDLL is a 32-bit Windows DLL. Under Windows 95 it will run as flat 32-bit code. It
must be re-entrant. It is assumed the reader knows how to write a DLL.

RGB
RGB GDI RGB' Device
App Device
CMYK CMYK Driver
CMYK'

Log
Colorspace
ICC Profile

CMGetInfo
CMCreateTransform CMTranslateRGB
CMDeleteTransform CMTranslateRGBs
CMCheckColorsInGamut

Generic
Image Color
Matcher

The set of functionality that GDI depends on is small. Basically the ICMDLL constructs transforms and
GDI calls to the ICMDLL to apply those transforms. GDI creates and destroys new transforms when the

Microsoft Confidential
19
device characterization changes or the application color space changes. The lifetime of a transform is
controlled by the application, an application can create a color space and keep it around for its lifetime. Or
it can create a color space just when proofing needs to be done.

The ICMDLL does all of its own memory management, GDI does no allocations on behalf of the ICM.

The ICMDLL is not allowed to export any other functionality to applications.

Writing a Device Driver to Implement Image Color Matching


The architecture of image color matching requires device drivers to only update for the DevMode
additions to report the printing process more accurately. They do not need to transform RGBQuads from
one color space to another. All color matching can be done independently of the device driver. However
there are a few reasons why device drivers may wish to be updated to support some ICM functionality.
These reasons have to do with memory, performance, and the quality of the image produced. Memory:
when doing a color translation on a DIB a translated copy of that DIB is made before passing it to the
device driver. DIBs can be quite large, especially those generated for 1200 DPI devices. This could cause a
wee bit of paging. We allow device drivers to use the ICMDLL as support to do the translation in bands.
Performance: Some device drivers could download the transforms to the printer to allow for the color
correction to be done on the printer instead of the host. This allows for quicker return to app time.
Quality: Note that for some devices the characterization of the device is not just of the device, but of the
driver/device pair. This is generally the case of inkjets. To get good looking output the driver does a lot of
sophisticated processing to make up for simple hardware. These devices are therefore hard to characterize.
The driver knows more about the device than an independent color matcher could. In this case the driver
should do the translation directly from the incoming logical color space to device coordinates without the
intervention of a third party image color matcher.

In some of these cases note that the driver must see the CMCreateTransform call before any installed ICM
does. The details of these interactions, and how drivers should implement the various levels of support, we
now discuss in pedantic detail.

The image color matching interface to device drivers is the same as to ICMDLLs. The driver implements
a subset of the ICM interface depending on the level of support it is providing. The device sets the
C1_ICM bit in dpCaps1 in the gdiinfo block if any level of support is implemented. The driver informs
GDI of the level of support it is providing through CMGetInfo. For those drivers that wish to integrate
well with ICMDLLs there is a callback through GDI to the ICMDLL. Please see the diagram below.
Because the ICM interface to device drivers is the same as for ICMDLLs the arguments to the callback
calls are identical to the original call to the device. GDI simply routes it to the correct ICMDLL. Device
drivers cannot call directly to the ICMDLL because there is no way for it to distinguish between multiple
ICMDLLs in the system and because the ICMDLL lives on the 32-bit side of the GDI fence. The GDI
callback names are the ICM calls with a prepended 'I'. The diagram below shows the interaction for one
specific all, CMTranslateRGB(). GDI calls the device drivers entry point for CMTranslateRGB. The
device driver can call ICMTranslateRGB() in GDI. GDI then calls the appropriate ICMDLL on behalf of
the device driver, and then returns the results to the device driver.

Microsoft Confidential
20
RGB
RGB GDI RGB' Device
App Device
CMYK CMYK Driver
CMYK'

CMTranslateRGB

ICMCreateTransform
Log
Colorspace
ICC Profile

ColorQuad ColorQuad'
hcmTransform

ICM

The first level of support is a simple and straightforward interaction in implementation. It is not the
suggested level device drivers should implement. In fact it is mostly useful as a basis which to discuss
levels 2 and 3. In this simple case the driver implements the complete ICM interface. GDI treats it like an
ICMDLL. Please see the diagram below. Instead of GDI calling an ICMDLL to transform RGBs or DIBs
before passing them to the device driver, GDI calls the device drivers to transform RGBs or DIBs before
passing them to the device driver. Obviously the major drawback of this approach is that it does not
integrate the ICM functionality intelligently into the device driver, neither the memory or performance
problems are solved. It is not expected that many device drivers will take this approach.

RGB
RGB GDI RGB' Device
App Device
CMYK CMYK Driver
CMYK'

CMCreateTransform
CMDeleteTransform
CMGetInfo
CMTranslateRGB
CMTranslateRGBs
CMCheckColorsInGamut
Log
Colorspace
ICC Profile

The second level of support is for device drivers that do not wish to implement their own color matching,
but wish to ameliorate the memory hit of a copy of the original bitmap being made to store the color
corrected bitmap. These devices will do banding of the color translation of a DIB. Please see the diagram
below. The device driver relies on an ICMDLL for all calls except for DIBits, StretchDIB, and
DIBToDevice. GDI does not call the ICMDLL to translate DIBs before calling the device driver. When the

Microsoft Confidential
21
device driver gets the DIB it calls through ICMTranslateRGBs to the ICMDLL to eat the DIB. It is up to
the device driver to setup the arguments correctly for this call. The hcmTransform to be used is stored in
the Windows 95 DrawMode in the hcmTransform field.

RGB
RGB GDI RGB'
App Device Device
CMYK CMYK Driver
CMYK'
DIBBits
StretchDIB
DIBtoDevice
ICMTranslateRGBs
Log hcmTransform
Colorspace
ICC Profile

CMCreateTransform CMTranslateRGB
CMDeleteTransform
CMCheckColorsInGamut

ICM

The third and last level of support is complete integration of image color matching supported by the
device driver. It is the suggested level for device drivers that implement their own image color matching
code. Please see the next diagram. The driver supports CMCreateTransform(), CMDeleteTransform(), and
CMCheckColorsInGamut() directly. The color translations are done in the calls that take colorquads:
RealizeObject() for pens and brushes and ColorInfo() for all the rest. The DIB calls are handled in the
same as in level 2, the hcmTransform is added to the DrawMode. The LogPen and LogBrush structures
have been extended to include the hcmTransform to be used. Please see the section on structures changed
to support color matching. The role the DDI ColorInfo() plays in color communication across the DDI has
been subtly ignored so far. The lines in the diagrams above from GDI to the device driver labeled RGB
and CMYK go to ColorInfo for everything except pens, brushes, and DIBs. All the rest of the DDI take
physical colors, Pixel, foreground color, background color, scanline, etc. GDI first calls ColorInfo to
convert a logical color into a physical color. For example in SetPixel(x, y, RGB) GDI calls ColorInfo() on
the RBG argument to get a physical color, and then immediately calls Pixel() with that physical color.
When an ICMDLL is used to translate colors GDI calls the ICMDLL CMTranslateRGB() immediately
before calling ColorInfo(). It would make more sense with a device driver to merge the calls together. A
new ICMColorInfo() has been defined that takes as a new parameter hcmTransform. Level 3 support
requires the device driver to implement this DDI.

Microsoft Confidential
22
RGB GDI RGB Device
App Device
CMYK CMYK Driver
ColorInfoEx
CreatePen
CreateBrush
hcmTransform

CMCreateTransform
CMDeleteTransform

Log CMCheckColorsInGamut
Colorspace
ICC Profile

ICM
DLL

Notice that for all of these cases whether ICM is turned on or off on any particular call is up to the
application. By the simple expedient of calling SetICMMode(hDC, uiEnableICM) applications can turn
on and off image color matching. If image color matching is off for a printer DC, GDI does the
appropriate thing. In level 1 GDI will not call the ICM routines in the printer. In level 2 the
hcmTransform in the DrawMode will be zero if no image color matching is to be done. In level three
either the new DDI's will not be called or the hcmTransform will be zero. What about the ICM button in
the Printer Setup Dialog? For non-ICM aware applications this tells GDI to SetICMMode for the printer
DC. ICM aware applications should use this information (returned in the DevMode) appropriately; but it
is up to the application to control the images it produces.

A note about 8-bit display adapters


There are some behaviors on 8-bit display adapters that although appear somewhat strange are expected.
The first is the dithering of brushes created with ‘straight’ RGB’s. On an 8-bit display this brushes are
produced as if there were on a 4-bit display. The RGB requested is produced by dithering the static 16
colors. But the monitor profiles are produced for 24-bit display adapters, and so using dithered brushes
with color matching enabled is wrong. Use palette relative RGB’s instead. The second effect is due to the
fact that there is just one hardware palette. It’s not just logical palettes that share the hardware palette, a
color matched palette is a separate palette that must be matched to the hardware palette. So if an
application has selected a palette into a DC, drawn using that palette and then enables ICM the previous
colors used in drawing are now invalid. This also produces palette flash. All drawing to a DC using
palettes should use a single ICM mode, either on or off.

Microsoft Confidential
23
API, flags, #defines, and structures
Flags
// values for CMGetInfo()

typedef UINT INFOFLAGS;


#define CMS_GET_VERSION 0x00000000
#define CMS_GET_IDENT 0x00000001
#define CMS_GET_DRIVER_LEVEL 0x00000002
#define CMS_GET_RESERVED 0xFFFFFFFC

typedef UINT CMS_DRIVER_LEVEL;


#define CMS_LEVEL_1 0x00000001
#define CMS_LEVEL_2 0x00000002
#define CMS_LEVEL_3 0x00000004
#define CMS_LEVEL_RESERVED 0xFFFFFFFC

// flags for CMTranslateRGB(s)


typedef UINT DIRECTIONFLAG;
#define CMS_FORWARD 0x00000000
#define CMS_BACKWARD 0x00000001

typedef UINT TRANSLATEFLAGS;


#define CMS_x555WORD 0x00000000
#define CMS_565WORD 0x00000001
#define CMS_RGBTRIPLETS 0x00000002
#define CMS_BGRTRIPLETS 0x00000004
#define CMS_XRGBQUADS 0x00000008
#define CMS_XBGRQUADS 0x00000010
#define CMS_QUADS 0x00000020

// flags for LogColorSpace

typedef UINT LCSIDENT

#define LCS_CALIBRATED_RGB0x00000000
#define LCS_DEVICE_RGB 0x00000001
#define LCS_DEVICE_CMYK 0x00000002

typedef UINT LCSGAMUTMATCH

#define LCS_GM_BUSINESS 0x00000001


#define LCS_GM_GRAPHICS 0x00000002
#define LCS_GM_IMAGES 0x00000004

// values for UpdateICMRegKey()

#define ICM_ADDPROFILE 0x00000001


#define ICM_DELETEPROFILE 0x00000002
#define ICM_QUERYPROFILE 0x00000003
#define ICM_SETDEFAULTPROFILE 0x00000004
#define ICM_REGISTERICMATCHER 0x00000005
#define ICM_UNREGISTERICMATCHER 0x00000006
#define ICM_QUERYMATCH 0x00000007

Microsoft Confidential
24
#define's
typedef HANDLE LCOLORSPACE;
typedef long FXPT16DOT16, FAR* LPFXPT16DOT16; // Fixed point 16.16
typedef long FXPT2DOT30, FAR* LPFXPT2DOT30; // Fixed point 2.30

Structures
Added color definitions:

typedef struct tagCIEXYZ


{
FXPT2DOT30 ciexyzX;
FXPT2DOT30 ciexyzY;
FXPT2DOT30 ciexyzZ;
} CIEXYZ;
typedef CIEXYZ FAR* LPCIEXYZ;

typedef struct tagCIEXYZTRIPLE


{
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
} CIEXYZTRIPLE;
typedef CIEXYZTRIPLE FAR* LPCIEXYZTRIPLE;

LOGCOLORSPACE

Logical Color Sapce Information

The LOGCOLORSPACE data structure defines a logical color space.

typedef struct tagLOGCOLORSPACE


{
DWORD lcsSignature;
DWORD lcsVersion;
DWORD lcsSize;
LCSCSTYPE lcsCSType;
LCSGAMUTMATCH lcsIntent;
CIEXYZTRIPLE lcsEndpoints; // Fixed point 2.30
DWORD lcsGammaRed; // Fixed point 16.16
DWORD lcsGammaGreen; // Fixed point 16.16
DWORD lcsGammaBlue; // Fixed point 16.16
char lcsFilename[MAX_PATH];
} LOGCOLORSPACE;
typedef LOGCOLORSPACE FAR* LPLOGCOLORSPACE;

The LOGCOLORSPACE structure has the following fields:

Field Description
lcsSignature Identifier for this structure,‘PSOC’.
lcsVersion Specifies the Windows version number for the structure (currently 0x400).
lcsSize Specifies the size of this structure, which is version specific.
lcsCSType Specifies the type of color space to set. It can have the following meanings:

Constant Meaning

Microsoft Confidential
25
LCS_DEVICE_RGB RGBQuads defined in API's are to be
interpreted as device RGB's. In effect this
turns color matching off.
LCS_DEVICE_CMYK RGBQuads defined in API's are to be
interpreted as device CMYK. No translation
of these values are allowed. The remainder
of the structure is ignored in this case.
LCS_CALIBRATED_RGB The given CIEXYZTriplet defines the
endpoints of the RGB's used in all API's.

lcsIntent Specifies the gamut matching method wanted. It can have the following
meanings:

Constant Meaning

LCS_GM_BUSINESS Maintain saturation. Used for business charts


and the like.
LCS_GM_GRAPHICS Colormetric match. Used for graphic designs
and named colors.
LCS_GM_IMAGES Maintain contrast. Used for photographs and
natural images.

LcsEndpoints Definition of the RGB endpoints in CIEXYZ space. Values are fixed pt 2.30
lcsGammaRed The scale of the red coordinate. It is fixed point, 16.16.
lcsGammaGreen The scale of the green coordinate. It is fixed point, 16.16.
lcsGammaBlue The scale of the blue coordinate. It is fixed point, 16.16.
lcsFilename NOT REQUIRED. Under certain limited circumstances an application may
wish to pass in a device profile for the source color space. For example the
scanner used might only output device CMYK's for a specific printer. Instead
of forcing an application to transform to calibrated RGB and then to another
device space, which leads to artifacts because 8 bits just can't stand the
strain, the characterization of the scanner can be passed in. Or a third party
color matcher might require a profile. The rest of the structure should be
filled in if at all possible, although it may not be 100% accurate.

Application APIs
The functions added are:

SetICMMode allows app to force color matching


CreateColorSpace creates a logical color space
DeleteColorSpace deletes a color space created with CreateColorSpace
SetColorSpace defines the endpoints of the logical RGB space in the CIEXYZ space
GetColorSpace gets the handle of the color space currently set into a DC
GetLogColorSpace gets the LogColorSpace associated with the handle to that color space
CheckColorsInGamut determines if the specified colors are in the gamut of the device
ColorMatchToTarget does preview matching
GetColorProfile retrieves the current color profile for the given DC
SetColorProfile sets the color profile for the given DC
EnumICMProfiles enumerates the different color profiles available on the given DC
EnumICMProfilesProc callback for above
UpdateICMRegKey manages the registry entries that match profiles to devices
GetDisplayGammaRamp retrieves the gamma ramp for 24 (and higher) bit displays
SetDisplayGammaRamp sets the gamma ramp for 24 (and higher) bit displays

Microsoft Confidential
26
Microsoft Confidential
27
SetICMMode
int WINAPI SetICMMode(hDC, iEnableICM)

HDC hdc; /* handle of device context */


int iEnableICM; /* turns image color matching on and off */

The SetICMMode function causes image color matching to be enabled, disabled, or queried on the given
DC.

Parameter Description

hdc Identifies the device context.


IEnableICM Can have one of the following meanings:
Constant Meaning

ICM_ON Turns color matching on.


ICM_OFF Turns color matching off.
ICM_QUERY Queries the current state of color matching.

Returns

The return value is non-zero if the function is successful. Otherwise, it is zero.


If ICM_QUERY is specified, the function returns ICM_ON or ICM_OFF to indicate current mode if
successful.

Comments

If GDI cannot find an ICC color profile to match the state of the device then this function fails.

CreateColorSpace
HCOLORSPACE WINAPI CreateColorSpace(lpLogColorSpace)

LPLOGCOLORSPACE lpLogColorSpace; /* pointer to LOGCOLORSPACE data structure */

The CreateColorSpace function creates a logical color space.

Parameter Description

lpLogColorSpace Points to the LOGCOLORSPACE data structure.

Returns

If the function is successful, the return value is a handle that identifies a logical color space. Otherwise, it
is NULL.

Microsoft Confidential
28
SetColorSpace
HCOLORSPACE WINAPI SetColorSpace(hdc, hColorSpace)

HDC hdc; /* handle of device context */


HCOLORSPACE hColorSpace /* color space to set */

The SetColorSpace defines the endpoints of the logical RGB space in CIEXYZ space.

Parameter Description

hdc Identifies the device context.


hColorSpace Handle to the logical color space to set.

Returns

The return value is the handle of the hColorSpace being replaced if successful. Otherwise, it is NULL.

GetColorSpace
HCOLORSPACE WINAPI GetColorSpace(hdc)

HDC hdc; /* handle of device context */

The GetColorSpace retrieves the current hLogColorSpace from the given device context.

Parameter Description

hdc Identifies a device context that is to have its hLogColorSpace retrieved.

Returns

The return value is the current hLogColorSpace if the function is successful. Otherwise, it is NULL.

Microsoft Confidential
29
GetLogColorSpace
BOOL WINAPI GetLogColorSpace(hColorSpace, lpBuffer, nSize)

HCOLORSPACE hColorSpace; /* handle of logical color space */


LPVOID lpbuffer; /* pointer to put logical color space */
DWORD nSize; /* size of buffer */

The GetLogColorSpace retrieves the definition of the given handle to a logical color space.

Parameter Description

hColorSpace Handle to LOGCOLORSPACE to retrieve.


lpBuffer Points to buffer that receives the LOGCOLORSPACE.
nSize Specifies the maximum size of the buffer.

Returns

The return value is TRUE if the function is successful. Otherwise, it is FALSE.

Comments

This function will copy as much of the LOGCOLORSPACE to the buffer as space allows. To determine
the correct size of the buffer to use, applications should check the lcsSize value in the structure.

DeleteColorSpace
BOOL WINAPI DeleteColorSpace(hColorSpace)

HCOLORSPACE hColorSpace /* color space to delete */

The DeleteColorSpace removes and destroys the given logical color space.

Parameter Description

hColorSpace Handle to the logical color space to delete.

Returns

The return value is TRUE if successful. Otherwise, it is FALSE.

Microsoft Confidential
30
GetICMProfile
BOOL WINAPI GetICMProfile(hdc, lpcbSizeBuffer, lpBuffer)

HDC hdc; /* handle of device context */


LPDWORD lpcbName; /* pointer to size of buffer */
LPSTR lpszFilename; /* pointer to buffer to store result */

The GetICMProfile function retrieves the current color profile for the specified DC.

Parameter Description

hdc Identifies the device context to retrieve the color profile from.
LpcbName Pointer to DWORD that is the size of the buffer to hold the pathname of the profile.
LpszFilename Pointer to the buffer that receives the pathname of the profile.

Returns

The return value is TRUE if the function succeeds. Otherwise it is FALSE.

SetICMProfile
BOOL WINAPI SetICMProfile(hdc,lpFileName)

HDC hdc; /* handle of device context */


LPSTR lpFileName /* pointer to fully qualified path of profile to use */

The SetICMProfile function sets the color profile as the destination profile for the specified DC. This
must be set before ICM is enabled for the DC.

Parameter Description

hdc Identifies the device context to set the color profile into.
LpFileName Pathname of the color profile to be used as the device profile.

Returns

The return value is non zero, if successful. Otherwise, it is zero.

Microsoft Confidential
31
EnumICMProfiles
int WINAPI EnumICMProfiles(hdc, lpEnumICMProfilesFunc, lParam)

HDC hdc; /* device-context handle */


ICMENUMPROC lpEnumICMProfilesFunc; /* address of callback function */
LPARAM lParam; /* application supplied data */

The EnumICMProfiles function enumerates the different color profiles that the system supports for the
given device context.

Parameter Description

hdc Identifies the device context.


lpICMProfilesFunc Specifies the procedure instance address of the application defined
callback function. See the description of the EnumICMProfilesProc
function.
lParam Application supplied data. The data is passed to the callback function
along with the color profile information.

Returns

A return value of zero specifies the application interrupted the enumeration; -1 specifies that there are no
color profiles to enumerate, or that the system is not enabled for ICM. Otherwise the return is the last
value returned by the callback function.

EnumICMProfilesProc
int CALLBACK EnumICMProfilesProc(lpszFilename, lParam)

LPSTR lpszFilename; /* filename of color profile */


LPARAM lparam; /* application supplied data */

The EnumICMProfilesProc function is an application defined callback function that processes color
profile data from the EnumICMProfiles function.

Parameter Description

LpszFilename Pointer to filename of profile.


lParam Application supplied data passed by EnumICMProfiles.

Returns

This function must return a positive value to continue enumeration; to stop enumeration, it must return
zero. A negative value may not be returned.

Microsoft Confidential
32
CheckColorsInGamut
BOOL WINAPI CheckColorsInGamut(hdc, lpaRGBTriples, lpBuffer, nCount)

HDC hdc; /* handle of device context */


RGBTRIPLE *lpaRGBTriples; /* array of RGB triples to check */
LPBYTE lpBuffer; /* buffer to put results */
UINT nCount; /* count of elements in array */

The CheckColorsInGamut determines if the given set of RGB triples lies in the output gamut of the
given device. The given RGB triples are interpreted in the input logical color space.

Parameter Description

hdc Identifies a device context that is to have the given color space definition.
lpaRGBTriples Pointer to array of RGB triples to check.
lpBuffer Pointer to buffer to put results.
nCount Count of elements in array.

Returns

The return value is TRUE if the function is successful. Otherwise, it is FALSE.

The lpBuffer holds the results, each byte corresponding to an RGB triple is an integer in the range 0 to
255.

Microsoft Confidential
33
ColorMatchToTarget
BOOL WINAPI ColorMatchToTarget(hdc, hdcTarget, uiAction)

HDC hdc; /* handle of device context */


HDC hdcTarget; /* handle of device context of target device */
DWORD uiAction; /* action (e.g. enable/disable) to take */

The ColorMatchToTarget allows for previewing of colors as they would appear on the target device. The
color transform for the target device is first performed, and then the transform to the preview device is
applied to the results of the first transform. This is mostly useful for checking gamut mapping conditions.
The application must have enabled ICM for both DC's.

Parameter Description

hdc Identifies the device context for previewing, generally the screen.
hdcTarget Identifies the target device context, generally a printer.
uiAction Can have one of the following values:

Constant Meaning

CS_ENABLE Color matching is done through the target.


CS_DISABLE Color matching is done in the normal way.
CS_DELETE_TRANSFORM Do a disable if enabled and then delete the
concatenated transform.

Returns

The return value is non zero if the function is successful. Otherwise, it is zero.

Comments

This function cannot be cascaded. While enabled application changes to the color space or gamut
matching method are ignored; those changes take effect when this function is disabled. It is not required
that an application delete transform using CS_DELETE_TRANSFORM. The transform will be deleted
when either of devices are removed from the system, or the application color space is deleted. However if
the transform is not going to be used again, an application can free up the space taken by it.

Microsoft Confidential
34
UpdateICMRegKey
BOOL WINAPI UpdateICMRegKey(uiReserved, CMID, pszFileName, nCommand )

DWORD dwReserved; /* reserved */


LPSTR lpszCMID; /* ident for color matching DLL */
PSTR pszFileName; /* file name of profile */
UINT nCommand; /* function to execute */

The UpdateICMRegKey provides a set of functions to install and deinstall ICC color profiles. It also
manages other aspects of the ICM branch in the registry. Not all parameters are used by all functions. The
function to execute is determined by nCommand.

Parameter Description

dwReserved Reserved, must be set to zero.


lpszCMID Pointer to string that specifies the ICC profile identifier for color matching dll to
use with the profile.
pszFileName Points to a fully qualified ICC color profile file name, or to a DevMode.
nCommand Function to execute. It can have one of the following values:

Constant Meaning

ICM_ADDPROFILE Adds the ICC profile to the ICM branch


in the registry.
ICM_DELETEPROFILE Deletes the ICC profile from the ICM
branch in the registry.
ICM_QUERYPROFILE Determines if the profile is in the ICM
branch of the registry.
ICM_SETDEFAULTPROFILE Makes the profile first among equals.
ICM_REGISTERICMATCHER Equates a CMID to a color matcher DLL.
pszFilename points to fully qualified path
for color matcher DLL.
ICM_UNREGISTERICMATCHER Removes the refererence between CMID
and a color matcher DLL. pszFilename
points to fully qualified path for color
matcher DLL.
ICM_QUERYMATCH Determines if a profile exists based on the
DevMode pointed to by pszFileName.

Returns

The return value is TRUE if the function is successful. Otherwise, it is FALSE.

Comments

GDI uses the registry to keep track of ICC profiles installed in the system. Installed in the system means
the profile is mentioned in the registry. ICC profiles are not limited to the color directory
(\Windows\System\Color), there could be a network location with a bevy (gaggle?) of them there. However
if any are copied to the local drive it is strongly encouraged that they be copied to the color directory.

Microsoft Confidential
35
GetDeviceGammaRamp
BOOL WINAPI GetDeviceGammaRamp(hdc, lpRamp)

HDC hdc; /* device-context handle */


LPARAM lpRamp; /* address of application-supplied data */

The GetDeviceGammaRamp gets the gamma ramp on direct color display boards.

Parameter Description

hdc Identifies the device context.


lpRamp Points to a set of three arrays of 256 word elements. These arrays are the
mapping between RGB values in the frame buffer and DAC values. The
first array is red, the next green, and the final one blue.

Returns

The return value is TRUE if the function is successful. Otherwise, it is FALSE.

Comments

Direct color display modes do not use color lookup tables. The direct color modes are usually 16, 24, or 32
bit. Not all direct color video boards support loadable gamma ramps. This function returns success only
for those drivers that support loadable gamma ramps in hardware.

SetDeviceGammaRamp
BOOL WINAPI SetDeviceGammaRamp(hdc, lpRamp)

HDC hdc; /* device-context handle */


LPARAM lpRamp; /* address of application-supplied data */

The SetDeviceGammaRamp sets the gamma ramp on direct color display boards.

Parameter Description

hdc Identifies the device context.


lpRamp Points to a set of three arrays of 256 word elements. These arrays are the
mapping between RGB values in the frame buffer and DAC values. The
first array is red, the next green, and the final one blue.

Returns

The return value is TRUE if the function is successful. Otherwise, it is FALSE.

Comments

Direct color display modes do not use color lookup tables. The direct color modes are usually 16, 24, or 32
bit. Not all direct color video boards support loadable gamma ramps. This function returns success only
for those drivers that support loadable gamma ramps in hardware.

Microsoft Confidential
36
API for Color Matching DLL
Installable image color matchers are supported under Windows. There can be multiple image color
matchers in the system, and applications will have access to all of them. Please see a previous section on
details.

typedef HANDLE HCMTRANSFORM;


typedef LPVOID LPDEVCHARACTER;
typedef LPVOID LPDEVMODE;
typedef COLORREF FAR *LPCOLORREF;

The functions added are:

CMGetInfo gets various information about the ICM


CMCreateTransform sets up a transform to translate color spaces
CMDeleteTransform deletes transform created with CMCreateTransform
CMTranslateRGB translates a given RGB
CMTranslateRGBs translates an array of RGBs
CMCheckColorsInGamut determines if the given colors are in the specifed gamut

Microsoft Confidential
37
CMGetInfo
ULONG WINAPI CMGetInfo(dwInfo)

UINT dwInfo; /* information to be retrieved */

The CMGetInfo function retrieves various information about the ICM.

Parameter Description

dwInfo Values that can have the following meaning:

Type Meaning

CMS_VERSION Retrieves the version of Windows supported.


CMS_IDENT Retrieves the identifier of the ICMDLL.
CMS_DRIVER_LEVEL Retrieves the support level of a device driver.

Returns

CMGetInfo returns zero if an invalid parameter is passed in. If successful it returns a value that depends
on the information requested.

For CMS_VERSION CMGetInfo retrieves the version of Windows ICM interface supported by this
module. For Windows 95 this should be 4.0, represented as 0x00040000.

For CMS_IDENT CMGetInfo retrieves the identifier of the ICMDLL. This is the same as the ICC color
profile header identifier.

For CMS_DRIVER_LEVEL CMGetInfo retrieves the supported level of the device driver. ICMDLLs
should return CMS_LEVEL_1. The values have been defined in a previous section.

Microsoft Confidential
38
CMCreateTransform
HCMTRANSFORM WINAPI CMCreateTransform(lpColorSpace, lpDevCharacter,
lpTargetDevCharacter)

LPCOLORSPACE lpColorSpace; /* source color space */


LPDEVCHARACTER lpDevCharacter; /* characterization of output device */
LPDEVCHARACTER lpTargetDevCharacter; /* characterization of target output device */

The CMCreateTransform function creates mappings between an application color space and a device
color space. The transform allows for previewing of a target device color transformation on a preview
device, for example one can preview on the screen how a printed image would appear on the target
printer. The lpTargetDevCharacter parameter determines if a straight color transform or a match to target
transform is requested. If lpTargetDevCharacter is null then a straight application to device color
transform is wanted. In this case the ICM should construct two mappings : 1) a mapping from the
application's defined color space to the device's hardware color space, and 2) a mapping from the device's
hardware color space to the application's defined color space. If lpTargetDevCharacter is not null then a
mapping from the application color space to the target device and then to the preview device is wanted.

NOTE For ICMDLLs, which live on the 32-bit side, the parameters are pointers to the files in memory.
GDI32 uses memory mapped files to map the files into memory. The parameters below are pointers.

Parameter Description

lpColorSpace Pointer to application's color space. If lcsFilename is non-zero


then this pointer is to that file's memory mapping 13.
lpDevCharacter Pointer to device color profile.
lpTargetDevCharacter Pointer to target device color profile.

For device drivers, which live on the 16-bit side, the parameters are filenames. It is up to the device driver
to read the file from disk.

Parameter Description

lpColorSpace Pointer to application's color space.


lpDevCharacter Pointer to filename of device color profile.
lpTargetDevCharacter Pointer to filename of target device color profile.

Returns

If the return value is greater than 255 then it is a handle to a color transform. A value less than 255 is an
error return. ERROR_INVALID_PARAMETER denotes that there is an invalid parameter in a color
profile passed in.

Comments

The format of the returned transform is completely undefined, it is specific to the image color matching
DLL. The handle is used when translating specific color values to device color coordinates.

The forward mapping from the application to the device must precomputed at this time, if necessary.
Future calls to CMTranslateRGB and CMTranslateRGBs using the forward transform cannot fail due to
inability to construct the transform. The backward transform can be delay until a request for its use 14. The

13In Windows 95 if lcsFilename is non-zero then it is a filename and not a memory mapped file.
14In Windows 95 the pointers to the memory mapped files are valid only during this function. The
backwards transform must either be computed at the time of the call, or the relevant information from the
ICC must be cached.

Microsoft Confidential
39
backward transformation is used only to support GetPixel() and GetDIBits(). The forward or backward
transform is denoted by a flag passed to CMTranslateRGB(s)().
NOTE: Only the low word of the return value is retained by GDI.

Microsoft Confidential
40
CMDeleteTransform
BOOL WINAPI CMDeleteTransform(hcmTransform)

HCMTRANSFORM hcmTransform; /* handle of transform to delete */

The CMDeleteTransform function deletes and destroys the transforms created with CMCreateTransform.

Parameter Description

hcmTransform Handle of transform to delete.

Returns

The return value is TRUE if the function is successful. Otherwise, it is NULL.

Microsoft Confidential
41
CMTranslateRGB
BOOL WINAPI CMTranslateRGB(hcmTransform, ColorRef, lpColorRef, dwFlags)

HCMTRANSFORM hcmTransform; /* handle of transform to use */


COLORREF ColorRef; /* RGBQuad to translate */
LPCOLORREF lpColorRef; /* buffer to store result */
DWORD dwFlags; /* flags */

The CMTranslateRGB function translates an application supplied RGBQuad into the device color
coordinate space.

Parameter Description

hcmTransform Handle of transform to use.


RGBQUAD RGBQuad to translate.
LpColorRef Pointer to buffer to store result.
DwFlags Flags that can have the following meaning

Type Meaning

CMS_FORWARD Specifies that the forward transform is to be used.


CMS_BACKWARD Specifies that the backward transform is to be used.

Returns

The return value is TRUE if the function is successful. Otherwise, it is NULL.

Comments

If CMS_BACKWARD is clear then the function uses the forward color transform to do the translation. If
it is set then the backwards color transform is to be used.

Microsoft Confidential
42
CMTranslateRGBs
BOOL WINAPI CMTranslateRGBs(hcmTransform, lpSrcDIBBits, dwSrcTransFlags, nSrcWidth,
nSrcHeight, nsrcStride, lpDestDIBBits, dwDestTransFlags, nCount, dwFlags)

HCMTRANSFORM hcmTransform; /* handle of transform to use */


LPVOID lpSrcDIBBits; /* pointer to DIB bits to translate */
TRANSLATEFLAGS dwSrcTransFlags; /* translate flags */
UINT nSrcWidth; /* number of pixels in scanline */
UINT nSrcHeight; /* number of scanlines */
UINT nSrcStride; /* number to get from scanline to scanline */
LPVOID lpDestDIBBits; /* DIB buffer to store results */
TRANSLATEFLAGS dwDestTransFlags; /* translate flags */
DWORD dwFlags; /* flags */

The CMTranslateRGBs function translates an array of double bytes, triple bytes, or quad bytes,
depending on dwflags.

Parameter Description

hcmTransform Handle of transform to use.


lpSrcDIBBits Pointer to DIB bits to translate.
dwSrcTransFlags source translate flags
nSrcWidth number of pixels in scanline
nSrcHeight number of scanlines to be translated
nSrcStride number of bytes from beginning of scanline to beginning of next scanline
lpDestDIBBits Pointer to DIB buffer to store results.
dwDestTransFlags translate flags

Type Meaning

CMS_x555WORD 16 bit pixels, x555


CMS_565WORD 16 bit pixels, 565
CMS_RGBTRIPLETS 24 bit pixels, RGB
CMS_BGRTRIPLETS 24 bit pixels, BGR
CMS_XRGBQUADS 32 bit pixels, xRGB
CMS_XBGRQUADS 32 bit pixels, xBGR
CMS_QUADS 32 bit pixels, CMYK

dwFlags Describes direction of transform. Flags can have the following meaning:

CMS_FORWARD Specifies that the forward transform is to be used.


CMS_BACKWARD Specifies that the backward transform is to be used.

Returns

The return value is TRUE if the function is successful. Otherwise, it is NULL.

Comments

The input and output buffers are DIBs. The properties of DIBs must be respected. Scanlines begin on
dword boundaries. When the end of a scanline is reached the next scanline starts on the next closest
dword boundary. On occasion not all of a DIB is translated, for example clipping may be done. This could
lead to just a few rows and columns in the middle of the DIB needed translation. The nSrcStride
parameter gives the number of bytes to from the beginning of one scanline to the next. If nSrcStride is
zero then complete scanlines are converted. The destination is always a complete DIB, there is never a
wrap associated with it.

Microsoft Confidential
43
If CMS_FORWARD is specified then the function uses the forward color transform to do the translation.
If it is set to CMS_BACKWARD then the backwards color transform is to be used.

Microsoft Confidential
44
CMCheckColorsInGamut
BOOL WINAPI CMCheckColorInGamut(hcmTransform, lpaRGBTriples, lpBuffer, nCount)

HCMTRANSFORM hcmTransform; /* handle of transform to use */


RGBTRIPLE *lpaRGBTriples; /* array of RGB triples to check */
LPBYTE lpBuffer; /* buffer to put results */
UINT nCount; /* count of elements in array */

The CMCheckColorInGamut determines if the given RGBs lie in the output gamut of the given
transform.

Parameter Description

hcmTransform Handle of transform to use.


lpaRGBTriples Pointer to array of RGB triples to check.
LpBuffer Pointer to buffer to put results.
nCount Count of elements in array.

Returns

The return value is TRUE if the function is successful. Otherwise, it is NULL.

The lpBuffer holds the results, each byte corresponding to an RGB triple is a value in the range 0 to 255.

Microsoft Confidential
45
DDI, flags, #defines, and structures

Other than DevMode changes device drivers do not have to be rev'ved in order for image color matching
to occur at output time. However, if drivers wish to completely take over color matching they can do so by
supporting the ICM interfaces described in previous sections. Windows will default to the device ICM if
available.

Flags
// dpCaps1 capability bits

#define C1_GAMMA_RAMP 0x0020 // The device supports downloaded of gamma ramps.


#define C1_ICM 0x0040 // The device supports some form of ICM.

Structures
The DRAWMODE structure has been modified by the addition of the field hcmTransform. This field is
always correct, even if the driver does no color management. The use of the field is described in a previous
section. The field is NULL if the driver is to do no system supplied color processing on the colors passed
in. If non-null the the field holds the hcmTransform to use. Note that there are additional Windows 95
fields that are not related to image color matching.

DRAWMODE struc ;*/ typedef struct { /*


Rop2 dw 0 ; The 16-bit encoded logical op ;*/ short Rop2; /*
bkMode dw 0 ; Background Mode (for text only) ;*/short bkMode;/*
bkColor dd 0 ; Physical background Color ;*/DWORD bkColor; /*
TextColor dd 0 ; Physical text (foreground) color ;*/DWORD TextColor; /*
TBreakExtra dw 0 ; Total pixels to stuff into a line ;*/short TBreakExtra; /*
BreakExtra dw 0 ; Div(TBreakExtra, BreakCount) ;*/short BreakExtra; /*
BreakErr dw 0 ; Running error term ;*/short BreakErr; /*
BreakRem dw 0 ; Mod(TBreakExtra, BreakCount) ;*/ short BreakRem; /*
BreakCount dw 0 ; Count of breaks in the line ;*/ short BreakCount; /*
CharExtra dw 0 ; Extra pixles to stuff after each char ;*/ short CharExtra; /*
LbkColor dd 0 ; Logical background color ;*/ DWORD LbkColor; /*
LTextColor dd 0 ; Logical Text (foreground) color ;*/ DWORD LTextColor; /*
hcmTransform dd 0 ; handle of color transform ;*/HCMTRANSFORM hcmTransform;/*
StretchBltMode dw 0 ; stretch blt mode for shrinking ;*/ short StretchBltMode /*
eMiterLimit dd 0 ; single precision IEEE float ;*/ DWORD eMiterLimit /*
DRAWMODE ends ;*/ } DRAWMODE, FAR *LPDRAWMODE; /*

The DEVMODE structure has changed in many great and mysterious ways for Windows 95 For the
purposes of this discussion we will concentrate on the fields relevant to color matching. These fields are
dmICMMethod, dmICMIntent, dmMediaType, and dmDitherType. The fields dmReserved1 and
dmReserved2 must be set to zero in Windows 95.

The field dmICMMethod communicates the color matching option in the printer setup dialog box and
where the matching is to occur. DMICMETHOD_NONE means that color matching is not to be done by
default. All other non-zero values mean color matching should occur. DMICMETHOD_SYSTEM means
that conversion should occur on the host by a color matching DLL, DMICMETHOD_DRIVER 15 means
the device driver uses the suppplied profiles to do the conversion, DMICMETHOD_DEVICE means the
profiles are downloaded to the device by the driver and the device does the conversions.

15 The PostScript driver supports these options in Windows 95.

Microsoft Confidential
46
/* ICM methods */
#define DMICMMETHOD_NONE 1 /* ICM disabled */
#define DMICMMETHOD_SYSTEM 2 /* ICM handled by system */
#define DMICMMETHOD_DRIVER 3 /* ICM handled by driver */
#define DMICMMETHOD_DEVICE 4 /* ICM handled by device */
#define DMICMMETHOD_USER 256 /* Device-specific methods start here */

The field dmICMIntent communicates the gamut matching option in the printer setup dialog box.

/* ICM Intents */
#define DMICM_SATURATE 1 /* Maximize color saturation */
#define DMICM_CONTRAST 2 /* Maximize color contrast */
#define DMICM_COLORMETRIC 3 /* Use specific color metric */
#define DMICM_USER 256 /* Device-specific intents start here */

The field dmMediaType communicates what paper the user has selected. Most special papers are in the
DMMEDIA_USER range. DMMEDIA values do not have to be non-overlapping across devices because
the search for a match starts with the manufacturer and model.

/* Media types */
#define DMMEDIA_STANDARD 1 /* Standard paper */
#define DMMEDIA_TRANSPARENCY 2 /* Transparency */
#define DMMEDIA_GLOSSY 3 /* Glossy paper */
#define DMMEDIA_USER 256 /* Device-specific media start here */

The field dmDitherType communicates what dither the user has selected.

/* Dither types */
#define DMDITHER_NONE 1 /* No dithering */
#define DMDITHER_COARSE 2 /* Dither with a coarse brush */
#define DMDITHER_FINE 3 /* Dither with a fine brush */
#define DMDITHER_LINEART 4 /* LineArt dithering */
#define DMDITHER_ERRORDIFFUSION 5 /* Error diffusion */
#define DMDITHER_RESERVED6 6 /* Reserved */
#define DMDITHER_RESERVED7 7 /* Reserved */
#define DMDITHER_RESERVED8 8 /* Reserved */
#define DMDITHER_RESERVED9 9 /* Reserved */
#define DMDITHER_GRAYSCALE 10 /* Device does grayscaling */
#define DMDITHER_USER 256 /* Device-specific dither start here*/

DEVMODE struc ;/* typedef struct { */


dmDeviceName db CCHDN dup (0) ;/* char dmDeviceName[CCHDN]; */
dmSpecVersion dw 0 ;/* UINT dmSpecVersion; */
dmDriverVersion dw 0 ;/* UINT dmDriverVersion; */
dmSize dw 0 ;/* UINT dmSize; */
dmDriverExtra dw 0 ;/* UINT dmDriverExtra;
*/
dmFields dd 0 ;/* DWORD dmFields; */
dmOrientation dw 0 ;/* int dmOrientation; */
dmPaperSize dw 0 ;/* int dmPaperSize; */
dmPaperLength dw 0 ;/* int dmPaperLength; */
dmPaperWidth dw 0 ;/* int dmPaperWidth; */
dmScale dw 0 ;/* int dmScale; */
dmCopies dw 0 ;/* int dmCopies; */
dmDefaultSource dw 0 ;/* int dmDefaultSource; */
dmPrintQuality dw 0 ;/* int dmPrintQuality;
*/

Microsoft Confidential
47
dmColor dw 0 ;/* int dmColor; */
dmDuplex dw 0 ;/* int dmDuplex; */
dmYResolution dw 0 ;/* int dmYResolution; */
dmTTOption dw 0 ;/* int dmTTOption; */
dmCollate dw 0 ;/* int dmCollate; */
dmFormName db CCHFORMN dup(0) ;/*char dmFormName[CCHFORMN]; */
dmUnusedPadding dw 0 ;/* WORD dmUnusedPadding; */
dmBitsPerPel dw 0 ;/* WORD dmBitsPerPel; */
dmPelsWidth dd 0 ;/* DWORD dmPelsWidth; */
dmPelsHeight dd 0 ;/* DWORD dmPelsHeight; */
dmDisplayFlags dd 0 ;/* DWORD dmDisplayFlags; */
dmDisplayFrequency dd 0 ;/* DWORD dmDisplayFrequency; */
dmICMMethod dw 0 ;/* WORD dmICMMethod; */
dmICMIntent dw 0 ;/* WORD dmICMIntent;*/
dmMediaType dw 0 ;/* WORD dmMediaType; */
dmDitherType dw 0 ;/* WORD dmDitherType; */
dmReserved1 dd 0 ;/* DWORD dmReserved1; */
dmReserved2 dd 0 ;/* DWORD dmReserved2; */
DEVMODE ends ;/* } DEVMODE; */

The LOGPEN structure passed to the drivers has been extended to include a hcmTransform. This field is
always filled in and correct even if the driver does not do its own image color matching. The lopnStyle2
field is described in a different specification.

LogPen struc ;*/ typedef struct { /*


lopnStyle dw 0 ;See flags above. ;*/ unsigned short int lopnStyle; /*
lopnWidth dw 0 ;Is a point type ;*/ PTTYPE lopnWidth; /*
dw 0
lopnColor dd 0 ;*/ unsigned long int lopnColor; /*
lopnStyle2 dw 0 ;See flags above. ;*/ unsigned short int lopnStyle2; /*
lopnhcmTransform dd 0 ;*/ HCMTRANSFORM lopncmTransform;
LogPen ends ;*/ } LOGPEN; /*

The LOGBRUSH structure passed to the drivers haa been extended to include a hcmTransform. This field
is always filled in and correct even if the driver does not do its own image color matching.

LogBrush struc ;*/ typedef struct { /*


lbStyle dw 0 ;Style of logical BRUSH ;*/ unsigned short int lbStyle; /*
lbColor dd 0 ;RGB color ;*/ unsigned long int lbColor; /*
lbHatch dw 0 ;Hatching style ;*/ unsigned short int lbHatch; /*
lbBkColor dd 0 ;*/ unsigned long int lbBkColor; /*
lbhcmTransform dd 0 ;*/ HCMTRANSFORM idhcmTransform;/*
LogBrush ends */ } LOGBRUSH; /*

lbPattern equ lbColor ;Pointer to physical pattern

DDI
The functions added are:

DDIGammaRamp sets and gets display adaptor gamma ramps


ICMColorInfo hcmTransform added as a parameter to ColorInfo

Microsoft Confidential
48
DDIGammaRamp
BOOL WINAPI DDIGammaRamp(lpDev, fGetSet, lpRamp)

LPDEVICE lpDev; / * pointer to the physical device */


BOOL fGetSet; /* flag to determine if a get or set is wanted */
LPARAM lpGammaRamp; /* address of application-supplied data */

The DDIGammaRamp sets the ramp on direct color display boards.

Parameter Description

lpDev Pointer to the physical device.


fGetSet TRUE for setting, FALSE for getting.
lpRamp Points to a set of three arrays of 256 word (16 bit) elements. These arrays
are the mapping between RGB values in the frame buffer and DAC values.
The first array is red, the next green, and the final one blue.

Returns

The return value is TRUE if the function is successful. Otherwise, it is NULL.

Comments

The export ordinal for this function is 32.

For display adapters that only have 8 bit DACs the high byte of the word is to be loaded. For adaptors that
have 12 bit DACs the high 12 bits are used. For 16 bit DACs the whole word is loaded.

Direct color display modes do not use color lookup tables to translate between pixel values and colors, the
pixel value is fed directly to the DACs. The direct color modes are usually 16, 24, or 32 bit deep. The
display adaptor must have hardware to support loadable gamma ramps for the driver to support this
function. If the driver does support this function it must also set the C1_GAMMA_RAMP bit in dpCaps1.

The setting of the display gamma ramp acts globally across all tasks. The gamma ramp is not maintained
on a per application basis. Once set, the gamma ramp does not change until the next set call made by an
application. It is expected that users will run a calibration utility to set the gamma ramps when they boot
Windows. Arbitrary applications must not set it independently of each other.

Microsoft Confidential
49
ICMColorInfo
COLORREF WINAPI ICMColorInfo(lpDestDev, dwColorin, lpPColor,hcmTransform)

LPPDEVICE lpDestDev;
DWORD dwColorin;
LPPCOLOR lpPColor;
HCMTRANSFORM hcmTransform;

The ICMColorInfo function converts a logical color (an ColorRef value) to a physical color ( a physical
color value) or converts a physical to a logical color, depending on the value of the lpPColor parameter.

Parameter Description

lpDestDev Points to a PDEVICE or PBITMAP structure specifying the destination device or


bitmap.
dwColorin Specifies either a logical or physical color, depending on the value of lpPColor
parameter.
lpPColor Points to a PCOLOR structure or is NULL. If lpPColor points to a PCOLOR
structure, the function assumes that dwColorin specifies a logical color (an RGB
value) and copies the physical color value that most closely matches the logical
color to this structure. If lpPColor is NULL, the function assumes that dwColorin
specifies a physical color and returns the logical color that matches the physical
color.
hcmTransform Handle of color transform to be used in transforming dwColorin.

Returns

The return value is the logical color that most closely matches the physical color either specified by
dwColorin, or copied to the PCOLOR structure pointed to by lpPColor.

Comments

The export ordinal for this function is 33.

This function is identical in intent and purpose to ColorInfo. The added parameter is refers to a transform
to apply to the logical color to get to the physical color.

When converting a logical color, ICMColorInfo chooses the best possible physical color to match the
logical color and return the ColorQuad value that corresponds to this physical color.

GDI uses the physical colors returned by ICMColorInfo to set text colors, background colors, and pixel
colors using the Pixel function.

If dwColorin is a logical color, it will never specify color index.

Microsoft Confidential
50

Vous aimerez peut-être aussi