home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / general / diblook / myfile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  5.7 KB  |  217 lines

  1. //  myfile.cpp
  2. //
  3. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  4. //  the following functions:
  5. //
  6. //  SaveDIB()           - Saves the specified dib in a file
  7. //  ReadDIBFile()       - Loads a DIB from a file
  8. //
  9. //
  10. // This is a part of the Microsoft Foundation Classes C++ library.
  11. // Copyright (C) 1992-1998 Microsoft Corporation
  12. // All rights reserved.
  13. //
  14. // This source code is only intended as a supplement to the
  15. // Microsoft Foundation Classes Reference and related
  16. // electronic documentation provided with the library.
  17. // See these sources for detailed information regarding the
  18. // Microsoft Foundation Classes product.
  19.  
  20. #include "stdafx.h"
  21. #include <math.h>
  22. #include <io.h>
  23. #include <direct.h>
  24. #include "dibapi.h"
  25.  
  26. /*
  27.  * Dib Header Marker - used in writing DIBs to files
  28.  */
  29. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  30.  
  31.  
  32. /*************************************************************************
  33.  *
  34.  * SaveDIB()
  35.  *
  36.  * Saves the specified DIB into the specified CFile.  The CFile
  37.  * is opened and closed by the caller.
  38.  *
  39.  * Parameters:
  40.  *
  41.  * HDIB hDib - Handle to the dib to save
  42.  *
  43.  * CFile& file - open CFile used to save DIB
  44.  *
  45.  * Return value: TRUE if successful, else FALSE or CFileException
  46.  *
  47.  *************************************************************************/
  48.  
  49.  
  50. BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
  51. {
  52.     BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  53.     LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure
  54.     DWORD dwDIBSize;
  55.  
  56.     if (hDib == NULL)
  57.         return FALSE;
  58.  
  59.     /*
  60.      * Get a pointer to the DIB memory, the first of which contains
  61.      * a BITMAPINFO structure
  62.      */
  63.     lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
  64.     if (lpBI == NULL)
  65.         return FALSE;
  66.  
  67.     if (!IS_WIN30_DIB(lpBI))
  68.     {
  69.         ::GlobalUnlock((HGLOBAL) hDib);
  70.         return FALSE;       // It's an other-style DIB (save not supported)
  71.     }
  72.  
  73.     /*
  74.      * Fill in the fields of the file header
  75.      */
  76.  
  77.     /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  78.     bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  79.  
  80.     // Calculating the size of the DIB is a bit tricky (if we want to
  81.     // do it right).  The easiest way to do this is to call GlobalSize()
  82.     // on our global handle, but since the size of our global memory may have
  83.     // been padded a few bytes, we may end up writing out a few too
  84.     // many bytes to the file (which may cause problems with some apps).
  85.     //
  86.     // So, instead let's calculate the size manually (if we can)
  87.     //
  88.     // First, find size of header plus size of color table.  Since the
  89.     // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  90.     // the size of the structure, let's use this.
  91.  
  92.     dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation
  93.  
  94.     // Now calculate the size of the image
  95.  
  96.     if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
  97.     {
  98.         // It's an RLE bitmap, we can't calculate size, so trust the
  99.         // biSizeImage field
  100.  
  101.         dwDIBSize += lpBI->biSizeImage;
  102.     }
  103.     else
  104.     {
  105.         DWORD dwBmBitsSize;  // Size of Bitmap Bits only
  106.  
  107.         // It's not RLE, so size is Width (DWORD aligned) * Height
  108.  
  109.         dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
  110.  
  111.         dwDIBSize += dwBmBitsSize;
  112.  
  113.         // Now, since we have calculated the correct size, why don't we
  114.         // fill in the biSizeImage field (this will fix any .BMP files which
  115.         // have this field incorrect).
  116.  
  117.         lpBI->biSizeImage = dwBmBitsSize;
  118.     }
  119.  
  120.  
  121.     // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  122.  
  123.     bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  124.     bmfHdr.bfReserved1 = 0;
  125.     bmfHdr.bfReserved2 = 0;
  126.  
  127.     /*
  128.      * Now, calculate the offset the actual bitmap bits will be in
  129.      * the file -- It's the Bitmap file header plus the DIB header,
  130.      * plus the size of the color table.
  131.      */
  132.     bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
  133.                                               + PaletteSize((LPSTR)lpBI);
  134.     TRY
  135.     {
  136.         // Write the file header
  137.         file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  138.         //
  139.         // Write the DIB header and the bits
  140.         //
  141.         file.WriteHuge(lpBI, dwDIBSize);
  142.     }
  143.     CATCH (CFileException, e)
  144.     {
  145.         ::GlobalUnlock((HGLOBAL) hDib);
  146.         THROW_LAST();
  147.     }
  148.     END_CATCH
  149.  
  150.     ::GlobalUnlock((HGLOBAL) hDib);
  151.     return TRUE;
  152. }
  153.  
  154.  
  155. /*************************************************************************
  156.  
  157.   Function:  ReadDIBFile (CFile&)
  158.  
  159.    Purpose:  Reads in the specified DIB file into a global chunk of
  160.              memory.
  161.  
  162.    Returns:  A handle to a dib (hDIB) if successful.
  163.              NULL if an error occurs.
  164.  
  165.   Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  166.              from the end of the BITMAPFILEHEADER structure on is
  167.              returned in the global memory handle.
  168.  
  169. *************************************************************************/
  170.  
  171.  
  172. HDIB WINAPI ReadDIBFile(CFile& file)
  173. {
  174.     BITMAPFILEHEADER bmfHeader;
  175.     DWORD dwBitsSize;
  176.     HDIB hDIB;
  177.     LPSTR pDIB;
  178.  
  179.     /*
  180.      * get length of DIB in bytes for use when reading
  181.      */
  182.  
  183.     dwBitsSize = file.GetLength();
  184.  
  185.     /*
  186.      * Go read the DIB file header and check if it's valid.
  187.      */
  188.     if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  189.         return NULL;
  190.  
  191.     if (bmfHeader.bfType != DIB_HEADER_MARKER)
  192.         return NULL;
  193.  
  194.     /*
  195.      * Allocate memory for DIB
  196.      */
  197.     hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  198.     if (hDIB == 0)
  199.     {
  200.         return NULL;
  201.     }
  202.     pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  203.  
  204.     /*
  205.      * Go read the bits.
  206.      */
  207.     if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
  208.         dwBitsSize - sizeof(BITMAPFILEHEADER) )
  209.     {
  210.         ::GlobalUnlock((HGLOBAL) hDIB);
  211.         ::GlobalFree((HGLOBAL) hDIB);
  212.         return NULL;
  213.     }
  214.     ::GlobalUnlock((HGLOBAL) hDIB);
  215.     return hDIB;
  216. }
  217.