To get either bitmap information (header) or bitmap data, Gpi2QueryBitmapInfo() and Gpi2QueryBitmapBits() should be used. It will be useful to process BITMAP2 data directly. Syntax:
BOOL APIENTRY Gpi2QueryBitmapInfo(HBITMAP2 hbitmap2, // BITMAP2 handle
PBITMAP2HEADER pbmp2header); // Pointer to BITMAP2HEADER structure,
// where bitmap information will be placed
Returns: TRUE - function completed successfuly
FALSE - error occured. Gpi2GetLastError() will return error code;
BOOL APIENTRY Gpi2QueryBitmapBits(HBITMAP2 hbitmap2, // BITMAP2 handle
LONG lScanStart, // First scanline
LONG lScans, // number of scanlines
PBYTE pbBuffer); // memory buffer where bitmap data will be copied
Returns: TRUE - function completed successfuly
FALSE - error occured. Gpi2GetLastError() will return error code;
**********************************************************
*** Example of copying bitmap by using ***
*** Gpi2QueryBitmapInfo() and Gpi2QueryBitmapBits() ***
**********************************************************
BITMAP2HEADER bmp2header;
HBITMAP2 hbm2new;
// Let's suppose that here we have code from the first example
...
if (Gpi2QueryBitmapBits(hbm2, &bmp2header) // Query bitmap data
// Allocate memory for new bitmap data
if (!DosAllocMem((PPVOID)&cBitmapArray, bmp2header.usCx*bmp2header.usCy*bmp2header.cChannels, PAG_COMMIT|PAG_READ|PAG_WRITE)))
{
Gpi2QueryBitmapBits(hbm2, 0, bmp2header.usCy, &cBitmapArray); // Copy bitmap data
// Create bitmap and initialize it with copied bitmap data
hbm2new = Gpi2CreateBitmap(bmp2header.usCx, bmp2header.usCy, bmp2header.cChannels, bmp2header.cBits, cBitmapArray);
}
**********************************************************
*** End of the example ***
**********************************************************
Okay! The code above was just an example of using some calls. To tell the truth, its absolutely useless, 'cause ecomedia.dll contains a function for copying bitmaps, which works faster than the code above: Gpi2CopyBitmap(). It's syntax:
HBITMAP2 APIENTRY Gpi2CopyBitmap(HBITMAP2 hbitmap2); // BITMAP2 handle to be copied
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - new bitmap handle;
Pretty simple, right? I don't think it needs an example of using it. Another useful function is Gpi2CropBitmap(). Yeah, it allows you to crop bitmap. Its syntaxs also simple:
HBITMAP2 APIENTRY Gpi2CropBitmap(HBITMAP2 hbitmap2, // BITMAP2 handle to be cropped
PRECTL prcl); // pointer to RECTL structure, containg the rectangle inside hbitmap2 to crop
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - cropped bitmap handle;
And now... You know how to create and process bitmap. The only thing is left is bitmap output. There are two functions in ecomedia.dll for tis task:
Gpi2BitBlt() - to blit one BITMAP2 into another one, and Gpi2DrawBitmap() - to draw bitmap into a presentation space. Their syntax:
BOOL APIENTRY Gpi2BitBlt(HBITMAP2 hbm2Target, // Target bitmap handle
HBITMAP2 hbm2Source, // Source bitmap handle
LONG lCount, // Number of points (from 1 to 3) in the aptlPoints
PPOINTL aptlPoints, // array of POINTL structures, describing source and target blitting areas
ULONG ulBckgColor, // Background color. Used only if source bitmap have transparent areas (alpha channel) and FL_PROCESSALPHA flag is specified.
ULONG flOptions); // Bitmap flags. Valid flags are FL_STRIPALPHA, FL_PROCESSALPHA, FL_COPYALPHA
Returns: TRUE - function completed successfuly
FALSE - error occured. Gpi2GetLastError() will return error code;
BOOL APIENTRY Gpi2DrawBitmap(HPS hpsTarget, // Target presentation space handle
HBITMAP2 hbm2Source, // Source bitmap handle
LONG lCount, // Number of points (from 1 to 3) in the aptlPoints
PPOINTL aptlPoints); // array of POINTL structures, describing source and target blitting areas
Returns: TRUE - function completed successfuly
FALSE - error occured. Gpi2GetLastError() will return error code;
Both unlike GpiBitBlt() and WinDrawBitmap() calls, Gpi2DrawBitmap() and Gpi2BitBlt() are accept only 3 points, so no scaling is preformed. To scale bitmap Gpi2ScaleBitmap2() is used. Its syntax is:
HBITMAP2 APIENTRY Gpi2ScaleBitmap2(HBITMAP2 hbitmap2, // Handle of BITMAP2 to be scaled
ULONG width, // New bitmap width
ULONG height, // New bitmap height
BOOL bKeep); // Keep aspect ratio flag
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - scaled bitmap handle;
Note: there is also Gpi2ScaleBitmap() function, which works with standard OS/2 BITMAP (not BITMAP2) format. It is left only for backwards compatibility and being unsafe is DEPRECATED!
Of course, after bitmap was used and is not needed anymore, it must be deleted. Use Gpi2DeleteBitmap() function to do it. It's syntax is obvious:
BOOL APIENTRY Gpi2DeleteBitmap(HBITMAP2 hbitmap2); // Handle of BITMAP2 to be deleted
Returns: TRUE - function completed successfuly
FALSE - error occured. Gpi2GetLastError() will return error code;
Okay! Let's see, how we can use those functions.
**********************************************************
*** Example of drawing bitmap by using ***
*** Gpi2BitBlt(), Gpi2DrawBitmap(), Gpi2DeleteBitmap() ***
*** and Gpi2ScaleBitmap2() functions ***
**********************************************************
// Let's suppose that this is a part of the window procedure...
HBITMAP2 hbm2scaled;
POINTL aptlPoints[3];
RECTL rcl;
HPS hps;
switch (msg)
{
...
case WM_PAINT:
hps=WinBeginPaint(hps, 0L, &rcl);
if (hps)
{
// Let's suppose that here we have code from the second example
...
hbm2scaled=Gpi2ScaleBitmap(hbm2, ulWidth/2, ulHeight/2, FALSE); // Shrink bitmap
if (hbm2Scaled)
{
// Lower-left corner in the source bitmap
aptlPoints[0].x=5;
aptlPoints[0].y=5;
// Upper-right corner in the source bitmap
aptlPoints[1].x=ulWidth/2-5;
aptlPoints[1].y=ulHeight/2-5;
aptlPoints[2].x=1;
aptlPoints[2].y=1;
if (Gpi2BitBlt(hbm2, hbm2scaled, 3, aptlPoints, 0L, 0L))
{
// Let's suppose, that the window (hwnd) and the bitmap (hbm2) have the same size,
// so, let's copy appropriate part of the bitmap to the window's update rectangle
aptlPoints[0].x=rcl.xLeft;
aptlPoints[0].y=rcl.yBottom;
aptlPoints[1].x=rcl.xRght;
aptlPoints[1].y=rcl.yTop;
aptlPoints[2].x=rcl.xLeft;
aptlPoints[2].y=rcl.yBottom;
Gpi2DrawBitmap(hps, hbm2, 3, aptlPoints);
}
// Yeah! Delete the bitmap, 'cause we don't need it anymore
Gpi2DeleteBitmap(hbm2Scaled);
}
WinEndPaint(hps);
Gpi2DeleteBitmap(hbm2); // We don't need this one as well!
}
break;
...
}
return WinDefWindowProc(hwnd, msg, mp1, mp2);
**********************************************************
*** End of the example ***
**********************************************************
Switching between old (OS/2 BITMAP) and new (BITMAP2) formats
Well, as you could see, everything is really simple. Those, who have experience in GPI programming will learn using that Gpi2* stuff without any problem.
And, if you already have an application, which uses GPI for drawing grapics, don't hesitate to switch it to Gpi2* calls. To simplify this task, there are two special functions in ecomedia.dll: Gpi2Bitmap2FromBitmap() and Gpi2BitmapFromBitmap2. Yeah! They doing just what they say: converting BITMAP2 format to standard OS/2 BITMAP and back. The syntax is:
HBITMAP2 APIENTRY Gpi2Bitmap2FromBitmap(HBITMAP hbmp); // Source BITMAP handle
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - new converted BITMAP2 handle;
HBITMAP APIENTRY Gpi2BitmapFromBitmap2(HBITMAP2 hbmp2, // Source BITMAP handle
ULONG ulColor, // Background color. Used only if source bitmap have transparent areas (alpha channel) and FL_PROCESSALPHA flag is specified.
ULONG flFlags); // Flags, which determine, how alpha channel will be treated. Valid flags are: FL_STRIPALPHA, FL_PROCESSALPHA, FL_COPYALPHA.
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - new converted BITMAP handle;
I think, using those functions is clear enough, so there is no need to publish examples of using those functions.
Instead, let's talk about two really useful features of ecomedia.dll, which will help you to develop nice mordern apllications: working with OS/2 bitmap data formats (icons/pointers/bitmaps) and working with portable network graphics (PNG) data formats:
Working with OS/2 Icon/Pointer/Bitmap data files
There are no functions for parsing OS/2 Icon/Pointer/Bitmap data structures in OS/2 GPI/PM. WinLoadBitmap()/WinLoadPointer() functions processing those structures internally giving you BITMAP/POINTER handle. So, if the file you are working with is an array, you are unable to choose which image of the array you need.
There are three functions in ecomedia.dll v2 to process OS/2 Icons/Pointers/Bitmaps: Gpi2GetIconData(), Gpi2ParseIconInfo() and Gpi2ReadBitmap().
Gpi2ReadBitmap() is the low-level function which used to parse the OS/2 icon data. Its syntax:
HBITMAP2 APIENTRY Gpi2ReadBitmap(PVOID pIconData, // OS/2 Icon data
PULONG pulCx, PULONG pulCy, // Image size
USHORT usBitCount, // Image bit depth
ULONG ulBckgColor, // Background color. Used only if source icon/pointer have transparent areas and FL_PROCESSALPHA flag is specified.
ULONG ulColor0, // Image color (0). Used only for monochrome (black-and-white) bitmaps
ULONG ulColor1, // Image color (1). Used only for monochrome (black-and-white) bitmaps
ULONG flOptions); // Icon processing flags
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - BITMAP2 handle;
pIconData: pointer to raw OS/2 icon data. You can get it by reading OS/2 Icon/Pointer/Bitmap from the file or from the resource (using DosLoadResource() function).
pulCx, pulCy: pointer to ULONG variables which on input contain desired image size. If pIconData contains a single image, it will be ignored. If pIconData is a bitmap array, it will be searched to find an image which best fits desired resolution. The decision, which image fits the best is taken this way:
- If there is an image with the same resolution, it is considered to be the best.
- Otherwise, if there are images larger, than desired, the smallest of them is considered to be the best.
- Otherwise, the largest image is considered to be the best.
usBitCount: desired bit depth. If there are more that one image have resolution, which considered to be the best, usBitCount is taken in account:
- If there is an image with the same bit count, it is considered to be the best.
- Otherwise, if there are images with bigger bit depth, than desired, the image with smallest bit depth is considered to be the best.
- Otherwise, the image with larger bit depth is considered to be the best.
ulBckgColor: used if the image is either a pointer or an icon and contains transparent areas, and FL_PROCESSALPHA flag specified. See flOptions for more detailed info.
ulColor0, ulColor1: Colors used for monochrome (1bps) bitmaps. ulColor0 is used for pixels which are set to 0 and ulColor1 is used for pixels, which are set to 1.
flOptions: bit flags used to specify how to process image. The only valid flag for now is: FL_PROCESSALPHA. This flag is meaningful only if the image is either a pointer or an icon and contains transparent or inverted areas:
- If this flag is specified, RGB (true color without alpha channel) BITMAP2 is created. Transparent areas are filled with ulBckgColor color and inverted areas are filled with inverted ulBckgColor.
- If this flag is not specified, RGBA (true color with alpha channel) bitmap is created. Transparent areas are left transparent (alpha = 0) and inverted areas are ignored (also become transparent).
Working with PNG data files
ECOMEDIA.DLL also provides function to work with portable network graphics (PNG) data file format: Gpi2ReadPng(). Here is the syntax:
HBITMAP2 APIENTRY Gpi2ReadPng(PBYTE pPngData, // PNG data
ULONG ulBackgroundColor, // Background color (see below)
ULONG flOptions); // PNG processing flag (see below).
Returns: NULLHANDLE - error occured. Gpi2GetLastError() will return error code;
Other - BITMAP2 handle;
Used only if source PNG have transparent areas (alpha channel or transparency chunk) and FL_PROCESSALPHA flag is specified and FL_USEBKGD flag is not specified or no PNG contains no bKGD chunk.
This function reads and renders PNG data specified by pPngData, and returns BITMAP2 handle. You can obtain PNG data by reading PNG file or by loading it from the resources (using DosLoadResource() function).
flOptions parameter used to specify how to process transparent areas in the PNG (if either alpha channel or tRNS chunk present).
Valid options are:
- FL_STRIPALPHA - ignore alpha channel/transparency;
- FL_PROCESSALPHA - render PNG using ulBackgroundColor parameter as a background color.
- FL_USEBKGD - use bKGD chunk instead of ulBackgroundColor as a background color. Ignored of FL_PROCESSALPHA is not specified or bKGD chunk is not present.
When PNG has transparency (alpha channel or tRNS chunk) and neither FL_STRIPALPHA nor FL_PROCESSALPHA flag is specified, RGBA (32-bit) BITMAP2 is created. Otherwise, RGB (24-bit) BOTMAP2 is created.
Special functions
There are three special functions, added to ECOMEDIA.DLL v2.0:
Gpi2GetVersion(), Gpi2GetVersionString() - allows you to check the library version. Syntax:
VOID APIENTRY Gpi2GetVersion(PULONG pulMajor, // Major version number
PULONG pulMinor); // Minor version number
returns: nothing
USHORT APIENTRY Gpi2GetVersionString(PSZ pszBuffer, // Buffer, where string, containing version number will be placed
USHORT cbBufLen); // pszBuffer length
returns: number of characters copied to pszBuffer
Gpi2GetLastError(): returns error code of the last failed Gpi2* function. Syntax:
APIRET APIENTRY Gpi2GetLastError();
returns: error code
THE MOST IMPORTANT PART
Examine PNGTEST example carefuly to see usage of all the functions, described in this document. This is the best and easiest way to learn how to use new features of ECOMEDIA.DLL v2.0!