home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 May / cica_0595_4.zip / cica_0595_4 / UTIL / MSWSRC35 / DIB.CPP < prev    next >
C/C++ Source or Header  |  1993-10-01  |  14KB  |  456 lines

  1.  
  2. //-----------------------------------------------------------------------------
  3. // DIB.C
  4. //
  5. // This is a collection of useful DIB manipulation/information gathering
  6. // functions.  Many functions are supplied simply to take the burden
  7. // of taking into account whether a DIB is a Win30 style or OS/2 style
  8. // DIB away from the application.
  9. //
  10. // The functions in this module assume that the DIB pointers or handles
  11. // passed to them point to a block of memory in one of two formats:
  12. //
  13. //       a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB)
  14. //       b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style)
  15. //
  16. // The SDK Reference, Volume 2 describes these data structures.
  17. //
  18. // A number of functions in this module were lifted from SHOWDIB,
  19. // and modified to handle OS/2 DIBs.
  20. //
  21. // The functions in this module could be streamlined (made faster and
  22. // smaller) by removing the OS/2 DIB specific code, and assuming all
  23. // DIBs passed to it are Win30 style DIBs.  The DIB file reading code
  24. // would need to be modified to always convert DIBs to Win30 style
  25. // DIBs.  The only reason this isn't done in DIBView is because DIBView
  26. // was written to test display and printer drivers (which are supposed
  27. // to support OS/2 DIBs wherever they support Win30 style DIBs).  SHOWDIB
  28. // is a great example of how to go about doing this.
  29. //-----------------------------------------------------------------------------
  30.  
  31.  
  32. #include "allwind.h"
  33. #include "dib.h"
  34.  
  35. #define PALVERSION 0x300
  36.  
  37. extern LPSTR FindDIBBits (LPSTR lpbi);
  38. extern WORD DIBNumColors (LPSTR lpbi);
  39. extern WORD PaletteSize (LPSTR lpbi);
  40. extern DWORD DIBHeight (LPSTR lpDIB);
  41. extern DWORD DIBWidth (LPSTR lpDIB);
  42. extern HBITMAP DIBToBitmap (HANDLE hDIB, HPALETTE hPal);
  43. extern void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,DWORD dwWidth,DWORD dwHeight,int nBPP);
  44. extern HANDLE BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal);
  45.  
  46. //---------------------------------------------------------------------
  47. //
  48. // Function:   FindDIBBits
  49. //
  50. // Purpose:    Given a pointer to a DIB, returns a pointer to the
  51. //             DIB's bitmap bits.
  52. //
  53. // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
  54. //                       or BITMAPCOREHEADER)
  55. //
  56. // History:   Date      Reason
  57. //             6/01/91  Created
  58. //
  59. //---------------------------------------------------------------------
  60.  
  61. LPSTR FindDIBBits (LPSTR lpbi)
  62. {
  63.    return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi));
  64. }
  65.  
  66.  
  67.  
  68.  
  69. //---------------------------------------------------------------------
  70. //
  71. // Function:   DIBNumColors
  72. //
  73. // Purpose:    Given a pointer to a DIB, returns a number of colors in
  74. //             the DIB's color table.
  75. //
  76. // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
  77. //                       or BITMAPCOREHEADER)
  78. //
  79. // History:   Date      Reason
  80. //             6/01/91  Created
  81. //
  82. //---------------------------------------------------------------------
  83.  
  84. WORD DIBNumColors (LPSTR lpbi)
  85. {
  86.    WORD wBitCount;
  87.  
  88.  
  89.       // If this is a Windows style DIB, the number of colors in the
  90.       //  color table can be less than the number of bits per pixel
  91.       //  allows for (i.e. lpbi->biClrUsed can be set to some value).
  92.       //  If this is the case, return the appropriate value.
  93.  
  94.    if (IS_WIN30_DIB (lpbi))
  95.       {
  96.       DWORD dwClrUsed;
  97.  
  98.       dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
  99.  
  100.       if (dwClrUsed)
  101.          return (WORD) dwClrUsed;
  102.       }
  103.  
  104.  
  105.       // Calculate the number of colors in the color table based on
  106.       //  the number of bits per pixel for the DIB.
  107.  
  108.    if (IS_WIN30_DIB (lpbi))
  109.       wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
  110.    else
  111.       wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
  112.  
  113.    switch (wBitCount)
  114.       {
  115.       case 1:
  116.          return 2;
  117.  
  118.       case 4:
  119.          return 16;
  120.  
  121.       case 8:
  122.          return 256;
  123.  
  124.       default:
  125.          return 0;
  126.       }
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133. //---------------------------------------------------------------------
  134. //
  135. // Function:   PaletteSize
  136. //
  137. // Purpose:    Given a pointer to a DIB, returns number of bytes
  138. //             in the DIB's color table.
  139. //
  140. // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
  141. //                       or BITMAPCOREHEADER)
  142. //
  143. // History:   Date      Reason
  144. //             6/01/91  Created
  145. //
  146. //---------------------------------------------------------------------
  147.  
  148. WORD PaletteSize (LPSTR lpbi)
  149. {
  150.    if (IS_WIN30_DIB (lpbi))
  151.       return (DIBNumColors (lpbi) * sizeof (RGBQUAD));
  152.    else
  153.       return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE));
  154. }
  155.  
  156.  
  157.  
  158.  
  159. //---------------------------------------------------------------------
  160. //
  161. // Function:   DIBHeight
  162. //
  163. // Purpose:    Given a pointer to a DIB, returns its height.  Note
  164. //             that it returns a DWORD (since a Win30 DIB can have
  165. //             a DWORD in its height field), but under Win30, the
  166. //             high order word isn't used!
  167. //
  168. // Parms:      lpDIB == pointer to DIB header (either BITMAPINFOHEADER
  169. //                       or BITMAPCOREHEADER)
  170. //
  171. // History:   Date      Reason
  172. //             6/01/91  Created
  173. //
  174. //---------------------------------------------------------------------
  175.  
  176. DWORD DIBHeight (LPSTR lpDIB)
  177. {
  178.    LPBITMAPINFOHEADER lpbmi;
  179.    LPBITMAPCOREHEADER lpbmc;
  180.  
  181.    lpbmi = (LPBITMAPINFOHEADER) lpDIB;
  182.    lpbmc = (LPBITMAPCOREHEADER) lpDIB;
  183.  
  184.    if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
  185.       return lpbmi->biHeight;
  186.    else
  187.       return (DWORD) lpbmc->bcHeight;
  188. }
  189.  
  190.  
  191.  
  192. //---------------------------------------------------------------------
  193. //
  194. // Function:   DIBWidth
  195. //
  196. // Purpose:    Given a pointer to a DIB, returns its width.  Note
  197. //             that it returns a DWORD (since a Win30 DIB can have
  198. //             a DWORD in its width field), but under Win30, the
  199. //             high order word isn't used!
  200. //
  201. // Parms:      lpDIB == pointer to DIB header (either BITMAPINFOHEADER
  202. //                       or BITMAPCOREHEADER)
  203. //
  204. // History:   Date      Reason
  205. //             6/01/91  Created
  206. //
  207. //---------------------------------------------------------------------
  208.  
  209. DWORD DIBWidth (LPSTR lpDIB)
  210. {
  211.    LPBITMAPINFOHEADER lpbmi;
  212.    LPBITMAPCOREHEADER lpbmc;
  213.  
  214.    lpbmi = (LPBITMAPINFOHEADER) lpDIB;
  215.    lpbmc = (LPBITMAPCOREHEADER) lpDIB;
  216.  
  217.    if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
  218.       return lpbmi->biWidth;
  219.    else
  220.       return (DWORD) lpbmc->bcWidth;
  221. }
  222.  
  223.  
  224.  
  225.  
  226. //---------------------------------------------------------------------
  227. //
  228. // Function:   DIBToBitmap
  229. //
  230. // Purpose:    Given a handle to global memory with a DIB spec in it,
  231. //             and a palette, returns a device dependent bitmap.  The
  232. //             The DDB will be rendered with the specified palette.
  233. //
  234. // Parms:      hDIB == HANDLE to global memory containing a DIB spec
  235. //                     (either BITMAPINFOHEADER or BITMAPCOREHEADER)
  236. //             hPal == Palette to render the DDB with.  If it's NULL,
  237. //                     use the default palette.
  238. //
  239. // History:   Date      Reason
  240. //             6/01/91  Created
  241. //
  242. //---------------------------------------------------------------------
  243.  
  244. HBITMAP DIBToBitmap (HANDLE hDIB, HPALETTE hPal)
  245. {
  246.    LPSTR    lpDIBHdr, lpDIBBits;
  247.    HBITMAP  hBitmap;
  248.    HDC      hDC;
  249.    HPALETTE hOldPal = NULL;
  250.  
  251.    if (!hDIB)
  252.       return NULL;
  253.  
  254.    lpDIBHdr  = (char *)GlobalLock (hDIB);
  255.    lpDIBBits = FindDIBBits (lpDIBHdr);
  256.    hDC       = GetDC (NULL);
  257.  
  258.    if (!hDC)
  259.       {
  260.       GlobalUnlock (hDIB);
  261.       return NULL;
  262.       }
  263.  
  264.    if (hPal)
  265.       hOldPal = SelectPalette (hDC, hPal, FALSE);
  266.  
  267.    RealizePalette (hDC);
  268.  
  269.    hBitmap = CreateDIBitmap (hDC,
  270.                              (LPBITMAPINFOHEADER) lpDIBHdr,
  271.                              CBM_INIT,
  272.                              lpDIBBits,
  273.                              (LPBITMAPINFO) lpDIBHdr,
  274.                              DIB_RGB_COLORS);
  275.  
  276.    if (!hBitmap)
  277.         MessageBox(MainHWindow, "Not Enough Memory", "Error", MB_OK | MB_ICONEXCLAMATION);
  278. //      DIBError (ERR_CREATEDDB);
  279.  
  280.    if (hOldPal)
  281.       SelectPalette (hDC, hOldPal, FALSE);
  282.  
  283.    ReleaseDC (NULL, hDC);
  284.    GlobalUnlock (hDIB);
  285.  
  286.    return hBitmap;
  287. }
  288.  
  289.  
  290.  
  291.  
  292. //---------------------------------------------------------------------
  293. //
  294. // Function:   InitBitmapInfoHeader
  295. //
  296. // Purpose:    Does a "standard" initialization of a BITMAPINFOHEADER,
  297. //             given the Width, Height, and Bits per Pixel for the
  298. //             DIB.
  299. //
  300. //             By standard, I mean that all the relevant fields are set
  301. //             to the specified values.  biSizeImage is computed, the
  302. //             biCompression field is set to "no compression," and all
  303. //             other fields are 0.
  304. //
  305. //             Note that DIBs only allow BitsPixel values of 1, 4, 8, or
  306. //             24.  This routine makes sure that one of these values is
  307. //             used (whichever is most appropriate for the specified
  308. //             nBPP).
  309. //
  310. // Parms:      lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
  311. //                            to be filled in.
  312. //             dwWidth     == Width of DIB (not in Win 3.0 & 3.1, high
  313. //                            word MUST be 0).
  314. //             dwHeight    == Height of DIB (not in Win 3.0 & 3.1, high
  315. //                            word MUST be 0).
  316. //             nBPP        == Bits per Pixel for the DIB.
  317. //
  318. // History:   Date      Reason
  319. //            11/07/91  Created
  320. //
  321. //---------------------------------------------------------------------
  322.  
  323. void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
  324.                                         DWORD dwWidth,
  325.                                         DWORD dwHeight,
  326.                                           int nBPP)
  327. {
  328.    _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));
  329.  
  330.    lpBmInfoHdr->biSize      = sizeof (BITMAPINFOHEADER);
  331.    lpBmInfoHdr->biWidth     = dwWidth;
  332.    lpBmInfoHdr->biHeight    = dwHeight;
  333.    lpBmInfoHdr->biPlanes    = 1;
  334.  
  335.    if (nBPP <= 1)
  336.       nBPP = 1;
  337.    else if (nBPP <= 4)
  338.       nBPP = 4;
  339.    else if (nBPP <= 8)
  340.       nBPP = 8;
  341.    else
  342.       nBPP = 24;
  343.  
  344.    lpBmInfoHdr->biBitCount  = nBPP;
  345.    lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
  346. }
  347.  
  348.  
  349.  
  350.  
  351. //---------------------------------------------------------------------
  352. //
  353. // Function:   BitmapToDIB
  354. //
  355. // Purpose:    Given a device dependent bitmap and a palette, returns
  356. //             a handle to global memory with a DIB spec in it.  The
  357. //             DIB is rendered using the colors of the palette passed in.
  358. //
  359. //             Stolen almost verbatim from ShowDIB.
  360. //
  361. // Parms:      hBitmap == Handle to device dependent bitmap compatible
  362. //                        with default screen display device.
  363. //             hPal    == Palette to render the DDB with.  If it's NULL,
  364. //                        use the default palette.
  365. //
  366. // History:   Date      Reason
  367. //             6/01/91  Created
  368. //
  369. //---------------------------------------------------------------------
  370.  
  371. HANDLE BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal)
  372. {
  373.    BITMAP             Bitmap;
  374.    BITMAPINFOHEADER   bmInfoHdr;
  375.    LPBITMAPINFOHEADER lpbmInfoHdr;
  376.    LPSTR              lpBits;
  377.    HDC                hMemDC;
  378.    HANDLE             hDIB;
  379.    HPALETTE           hOldPal = NULL;
  380.  
  381.       // Do some setup -- make sure the Bitmap passed in is valid,
  382.       //  get info on the bitmap (like its height, width, etc.),
  383.       //  then setup a BITMAPINFOHEADER.
  384.  
  385.    if (!hBitmap)
  386.       return NULL;
  387.  
  388.    if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap))
  389.       return NULL;
  390.  
  391.    InitBitmapInfoHeader (&bmInfoHdr,
  392.                          Bitmap.bmWidth,
  393.                          Bitmap.bmHeight,
  394.                          Bitmap.bmPlanes * Bitmap.bmBitsPixel);
  395.  
  396.  
  397.       // Now allocate memory for the DIB.  Then, set the BITMAPINFOHEADER
  398.       //  into this memory, and find out where the bitmap bits go.
  399.  
  400.    hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) +
  401.              PaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage);
  402.  
  403.    if (!hDIB)
  404.       return NULL;
  405.  
  406.    lpbmInfoHdr  = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
  407.    *lpbmInfoHdr = bmInfoHdr;
  408.    lpBits       = FindDIBBits ((LPSTR) lpbmInfoHdr);
  409.  
  410.  
  411.       // Now, we need a DC to hold our bitmap.  If the app passed us
  412.       //  a palette, it should be selected into the DC.
  413.  
  414.    hMemDC       = GetDC (NULL);
  415.  
  416.    if (hPal)
  417.       {
  418.       hOldPal = SelectPalette (hMemDC, hPal, FALSE);
  419.       RealizePalette (hMemDC);
  420.       }
  421.  
  422.  
  423.  
  424.       // We're finally ready to get the DIB.  Call the driver and let
  425.       //  it party on our bitmap.  It will fill in the color table,
  426.       //  and bitmap bits of our global memory block.
  427.  
  428.    if (!GetDIBits (hMemDC,
  429.                    hBitmap,
  430.                    0,
  431.                    Bitmap.bmHeight,
  432.                    lpBits,
  433.                    (LPBITMAPINFO) lpbmInfoHdr,
  434.                    DIB_RGB_COLORS))
  435.       {
  436.       GlobalUnlock (hDIB);
  437.       GlobalFree (hDIB);
  438.       hDIB = NULL;
  439.       }
  440.    else
  441.       GlobalUnlock (hDIB);
  442.  
  443.  
  444.       // Finally, clean up and return.
  445.  
  446.    if (hOldPal)
  447.       SelectPalette (hMemDC, hOldPal, FALSE);
  448.  
  449.    ReleaseDC (NULL, hMemDC);
  450.  
  451.    return hDIB;
  452. }
  453.  
  454.  
  455.  
  456.