00001 // dibapi.cpp 00002 // 00003 // Source file for Device-Independent Bitmap (DIB) API. Provides 00004 // the following functions: 00005 // 00006 // PaintDIB() - Painting routine for a DIB 00007 // CreateDIBPalette() - Creates a palette from a DIB 00008 // FindDIBBits() - Returns a pointer to the DIB bits 00009 // DIBWidth() - Gets the width of the DIB 00010 // DIBHeight() - Gets the height of the DIB 00011 // PaletteSize() - Gets the size required to store the DIB's palette 00012 // DIBNumColors() - Calculates the number of colors 00013 // in the DIB's color table 00014 // CopyHandle() - Makes a copy of the given global memory block 00015 // 00016 // This is a part of the Microsoft Foundation Classes C++ library. 00017 // Copyright (C) 1992-1995 Microsoft Corporation 00018 // All rights reserved. 00019 // 00020 // This source code is only intended as a supplement to the 00021 // Microsoft Foundation Classes Reference and related 00022 // electronic documentation provided with the library. 00023 // See these sources for detailed information regarding the 00024 // Microsoft Foundation Classes product. 00025 00026 #include "stdafx.h" 00027 #include "dibapi.h" 00028 #include <io.h> 00029 #include <errno.h> 00030 00031 /************************************************************************* 00032 * 00033 * PaintDIB() 00034 * 00035 * Parameters: 00036 * 00037 * HDC hDC - DC to do output to 00038 * 00039 * LPRECT lpDCRect - rectangle on DC to do output to 00040 * 00041 * HDIB hDIB - handle to global memory with a DIB spec 00042 * in it followed by the DIB bits 00043 * 00044 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect 00045 * 00046 * CPalette* pPal - pointer to CPalette containing DIB's palette 00047 * 00048 * Return Value: 00049 * 00050 * BOOL - TRUE if DIB was drawn, FALSE otherwise 00051 * 00052 * Description: 00053 * Painting routine for a DIB. Calls StretchDIBits() or 00054 * SetDIBitsToDevice() to paint the DIB. The DIB is 00055 * output to the specified DC, at the coordinates given 00056 * in lpDCRect. The area of the DIB to be output is 00057 * given by lpDIBRect. 00058 * 00059 ************************************************************************/ 00060 00061 BOOL WINAPI PaintDIB(HDC hDC, 00062 LPRECT lpDCRect, 00063 HDIB hDIB, 00064 LPRECT lpDIBRect, 00065 CPalette* pPal) 00066 { 00067 LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER 00068 LPSTR lpDIBBits; // Pointer to DIB bits 00069 BOOL bSuccess=FALSE; // Success/fail flag 00070 HPALETTE hPal=NULL; // Our DIB's palette 00071 HPALETTE hOldPal=NULL; // Previous palette 00072 00073 /* Check for valid DIB handle */ 00074 if (hDIB == NULL) 00075 return FALSE; 00076 00077 /* Lock down the DIB, and get a pointer to the beginning of the bit 00078 * buffer 00079 */ 00080 lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 00081 lpDIBBits = ::FindDIBBits(lpDIBHdr); 00082 00083 // Get the DIB's palette, then select it into DC 00084 if (pPal != NULL) 00085 { 00086 hPal = (HPALETTE) pPal->m_hObject; 00087 00088 // Select as background since we have 00089 // already realized in forground if needed 00090 hOldPal = ::SelectPalette(hDC, hPal, TRUE); 00091 } 00092 00093 /* Make sure to use the stretching mode best for color pictures */ 00094 ::SetStretchBltMode(hDC, COLORONCOLOR); 00095 00096 /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */ 00097 /* modified by Peter to support mapping modes */ 00098 POINT testPoints[2]; 00099 testPoints[0].x = 16; testPoints[0].x = 16; 00100 testPoints[1].x = 64; testPoints[1].x = 64; 00101 ::DPtoLP(hDC, testPoints, 2); 00102 bool bNoScale = ( (testPoints[1].x - testPoints[0].x) == (64-16) ); 00103 00104 if (bNoScale && (RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && 00105 (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 00106 bSuccess = ::SetDIBitsToDevice(hDC, // hDC 00107 lpDCRect->left, // DestX 00108 lpDCRect->top, // DestY 00109 RECTWIDTH(lpDCRect), // nDestWidth 00110 RECTHEIGHT(lpDCRect), // nDestHeight 00111 lpDIBRect->left, // SrcX 00112 (int)DIBHeight(lpDIBHdr) - 00113 lpDIBRect->top - 00114 RECTHEIGHT(lpDIBRect), // SrcY 00115 0, // nStartScan 00116 (WORD)DIBHeight(lpDIBHdr), // nNumScans 00117 lpDIBBits, // lpBits 00118 (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo 00119 DIB_RGB_COLORS); // wUsage 00120 else 00121 bSuccess = ::StretchDIBits(hDC, // hDC 00122 lpDCRect->left, // DestX 00123 lpDCRect->top, // DestY 00124 RECTWIDTH(lpDCRect), // nDestWidth 00125 RECTHEIGHT(lpDCRect), // nDestHeight 00126 lpDIBRect->left, // SrcX 00127 lpDIBRect->top, // SrcY 00128 RECTWIDTH(lpDIBRect), // wSrcWidth 00129 RECTHEIGHT(lpDIBRect), // wSrcHeight 00130 lpDIBBits, // lpBits 00131 (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo 00132 DIB_RGB_COLORS, // wUsage 00133 SRCCOPY); // dwROP 00134 00135 ::GlobalUnlock((HGLOBAL) hDIB); 00136 00137 /* Reselect old palette */ 00138 if (hOldPal != NULL) 00139 { 00140 ::SelectPalette(hDC, hOldPal, TRUE); 00141 } 00142 00143 return bSuccess; 00144 } 00145 00146 /************************************************************************* 00147 * 00148 * CreateDIBPalette() 00149 * 00150 * Parameter: 00151 * 00152 * HDIB hDIB - specifies the DIB 00153 * 00154 * Return Value: 00155 * 00156 * HPALETTE - specifies the palette 00157 * 00158 * Description: 00159 * 00160 * This function creates a palette from a DIB by allocating memory for the 00161 * logical palette, reading and storing the colors from the DIB's color table 00162 * into the logical palette, creating a palette from this logical palette, 00163 * and then returning the palette's handle. This allows the DIB to be 00164 * displayed using the best possible colors (important for DIBs with 256 or 00165 * more colors). 00166 * 00167 ************************************************************************/ 00168 00169 00170 BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal) 00171 { 00172 LPLOGPALETTE lpPal; // pointer to a logical palette 00173 HANDLE hLogPal; // handle to a logical palette 00174 // HPALETTE hPal = NULL; // handle to a palette 00175 int i; // loop index 00176 WORD wNumColors; // number of colors in color table 00177 LPSTR lpbi; // pointer to packed-DIB 00178 LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0) 00179 LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old) 00180 BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB 00181 BOOL bResult = FALSE; 00182 00183 /* if handle to DIB is invalid, return FALSE */ 00184 00185 if (hDIB == NULL) 00186 return FALSE; 00187 00188 lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 00189 00190 /* get pointer to BITMAPINFO (Win 3.0) */ 00191 lpbmi = (LPBITMAPINFO)lpbi; 00192 00193 /* get pointer to BITMAPCOREINFO (old 1.x) */ 00194 lpbmc = (LPBITMAPCOREINFO)lpbi; 00195 00196 /* get the number of colors in the DIB */ 00197 wNumColors = ::DIBNumColors(lpbi); 00198 00199 if (wNumColors != 0) 00200 { 00201 /* allocate memory block for logical palette */ 00202 hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 00203 + sizeof(PALETTEENTRY) 00204 * wNumColors); 00205 00206 /* if not enough memory, clean up and return NULL */ 00207 if (hLogPal == 0) 00208 { 00209 ::GlobalUnlock((HGLOBAL) hDIB); 00210 return FALSE; 00211 } 00212 00213 lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); 00214 00215 /* set version and number of palette entries */ 00216 lpPal->palVersion = PALVERSION; 00217 lpPal->palNumEntries = (WORD)wNumColors; 00218 00219 /* is this a Win 3.0 DIB? */ 00220 bWinStyleDIB = IS_WIN30_DIB(lpbi); 00221 for (i = 0; i < (int)wNumColors; i++) 00222 { 00223 if (bWinStyleDIB) 00224 { 00225 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; 00226 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; 00227 lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; 00228 lpPal->palPalEntry[i].peFlags = 0; 00229 } 00230 else 00231 { 00232 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; 00233 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; 00234 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; 00235 lpPal->palPalEntry[i].peFlags = 0; 00236 } 00237 } 00238 00239 /* create the palette and get handle to it */ 00240 bResult = pPal->CreatePalette(lpPal); 00241 ::GlobalUnlock((HGLOBAL) hLogPal); 00242 ::GlobalFree((HGLOBAL) hLogPal); 00243 } 00244 00245 ::GlobalUnlock((HGLOBAL) hDIB); 00246 00247 return bResult; 00248 } 00249 00250 /************************************************************************* 00251 * 00252 * FindDIBBits() 00253 * 00254 * Parameter: 00255 * 00256 * LPSTR lpbi - pointer to packed-DIB memory block 00257 * 00258 * Return Value: 00259 * 00260 * LPSTR - pointer to the DIB bits 00261 * 00262 * Description: 00263 * 00264 * This function calculates the address of the DIB's bits and returns a 00265 * pointer to the DIB bits. 00266 * 00267 ************************************************************************/ 00268 00269 00270 LPSTR WINAPI FindDIBBits(LPSTR lpbi) 00271 { 00272 return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); 00273 } 00274 00275 00276 /************************************************************************* 00277 * 00278 * DIBWidth() 00279 * 00280 * Parameter: 00281 * 00282 * LPSTR lpbi - pointer to packed-DIB memory block 00283 * 00284 * Return Value: 00285 * 00286 * DWORD - width of the DIB 00287 * 00288 * Description: 00289 * 00290 * This function gets the width of the DIB from the BITMAPINFOHEADER 00291 * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 00292 * width field if it is an other-style DIB. 00293 * 00294 ************************************************************************/ 00295 00296 00297 DWORD WINAPI DIBWidth(LPSTR lpDIB) 00298 { 00299 LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB 00300 LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB 00301 00302 /* point to the header (whether Win 3.0 and old) */ 00303 00304 lpbmi = (LPBITMAPINFOHEADER)lpDIB; 00305 lpbmc = (LPBITMAPCOREHEADER)lpDIB; 00306 00307 /* return the DIB width if it is a Win 3.0 DIB */ 00308 if (IS_WIN30_DIB(lpDIB)) 00309 return lpbmi->biWidth; 00310 else /* it is an other-style DIB, so return its width */ 00311 return (DWORD)lpbmc->bcWidth; 00312 } 00313 00314 00315 /************************************************************************* 00316 * 00317 * DIBHeight() 00318 * 00319 * Parameter: 00320 * 00321 * LPSTR lpbi - pointer to packed-DIB memory block 00322 * 00323 * Return Value: 00324 * 00325 * DWORD - height of the DIB 00326 * 00327 * Description: 00328 * 00329 * This function gets the height of the DIB from the BITMAPINFOHEADER 00330 * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER 00331 * height field if it is an other-style DIB. 00332 * 00333 ************************************************************************/ 00334 00335 00336 DWORD WINAPI DIBHeight(LPSTR lpDIB) 00337 { 00338 LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB 00339 LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB 00340 00341 /* point to the header (whether old or Win 3.0 */ 00342 00343 lpbmi = (LPBITMAPINFOHEADER)lpDIB; 00344 lpbmc = (LPBITMAPCOREHEADER)lpDIB; 00345 00346 /* return the DIB height if it is a Win 3.0 DIB */ 00347 if (IS_WIN30_DIB(lpDIB)) 00348 return lpbmi->biHeight; 00349 else /* it is an other-style DIB, so return its height */ 00350 return (DWORD)lpbmc->bcHeight; 00351 } 00352 00353 00354 /************************************************************************* 00355 * 00356 * PaletteSize() 00357 * 00358 * Parameter: 00359 * 00360 * LPSTR lpbi - pointer to packed-DIB memory block 00361 * 00362 * Return Value: 00363 * 00364 * WORD - size of the color palette of the DIB 00365 * 00366 * Description: 00367 * 00368 * This function gets the size required to store the DIB's palette by 00369 * multiplying the number of colors by the size of an RGBQUAD (for a 00370 * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other- 00371 * style DIB). 00372 * 00373 ************************************************************************/ 00374 00375 00376 WORD WINAPI PaletteSize(LPSTR lpbi) 00377 { 00378 /* calculate the size required by the palette */ 00379 if (IS_WIN30_DIB (lpbi)) 00380 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); 00381 else 00382 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 00383 } 00384 00385 00386 /************************************************************************* 00387 * 00388 * DIBNumColors() 00389 * 00390 * Parameter: 00391 * 00392 * LPSTR lpbi - pointer to packed-DIB memory block 00393 * 00394 * Return Value: 00395 * 00396 * WORD - number of colors in the color table 00397 * 00398 * Description: 00399 * 00400 * This function calculates the number of colors in the DIB's color table 00401 * by finding the bits per pixel for the DIB (whether Win3.0 or other-style 00402 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, 00403 * if 24, no colors in color table. 00404 * 00405 ************************************************************************/ 00406 00407 00408 WORD WINAPI DIBNumColors(LPSTR lpbi) 00409 { 00410 WORD wBitCount; // DIB bit count 00411 00412 /* If this is a Windows-style DIB, the number of colors in the 00413 * color table can be less than the number of bits per pixel 00414 * allows for (i.e. lpbi->biClrUsed can be set to some value). 00415 * If this is the case, return the appropriate value. 00416 */ 00417 00418 if (IS_WIN30_DIB(lpbi)) 00419 { 00420 DWORD dwClrUsed; 00421 00422 dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; 00423 if (dwClrUsed != 0) 00424 return (WORD)dwClrUsed; 00425 } 00426 00427 /* Calculate the number of colors in the color table based on 00428 * the number of bits per pixel for the DIB. 00429 */ 00430 if (IS_WIN30_DIB(lpbi)) 00431 wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 00432 else 00433 wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; 00434 00435 /* return number of colors based on bits per pixel */ 00436 switch (wBitCount) 00437 { 00438 case 1: 00439 return 2; 00440 00441 case 4: 00442 return 16; 00443 00444 case 8: 00445 return 256; 00446 00447 default: 00448 return 0; 00449 } 00450 } 00451 00452 00455 00456 //--------------------------------------------------------------------- 00457 // 00458 // Function: CopyHandle (from SDK DibView sample clipbrd.c) 00459 // 00460 // Purpose: Makes a copy of the given global memory block. Returns 00461 // a handle to the new memory block (NULL on error). 00462 // 00463 // Routine stolen verbatim out of ShowDIB. 00464 // 00465 // Parms: h == Handle to global memory to duplicate. 00466 // 00467 // Returns: Handle to new global memory block. 00468 // 00469 //--------------------------------------------------------------------- 00470 00471 HGLOBAL WINAPI CopyHandle (HGLOBAL h) 00472 { 00473 if (h == NULL) 00474 return NULL; 00475 00476 SIZE_T dwLen = ::GlobalSize((HGLOBAL) h); 00477 HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); 00478 00479 if (hCopy != NULL) 00480 { 00481 void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 00482 void* lp = ::GlobalLock((HGLOBAL) h); 00483 memcpy(lpCopy, lp, dwLen); 00484 ::GlobalUnlock(hCopy); 00485 ::GlobalUnlock(h); 00486 } 00487 00488 return hCopy; 00489 }