| Herd Software Development
|=
DaVinci Graphics Library
|==
DaVinci Documentation Home Search Order


Leonardo: Bitmap dithering functions

If your application is deployed on PCs limited to standard VGA cards, or systems whose video drivers are set to display 16 colors, then nothing you do with the color palette of your images can improve the appearance of the image. The target system's GDI will always reduce the image to 16 colors for display, and use a "nearest color" matching scheme when doing so. This might be fine for screen captures of dialogs, but it results in extremely poor image quality for any detailed images. To make matters worse, some video drivers use algorithms so slow that it could take a minute or more to display images you might consider modest in size.

GDI is also limited in the way it deals with displaying 24 bit (TrueColor) images on 256 color displays. When presented with this situation, it actually applies only 20 colors to the output image, once again resulting in a very poor onscreen image. "Dithering" allows for a more pleasing image by selecting colors for adjacent pixels to produce an effect that makes it appear as though there are more colors onscreen than there really are. Leonardo offers three dithering functions: DitherTo4, DitherTo8 and DitherTo1:

Function DitherTo4

HGLOBAL FAR PASCAL DitherTo4(LPBITMAPINFOHEADER lpbm);

lpbm LPBITMAPINFOHEADER
Pointer to a device independent bitmap (see API documenatation for BITMAPINFOHEADER)

BITMAPINFOHEADER, palette and bitmap bits must immediately follow each other as in the CF_DIB format.

Allows DIBs at 8, 16, 24 or 32 bit color depth.

Returns

If successful, the return value is a global memory handle in DIB format with 4 bits of color depth. Returns NULL if the conversion failed or the DIB was a 4 bit image in the first place. The handle must be released by the application using GlobalFree.

When the application releases the newly created DIB, the source DIB is neither changed nor released.

lpbm can point to a bitmap loaded from a resource.

Example for Borland OWL 2.x

{ TDib * 		theDib = new TDib( "MEINE.BMP");	// Loads file MEINE.BMP and creates new Tdib object
  HGLOBAL 		hg = HANDLE( *theDib );
  LPBITMAPINFOHEADER	pbm = (LPBITMAPINFOHEADER) GlobalLock(hg);
  HGLOBAL		h4bit = DitherTo4(pbm);
  GlobalUnlock(hg); 
  if (h4bit) {
	delete theDib;
	theDib = new TDib( h4bit );
  } 
}
  

Also see the sample programs.

Function DitherTo1

HGLOBAL FAR PASCAL DitherTo1(
LPBITMAPINFOHEADER lpbm,
LPBYTE LpabGamma);

lpbm LPBITMAPINFOHEADER
Pointer to a device independent bitmap (see API documenatation for BITMAPINFOHEADER)

BITMAPINFOHEADER, palette and bitmap bits must immediately follow each other as in the CF_DIB format.

Allows DIBs at 4, 8, 16, 24 or 32 bit color depth.

lpabGamma LPBYTE NULL or a pointer to a byte array which has been filled using a call to the GammaCorrectionGetArray function.

Returns

If successful, the return value is a global memory handle in DIB format with 1 bit of color depth. Returns NULL if the conversion failed or the DIB was a 4 bit image in the first place. The handle must be released by the application using GlobalFree.

When the application releases the newly created DIB, the source DIB is neither changed nor released.

lpbm can point to a bitmap loaded from a resource.

This function is especially well suited to producing high-quality images on one-color printers. In most cases this algorithm will produce a better quality output image than dithering algorithms executed by the printer driver. Many printer drivers use only an "ordered dither" algorithm, which tends to be much less pleasing than the error diffusion algorithm used by DitherTo1.

Function DitherTo8

DitherTo8 generates a DIB of 8 bit color depth using a palette derived from the colors used in a source 24 bit image.

HDIB FAR PASCAL DitherTo8(
LPBITMAPINFOHEADER lpDib,
int std,
int more,
LPBITMAPINFOHEADER lpPal);

lpbm LPBITMAPINFOHEADER
Pointer to a device independent bitmap (see API documenatation for BITMAPINFOHEADER)

BITMAPINFOHEADER, palette and bitmap bits must immediately follow each other as in the CF_DIB format.

Allows DIBs at 16, 24 or 32 bit color depth.

std int Specifies the number of nonoptimized colors the function should use in the palette of the new DIB (see remarks below) Valid values:

0 - none
2 - 2*2*2 = 8 nonoptimized colors
3 - 3*3*3 = 27 nonoptimized colors
4 - 4*4*4 = 64 nonoptimized colors
5 - 5*5*5 = 125 nonoptimized colors
6 - 6*6*6 = 216 nonoptimized colors

more int Number of Colors optimized for the conversion of the DIB defined by lpbm.

lpPal LPBITMAPINFOHEADER
Pointer to a DIB of 8 bit color depth which contains the color palette for the newly-created DIB, or NULL if the color palette should be generated using the parameters specified in std and more.

Use of optimized palettes generated by DIBSelectColors is recommended for higher output quality.

Returns

If successful, the return value is a global memory handle in DIB format of 8 bit color depth. Returns NULL if the conversion failed. The handle must be released by the application using GlobalFree.

When the application releases the newly created DIB, the source DIB is neither changed nor released.

lpbm can point to a bitmap loaded from a resource.

Use of std, More and lpPal

DitherTo8 allows the palette of the output DIB to be defined both from an optimized and a nonoptimized group of colors, allowing for reduction to a specific color count. It can also apply the palette of another DIB to the new DIB for palette matching multiple 256 color images.

The nonoptimized colors are specified in the number of increments of red, green and blue that can be used in defining a specific count for optimized colors. For example 0%, 50%, 100% = 3 steps and std = 3. Since this is used for all three color components (red, green, and blue), the result is 3*3*3, or 27 total nonoptimized colors. The std parameter specifies the number of allowable steps per component.

Optimized colors are generated using a histogram analysis of the source DIB. DitherTo8 selects the colors most frequent in the DIB to be displayed. The number of colors selected for the palette in this fashion is specified by the more parameter.

The total values of all colors defined by std and more must not exceed 236. This limit is in place to insure that the resulting DIB's palette will have at least 20 unused colors. These colors are needed for the standard palette on 8 bit displays. The upper and lower limit is specified as:
0 < std*std*std + more <= 236

Examples

std more lpPal

1 Extremely fast screening: Only nonoptimized colors are used, simulating the application of a "standard" 256 color palette. Speed is approximately three times faster than application of an optimized palette. 6 0 NULL
2 Optimized color palette: DitherTo8 determines the appropriate color palette for the current image by using the 236 colors best suited to mimicking the appearance of the source DIB. 0 236 NULL
3 Apply the palette of another DIB: Faster than calculating an optimized palette; slower than applying a strictly nonoptimized palette. 0 0 LpPal
4 Combining palettes of several DIBs for simultaneous display (palette matching): The combination of nonoptimized and optimized colors is specified in a fashion that insures the total number of colors for all selected DIBs is <235 5 50 NULL

Dithering in WinNT

Dithering can be done by NT's own GDI during the display of a DIB with StretchDIBits and/or StretchDIBBlt. HALFTONE mode is first activated using a call to SetStretchBltMode and gamma is then set using SetColorAdjustment. A color palette created by CreateHalftonePalette should then be applied to complete the process.

Contrary to Microsoft's own documentation, this built-in dithering can't be done on Windows 95 due to bug which Microsoft confirmed after publishing the API. Note also that NT applies only an ordered dither algorithm and performs no error diffusion. Resulting quality is significantly poorer for most images than error diffusion, but ordered dithering is a significantly faster process.