home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / mandel / savebmp.c < prev   
C/C++ Source or Header  |  1997-10-05  |  7KB  |  241 lines

  1. /******************************Module*Header*******************************\
  2. * Module Name: savebmp.c
  3. *
  4. *
  5. * Created: 06-Jan-1992 10:59:36
  6. *
  7. * Copyright (C) 1993-1997 Microsoft Corporation
  8. *
  9. * Contains the main routine, SaveBitmapFile, for saving a DDB into file
  10. * in DIB format.
  11. *
  12. * Dependencies:
  13. *
  14. *   (#defines)
  15. *   (#includes)
  16. *       #include <windows.h>
  17. *       #include "jtypes.h"
  18. *
  19. \**************************************************************************/
  20. #include <windows.h>
  21. #include "julia.h"
  22.  
  23. extern HPALETTE ghPal;
  24. extern HWND ghwndMain;
  25. extern char   gtext[256];
  26. BOOL SaveBitmapFile(HDC, HBITMAP, PSTR);
  27. // void ErrorOut(char errstring[30]);
  28.  
  29. /******************************Public*Routine******************************\
  30. * SaveBitmapFile
  31. *
  32. *
  33. * Effects: Save pInfo->hBmpSaved into disk specified by pszFileName
  34. *
  35. * Warnings: assumes hBmpSaved is not selected into window's DC other than
  36. *           pInfo->hwnd's DC
  37. *
  38. \**************************************************************************/
  39.  
  40. BOOL SaveBitmapFile(HDC hDC, HBITMAP hBmp, PSTR pszFileName)
  41. {
  42.     int         hFile;
  43.     OFSTRUCT    ofReOpenBuff;
  44.     HBITMAP     hTmpBmp, hBmpOld;
  45.     BOOL        bSuccess;
  46.     BITMAPFILEHEADER    bfh;
  47.     PBITMAPINFO pbmi;
  48.     PBYTE       pBits;
  49.     BITMAPINFO  bmi;
  50.     PBYTE pjTmp, pjTmpBmi;
  51.     ULONG sizBMI;
  52.  
  53.  
  54.     bSuccess = TRUE;
  55. #if 0
  56.     if (ghPal) {
  57.         SelectPalette(hDC, ghPal, FALSE);
  58.         RealizePalette(hDC);
  59.     }
  60. #endif
  61.     if (!hBmp) {
  62.         MessageBox(ghwndMain, 
  63.                    GetStringRes (IDS_NO_BITMAP_TO_SAVE),
  64.                    NULL, MB_OK);
  65.         return FALSE;
  66.     }
  67.  
  68.     //
  69.     // Let the graphics engine to retrieve the dimension of the bitmap for us
  70.     // GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO
  71.     // if BitCount != 0, color table will be retrieved
  72.     //
  73.     bmi.bmiHeader.biSize = 0x28;              // GDI need this to work
  74.     bmi.bmiHeader.biBitCount = 0;             // don't get the color table
  75.     if ((GetDIBits(hDC, hBmp, 0, 0, (LPSTR)NULL, &bmi, DIB_RGB_COLORS)) == 0) {
  76.        return FALSE;
  77.     }
  78.  
  79.     //
  80.     // Now that we know the size of the image, alloc enough memory to retrieve
  81.     // the actual bits
  82.     //
  83.     if ((pBits = (PBYTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  84.                 bmi.bmiHeader.biSizeImage)) == NULL) {
  85.         return FALSE;
  86.     }
  87.  
  88.     //
  89.     // Note: 24 bits per pixel has no color table.  So, we don't have to
  90.     // allocate memory for retrieving that.  Otherwise, we do.
  91.     //
  92.     pbmi = &bmi;                                      // assume no color table
  93.  
  94.     switch (bmi.bmiHeader.biBitCount) {
  95.         case 24:                                      // has color table
  96.             sizBMI = sizeof(BITMAPINFOHEADER);
  97.             break;
  98.         case 16:
  99.         case 32:
  100.             sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
  101.             break;
  102.         default:
  103.             sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*(1<<bmi.bmiHeader.biBitCount);
  104.             break;
  105.  
  106.     }
  107.  
  108.     //
  109.     // Allocate memory for color table if it is not 24bpp...
  110.     //
  111.     if (sizBMI != sizeof(BITMAPINFOHEADER)) {
  112.         ULONG       sizTmp;
  113.         //
  114.         // I need more memory for the color table
  115.         //
  116.         if ((pbmi = (PBITMAPINFO)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizBMI )) == NULL) {
  117.             bSuccess = FALSE;
  118.             goto ErrExit1;
  119.         }
  120.         //
  121.         // Now that we've a bigger chunk of memory, let's copy the Bitmap
  122.         // info header data over
  123.         //
  124.         pjTmp = (PBYTE)pbmi;
  125.         pjTmpBmi = (PBYTE)&bmi;
  126.         sizTmp = sizeof(BITMAPINFOHEADER);
  127.  
  128.         while(sizTmp--)
  129.         {
  130.             *(((PBYTE)pjTmp)++) = *((pjTmpBmi)++);
  131.         }
  132.     }
  133.  
  134.     //
  135.     // Let's open the file and get ready for writing
  136.     //
  137.     if ((hFile = OpenFile(pszFileName, (LPOFSTRUCT)&ofReOpenBuff,
  138.                  OF_CREATE | OF_WRITE)) == -1) {
  139.         MessageBox(ghwndMain, GetStringRes(IDS_FILE_OPEN_FAILED), 
  140.                    NULL, MB_OK);
  141.         goto ErrExit2;
  142.     }
  143.  
  144.     //
  145.     // But first, fill in the info for the BitmapFileHeader
  146.     //
  147.     bfh.bfType = 0x4D42;                            // 'BM'
  148.     bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizBMI+
  149.         pbmi->bmiHeader.biSizeImage;
  150.     bfh.bfReserved1 =
  151.     bfh.bfReserved2 = 0;
  152.     bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizBMI;
  153.  
  154.     //
  155.     // Write out the file header now
  156.     //
  157.     if (_lwrite(hFile, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER)) == -1) {
  158.         bSuccess = FALSE;
  159.         goto ErrExit3;
  160.     }
  161.  
  162.     //
  163.     // Bitmap can't be selected into a DC when calling GetDIBits
  164.     // Assume that the hDC is the DC where the bitmap would have been selected
  165.     // if indeed it has been selected
  166.     //
  167.     if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight)) {
  168.         hBmpOld = SelectObject(hDC, hTmpBmp);
  169.         if ((GetDIBits(hDC, hBmp, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS))==0){
  170.             bSuccess = FALSE;
  171.             goto ErrExit4;
  172.         }
  173.     } else {
  174.         MessageBox(ghwndMain, 
  175.             GetStringRes (IDS_BITMAP_NOT_CREATED),
  176.             NULL, MB_OK);
  177.         bSuccess = FALSE;
  178.         goto ErrExit3;
  179.     }
  180.  
  181.     //
  182.     // Now write out the BitmapInfoHeader and color table, if any
  183.     //
  184.     if (_lwrite(hFile, (LPSTR)pbmi, sizBMI) == -1) {
  185.         bSuccess = FALSE;
  186.         goto ErrExit4;
  187.     }
  188.  
  189.     //
  190.     // write the bits also
  191.     //
  192.     if (_lwrite(hFile, (LPSTR)pBits, pbmi->bmiHeader.biSizeImage) == -1) {
  193.         bSuccess = FALSE;
  194.         goto ErrExit4;
  195.     }
  196.  
  197.  
  198. ErrExit4:
  199.     SelectObject(hDC, hBmpOld);
  200.     DeleteObject(hTmpBmp);
  201. ErrExit3:
  202.     _lclose(hFile);
  203. ErrExit2:
  204.     GlobalFree(pbmi);
  205. ErrExit1:
  206.     GlobalFree(pBits);
  207.     return bSuccess;
  208. }
  209.  
  210.  
  211. #if 0 
  212. /************************************************************************
  213.  * void ErrorOut(char errstring[30])
  214.  *
  215.  * Purpose: Print out an meainful error code by means of
  216.  *      GetLastError and printf
  217.  *
  218.  * Inputs:  errstring - the action that failed, passed by the
  219.  *              calling proc.
  220.  *
  221.  * Returns: none
  222.  *
  223.  * Calls:   GetLastError
  224.  *
  225.  * History:
  226.  * 09-13-91 Pete Grey   Created.
  227.  *
  228. \************************************************************************/
  229.  
  230.  
  231. void ErrorOut(char errstring[30])
  232. {
  233. DWORD Error;
  234. CHAR  str[80];
  235.  
  236. Error= GetLastError();
  237. wsprintf((LPSTR) str, "Error on %s = %d\n", errstring, Error);
  238. OutputDebugString(str);
  239. }
  240.  
  241. #endif