home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / WBITMAP.ZIP / BMMANIP.C < prev    next >
C/C++ Source or Header  |  1991-11-12  |  14KB  |  650 lines

  1. /*
  2. **    $id: ssvcid bmmanip.c 1.1 11/12/91  8:38 am$
  3. **        This file contains various functions for manipulating bitmaps.
  4. **
  5. **    (C) 1991    Larry Widing
  6. */
  7. #include    <windows.h>
  8. #include    <dos.h>
  9. #include    <malloc.h>
  10. #include    "bitmaps.h"
  11.  
  12. /*
  13. ** int                                                number of color entries in header
  14. ** DIBitmapColors(BITMAPINFO FAR *bmi);    pointer to bitmap header
  15. **
  16. **    This function returns the number of colors in the color table of
  17. **    the specified Device-Independant Bitmap.
  18. **
  19. ** Modification History:
  20. ** 09/12/91  LCW  Created
  21. */
  22. int
  23. DIBitmapColors(BITMAPINFO FAR *bmi)
  24. {
  25.     if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  26.     {
  27.         /*
  28.         **    OS/2 PM Bitmap, use bcBitCount field to determine colors
  29.         */
  30.         switch (((BITMAPCOREINFO FAR *)bmi)->bmciHeader.bcBitCount)
  31.         {
  32.             case 1:
  33.                 return 2;    /* Monochrome bitmap -> 2 colors */
  34.  
  35.             case 4:
  36.                 return 16;    /* 4-bit image -> 16 colors */
  37.  
  38.             case 8:
  39.                 return 256;    /* 8-bit image -> 256 colors */
  40.  
  41.             case 24:
  42.                 return 0;    /* 24-bt image -> 0 colors in color table */
  43.         }
  44.     }
  45.     else
  46.     {
  47.         /*
  48.         **    Windows bitmap
  49.         */
  50.         if (bmi->bmiHeader.biClrUsed == 0)
  51.         {
  52.             /* Maximum number of entries */
  53.             switch (bmi->bmiHeader.biBitCount)
  54.             {
  55.                 case 1:
  56.                     return 2;    /* Monochrome bitmap -> 2 colors */
  57.  
  58.                 case 4:
  59.                     return 16;    /* 4-bit image -> 16 colors */
  60.  
  61.                 case 8:
  62.                     return 256;    /* 8-bit image -> 256 colors */
  63.  
  64.                 case 24:
  65.                     return 0;    /* 24-bt image -> 0 colors in color table */
  66.             }
  67.         }
  68.         else
  69.         {
  70.             return (int)bmi->bmiHeader.biClrUsed;
  71.         }
  72.     }
  73.  
  74.     return 0;
  75. }
  76.  
  77. /*
  78. ** LPSTR                                            pointer to bitmap bits
  79. ** DIBitmapBits(BITMAPINFO FAR *bmi);    pointer to bitmap header
  80. **
  81. **    This function returns a pointer to the bits in a packed Device-
  82. **    Independant Bitmap.
  83. **
  84. ** Modification History:
  85. ** 09/12/91  LCW  Created
  86. */
  87. LPSTR
  88. DIBitmapBits(BITMAPINFO FAR *bmi)
  89. {
  90.     LPSTR    bits;
  91.     int    colors = DIBitmapColors(bmi);
  92.  
  93.     bits = ((LPSTR)bmi) + bmi->bmiHeader.biSize;
  94.  
  95.     if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  96.     {
  97.         bits += colors * sizeof(RGBTRIPLE);
  98.     }
  99.     else
  100.     {
  101.         bits += colors * sizeof(RGBQUAD);
  102.     }
  103.  
  104.     return bits;
  105. }
  106.  
  107. /*
  108. ** BOOL                    TRUE if successful, FALSE otherwise
  109. ** DrawBitmap(
  110. **   HDC hdc,            Handle of target device context
  111. **   int x,                X coordinate to draw bitmap at
  112. **   int y,                Y coordinate to draw bitmap at
  113. **   HBITMAP hbm);    Handle of bitmap to draw
  114. **
  115. **    This function draws the specified bitmap onto the target device
  116. **    context at the given coordinates.  If an error occurs, the FALSE will
  117. **    be returned to the caller, otherwise TRUE will be returned if the
  118. **    bitmap was drawn without a problem.
  119. **
  120. ** Modification History:
  121. ** 09/09/91  LCW  Created
  122. */
  123. BOOL
  124. DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm)
  125. {
  126.     HDC        hdcMem;            /* Handle of memory context to use in drawing bitmap */
  127.     HBITMAP    oldBm;
  128.     POINT        ptSize, ptOrg;
  129.     BITMAP    bm;
  130.  
  131.     hdcMem = CreateCompatibleDC(hdc);
  132.     if (hdcMem != (HDC)NULL)
  133.     {
  134.         /*
  135.         **    Select bitmap to be draw into memory context
  136.         */
  137.         oldBm = SelectObject(hdcMem, hbm);
  138.  
  139.         /*
  140.         **    Set the mapping mode for the memory context to match the
  141.         **    target device context.
  142.         */
  143.         SetMapMode(hdcMem, GetMapMode(hdc));
  144.  
  145.         /*
  146.         **    Get the details of the bitmap being drawn
  147.         */
  148.         GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm);
  149.  
  150.         /*
  151.         **    Adjust height and width for mapping mode
  152.         */
  153.         ptSize.x = bm.bmWidth;
  154.         ptSize.y = bm.bmHeight;
  155.         DPtoLP(hdc, (LPPOINT)&ptSize, 1);
  156.  
  157.         /*
  158.         **    Adjust origin for mapping mode
  159.         */
  160.         ptOrg.x = 0;
  161.         ptOrg.y = 0;
  162.         DPtoLP(hdcMem, (LPPOINT)&ptOrg, 1);
  163.  
  164.         /*
  165.         **    Draw the bitmap
  166.         */
  167.         BitBlt(hdc, x, y, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y, SRCCOPY);
  168.  
  169.         /*
  170.         **    Clean up
  171.         */
  172.         SelectObject(hdcMem, oldBm);
  173.         DeleteDC(hdcMem);
  174.  
  175.         return TRUE;
  176.     }
  177.     return FALSE;
  178. }
  179.  
  180. /*
  181. ** BOOL                    TRUE if successful, FALSE if an error occurred
  182. ** DrawDIBitmap(
  183. **   HDC hdc,            Handle of target device context
  184. **   int x,                X coordinate to draw bitmap at
  185. **   int y,                Y coordinate to draw bitmap at
  186. **   HANDLE hbm);        Handle of memory block holding packed DIB
  187. **
  188. **    This function draws the specified DI bitmap onto the target device
  189. **    context at the given coordinates.  If an error occurs, the FALSE will
  190. **    be returned to the caller, otherwise TRUE will be returned if the DI
  191. **    bitmap was drawn without a problem.
  192. **
  193. ** Modification History:
  194. ** 09/09/91  LCW  Created
  195. */
  196. BOOL
  197. DrawDIBitmap(HDC hdc, int x, int y, HANDLE hbm)
  198. {
  199.     int                width, height;
  200.     BITMAPINFO FAR    *bmi;
  201.     LPSTR                bits;
  202.  
  203.     bmi = (BITMAPINFO FAR *)GlobalLock(hbm);
  204.     if (bmi != NULL)
  205.     {
  206.         bits = DIBitmapBits(bmi);
  207.  
  208.         if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  209.         {
  210.             width = ((BITMAPCOREINFO FAR *)bmi)->bmciHeader.bcWidth;
  211.             height = ((BITMAPCOREINFO FAR *)bmi)->bmciHeader.bcHeight;
  212.         }
  213.         else
  214.         {
  215.             width = (WORD)bmi->bmiHeader.biWidth;
  216.             height = (WORD)bmi->bmiHeader.biHeight;
  217.         }
  218.  
  219.         SetDIBitsToDevice(hdc, x, y, width, height, 0, 0, 0, height, bits,
  220.             bmi, DIB_RGB_COLORS);
  221.  
  222.         GlobalUnlock(hbm);
  223.  
  224.         return TRUE;
  225.     }
  226.  
  227.     return FALSE;
  228. }
  229.  
  230. /*
  231. ** HBITMAP                            Handle of duplicate if it could be created
  232. ** CopyBitmap(HBITMAP hbm);    Handle of bitmap to copy
  233. **
  234. **    This function will create a duplicate of the passed bitmap, returning
  235. **    the handle of the new bitmap if successful, and NULL if it could not
  236. **    perform the copy.
  237. **
  238. ** Modification History:
  239. ** 09/09/91  LCW  Created
  240. */
  241. HBITMAP
  242. CopyBitmap(HBITMAP hbm)
  243. {
  244.     HBITMAP    hbmNew = (HBITMAP)NULL;
  245.     HBITMAP    oldBm;
  246.     HDC        hdcMem;
  247.     BITMAP    bm;
  248.  
  249.     GetObject(hbm, sizeof(bm), (LPSTR)&bm);
  250.     hdcMem = CreateCompatibleDC(NULL);
  251.     if (hdcMem != (HDC)NULL)
  252.     {
  253.         oldBm = SelectObject(hdcMem, hbm);
  254.         hbmNew = CreateCompatibleBitmap(hdcMem, bm.bmWidth, bm.bmHeight);
  255.         if (hbmNew != (HBITMAP)NULL)
  256.         {
  257.             SelectObject(hdcMem, hbmNew);
  258.             DrawBitmap(hdcMem, 0, 0, hbm);
  259.         }
  260.         SelectObject(hdcMem, oldBm);
  261.         DeleteDC(hdcMem);
  262.     }
  263.  
  264.     return hbmNew;
  265. }
  266.  
  267. /*
  268. ** HANDLE                            Handle of newly created DI Bitmap
  269. ** CopyDIBitmap(HANDLE hbm);    Handle of DI Bitmap to copy
  270. **
  271. **    This function will create a dupilicate of the passed packed DI Bitmap,
  272. **    returning a handle to the newly created memory block.  If the copy could
  273. **    not be performed, then NULL is returned.
  274. **
  275. ** Modification History:
  276. ** 09/09/91  LCW  Created
  277. */
  278. HANDLE
  279. CopyDIBitmap(HANDLE hbm)
  280. {
  281.     DWORD        size;
  282.     HANDLE    hbmNew;
  283.  
  284.     size = GlobalSize(hbm);
  285.     if (size != 0)
  286.     {
  287.         hbmNew = GlobalAlloc(GMEM_MOVEABLE, size);
  288.         if (hbmNew != (HANDLE)NULL)
  289.         {
  290.             BYTE HUGE *src;
  291.             BYTE HUGE *dest;
  292.  
  293.             src = (BYTE HUGE *)GlobalLock(hbm);
  294.             if (src != NULL)
  295.             {
  296.                 dest = (BYTE HUGE *)GlobalLock(hbmNew);
  297.                 if (dest != NULL)
  298.                 {
  299.                     while (size != 0)
  300.                     {
  301.                         *dest = *src;
  302. #if    defined(__TSC__)
  303.                         if (FP_OFF(dest) == 0xffff)
  304.                         {
  305.                             dest = MK_FP(FP_SEG(dest) + 8, 0);
  306.                         }
  307.                         else
  308.                             ++dest;
  309.  
  310.                         if (FP_OFF(src) == 0xffff)
  311.                         {
  312.                             src = MK_FP(FP_SEG(src) + 8, 0);
  313.                         }
  314.                         else
  315.                             ++src;
  316. #else
  317.                         ++dest;
  318.                         ++src;
  319. #endif
  320.                         --size;
  321.                     }
  322.                     GlobalUnlock(hbmNew);
  323.                 }
  324.                 else
  325.                 {
  326.                     GlobalFree(hbmNew);
  327.                     hbmNew = (HANDLE)NULL;
  328.                 }
  329.                 GlobalUnlock(hbm);
  330.             }
  331.         }
  332.     }
  333.  
  334.     return hbmNew;
  335. }
  336.  
  337. /*
  338. ** HBITMAP                            handle of logical bitmap created, or NULL
  339. ** DibToBitmap(HANDLE hbm);    handle of packed DIB to convert
  340. **
  341. **    This function converts a packed DIB into a logical bitmap, returning
  342. **    a handle to the resulting bitmap.
  343. **
  344. ** Modification History:
  345. ** 10/16/91  LCW  Created
  346. */
  347. HBITMAP
  348. DibToBitmap(HANDLE hbm)
  349. {
  350.     HBITMAP            bm = (HBITMAP)NULL;
  351.     HDC                hdc;
  352.     BITMAPINFO FAR    *bmi;
  353.     LPSTR                bits;
  354.  
  355.     bmi = (BITMAPINFO FAR *)GlobalLock(hbm);
  356.     if (bmi != NULL)
  357.     {
  358.         hdc = GetDC(MainWindow);
  359.         if (hdc != (HDC)NULL)
  360.         {
  361.             bits = DIBitmapBits(bmi);
  362.  
  363.             bm = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)bmi, CBM_INIT,
  364.                 bits, bmi, DIB_RGB_COLORS);
  365.  
  366.             ReleaseDC(MainWindow, hdc);
  367.         }
  368.  
  369.         GlobalUnlock(hbm);
  370.     }
  371.  
  372.     return bm;
  373. }
  374.  
  375. /*
  376. ** HANDLE                handle of new packed DIB (NULL if an error occurred)
  377. ** BitmapToDIB(
  378. **   HBITMAP hbm,        handle of logical bitmap to convert
  379. **   int mode);        mode to use when converting
  380. **
  381. **    This function will convert a logical bitmap into a packed Device
  382. **    Independant Bitmap, using the mode parameter to determine if the resulting
  383. **    DIB should be run length encoded (mode == 1), a OS/2 compatible DIB
  384. **    (mode == 2) or a unencoded DIB (mode == 0).
  385. **
  386. ** Modification History:
  387. ** 09/07/91  LCW  Created
  388. */
  389. HANDLE
  390. BitmapToDIB(HBITMAP hbm, int mode)
  391. {
  392.     int                i;
  393.     HDC                hdc;
  394.     HANDLE            result = (HANDLE)NULL;
  395.     BITMAPINFO        *bmi;
  396.     BITMAPCOREINFO    *bmci;
  397.     LPSTR                ptr, sptr, dptr;
  398.     int                hdrSize;
  399.     int                bitsPerPixel;
  400.     BITMAP            bm;
  401.  
  402.     /*
  403.     **    Get bitmap information
  404.     */
  405.     GetObject(hbm, sizeof(bm), (LPSTR)&bm);
  406.     if (bm.bmPlanes == 1)
  407.         bitsPerPixel = bm.bmBitsPixel;
  408.     else
  409.         bitsPerPixel = bm.bmPlanes;
  410.  
  411.  
  412.     if (mode == 2)
  413.     {
  414.         /*
  415.         **    Building a OS/2 bitmap - allocate a LPBITMAPCOREINFO record
  416.         */
  417.         hdrSize = sizeof(BITMAPCOREHEADER);
  418.         switch (bitsPerPixel)
  419.         {
  420.             case 1:
  421.                 hdrSize += 2 * sizeof(RGBTRIPLE);
  422.                 break;
  423.  
  424.             case 3:
  425.                 ++bitsPerPixel;
  426.             case 4:
  427.                 hdrSize += 16 * sizeof(RGBTRIPLE);
  428.                 break;
  429.  
  430.             case 8:
  431.                 hdrSize += 256 * sizeof(RGBTRIPLE);
  432.                 break;
  433.         }
  434.         bmci = (BITMAPCOREINFO *)malloc(hdrSize);
  435.         bmci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
  436.         bmci->bmciHeader.bcWidth = bm.bmWidth;
  437.         bmci->bmciHeader.bcHeight = bm.bmHeight;
  438.         bmci->bmciHeader.bcPlanes = 1;
  439.         bmci->bmciHeader.bcBitCount = bitsPerPixel;
  440.         bmi = NULL;
  441.     }
  442.     else
  443.     {
  444.         /*
  445.         **    Building a Windows compatible Bitmap
  446.         */
  447.         hdrSize = sizeof(BITMAPINFOHEADER);
  448.  
  449.         switch (bitsPerPixel)
  450.         {
  451.             case 1:
  452.                 hdrSize += 2 * sizeof(RGBQUAD);
  453.                 break;
  454.  
  455.             case 3:
  456.                 ++bitsPerPixel;
  457.             case 4:
  458.                 hdrSize += 16 * sizeof(RGBQUAD);
  459.                 break;
  460.  
  461.             case 8:
  462.                 hdrSize += 256 * sizeof(RGBQUAD);
  463.                 break;
  464.         }
  465.         bmi = (BITMAPINFO *)malloc(hdrSize);
  466.  
  467.         bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  468.         bmi->bmiHeader.biWidth = bm.bmWidth;
  469.         bmi->bmiHeader.biHeight = bm.bmHeight;
  470.         bmi->bmiHeader.biPlanes = 1;
  471.         bmi->bmiHeader.biBitCount = bitsPerPixel;
  472.         if (mode == 0 || (bitsPerPixel != 8 && bitsPerPixel != 4))
  473.             bmi->bmiHeader.biCompression = BI_RGB;
  474.         else if (bitsPerPixel == 8)
  475.             bmi->bmiHeader.biCompression = BI_RLE8;
  476.         else
  477.             bmi->bmiHeader.biCompression = BI_RLE4;
  478.         bmi->bmiHeader.biSizeImage = 0;
  479.         bmi->bmiHeader.biXPelsPerMeter = 0;
  480.         bmi->bmiHeader.biYPelsPerMeter = 0;
  481.         bmi->bmiHeader.biClrUsed = 0;
  482.         bmi->bmiHeader.biClrImportant = 0;
  483.         bmci = NULL;
  484.     }
  485.  
  486.     /*
  487.     **    Get a DC to use
  488.     */
  489.     hdc = GetDC(MainWindow);
  490.     if (hdc != (HDC)NULL)
  491.     {
  492.         /*
  493.         **    Allocate storage needed
  494.         */
  495.         if (bmi == NULL)
  496.         {
  497.             DWORD    bitSize = (DWORD)bm.bmWidth * (DWORD)bitsPerPixel / 8;
  498.             if ((bitSize & 3) != 0)
  499.                 bitSize += 4 - (bitSize & 3);
  500.                 
  501.             result = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  502.                 (long)hdrSize + (DWORD)bm.bmHeight * bitSize);
  503.  
  504.             if (result != (HANDLE)NULL)
  505.             {
  506.                 ptr = (LPSTR)GlobalLock(result);
  507.                 if (ptr == NULL)
  508.                 {
  509.                     GlobalFree(result);
  510.                     result = (HANDLE)NULL;
  511.                     ErrorBox("BitmapToDIB(): Unable to lock DIB memory");
  512.                 }
  513.                 else
  514.                 {
  515.                     sptr = (LPSTR)bmci;
  516.                 }
  517.             }
  518.         }
  519.         else
  520.         {
  521.             if (GetDIBits(hdc, hbm, 0, bm.bmHeight, NULL, (LPBITMAPINFO)bmi, DIB_RGB_COLORS))
  522.             {
  523.                 result = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  524.                     (long)hdrSize + bmi->bmiHeader.biSizeImage);
  525.  
  526.                 if (result != (HANDLE)NULL)
  527.                 {
  528.                     ptr = (LPSTR)GlobalLock(result);
  529.                     if (ptr == NULL)
  530.                     {
  531.                         GlobalFree(result);
  532.                         result = (HANDLE)NULL;
  533.                         ErrorBox("BitmapToDIB(): Unable to lock DIB memory");
  534.                     }
  535.                     else
  536.                     {
  537.                         sptr = (LPSTR)bmi;
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.  
  543.         if (result)
  544.         {
  545.             /*
  546.             **    Copy header
  547.             */
  548.             dptr = ptr;
  549.             for (i = 0 ; i < hdrSize ; ++i)
  550.             {
  551.                 *dptr++ = *sptr++;
  552.             }
  553.  
  554.             /*
  555.             **    Get the bits
  556.             */
  557.             if (!GetDIBits(hdc, hbm, 0, bm.bmHeight, dptr, (LPBITMAPINFO)ptr, DIB_RGB_COLORS))
  558.             {
  559.                 GlobalUnlock(result);
  560.                 GlobalFree(result);
  561.                 result = (HANDLE)NULL;
  562.             }
  563.             else
  564.             {
  565.                 GlobalUnlock(result);
  566.             }
  567.         }
  568.         ReleaseDC(MainWindow, hdc);
  569.     }
  570.     else
  571.     {
  572.         ErrorBox("BitmapToDIB(): Unable to get DC from main window");
  573.     }
  574.  
  575.     if (bmi != NULL)
  576.         free(bmi);
  577.  
  578.     if (bmci != NULL)
  579.         free(bmci);
  580.  
  581.     return result;
  582. }
  583.  
  584. /*
  585. ** int                            TRUE if hbm points to a OS/2 DIB
  586. ** DibIsOs2(HANDLE hbm);    handle of packed DIB to check
  587. **
  588. **    This function checks the passd packed DIB to determine if it is a
  589. **    OS/2 compatible DIB.
  590. **
  591. ** Modification History:
  592. ** 10/16/91  LCW  Created
  593. */
  594. int
  595. DibIsOs2(HANDLE hbm)
  596. {
  597.     int                rc = FALSE;
  598.     BITMAPINFO FAR    *bmi;
  599.  
  600.     bmi = (BITMAPINFO FAR *)GlobalLock(hbm);
  601.     if (bmi != NULL)
  602.     {
  603.         if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  604.             rc = TRUE;
  605.  
  606.         GlobalUnlock(hbm);
  607.     }
  608.  
  609.     return rc;
  610. }
  611.  
  612. /*
  613. ** int                                    TRUE if hbm points to a compressed DIB
  614. ** DibIsCompressed(HANDLE hbm);    handle of packed DIB to check
  615. **
  616. **    This function checks the passed packed DIB to determine if it is
  617. **    a compressed windows DIB or not.
  618. **
  619. ** Modification History:
  620. ** 10/16/91  LCW  Created
  621. */
  622. int
  623. DibIsCompressed(HANDLE hbm)
  624. {
  625.     int                rc = FALSE;
  626.     BITMAPINFO FAR    *bmi;
  627.  
  628.     bmi = (BITMAPINFO FAR *)GlobalLock(hbm);
  629.     if (bmi != NULL)
  630.     {
  631.         if (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)
  632.             && bmi->bmiHeader.biCompression != BI_RGB)
  633.             rc = TRUE;
  634.  
  635.         GlobalUnlock(hbm);
  636.     }
  637.  
  638.     return rc;
  639. }
  640.  
  641. /*
  642. **    Modification History
  643. **    --------------------
  644. **    $lgb$
  645. ** 10/15/91     Larry Widing   Initial version for Win Tech Journal Article.
  646. ** 11/12/91     Larry Widing   Added DibIsOs2() and DibIsCompressed()
  647. **                             fucntions.
  648. **    $lge$
  649. */
  650.