MYFILE.CPP
上传用户:dfwb928
上传日期:2013-04-20
资源大小:228k
文件大小:8k
源码类别:

图形图象

开发平台:

Visual C++

  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-1997 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. #include "stdafx.h"
  20. #include <math.h>
  21. #include <io.h>
  22. #include <direct.h>
  23. #include "dibapi.h"
  24. /*
  25.  * Dib Header Marker - used in writing DIBs to files
  26.  */
  27. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  28. #ifdef _MAC
  29. #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
  30. #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
  31. void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader);
  32. void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header);
  33. #endif
  34. /*************************************************************************
  35.  *
  36.  * SaveDIB()
  37.  *
  38.  * Saves the specified DIB into the specified CFile.  The CFile
  39.  * is opened and closed by the caller.
  40.  *
  41.  * Parameters:
  42.  *
  43.  * HDIB hDib - Handle to the dib to save
  44.  *
  45.  * CFile& file - open CFile used to save DIB
  46.  *
  47.  * Return value: TRUE if successful, else FALSE or CFileException
  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. if (hDib == NULL)
  56. return FALSE;
  57. /*
  58.  * Get a pointer to the DIB memory, the first of which contains
  59.  * a BITMAPINFO structure
  60.  */
  61. lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
  62. if (lpBI == NULL)
  63. return FALSE;
  64. if (!IS_WIN30_DIB(lpBI))
  65. {
  66. ::GlobalUnlock((HGLOBAL) hDib);
  67. return FALSE;       // It's an other-style DIB (save not supported)
  68. }
  69. /*
  70.  * Fill in the fields of the file header
  71.  */
  72. /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  73. bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  74. // Calculating the size of the DIB is a bit tricky (if we want to
  75. // do it right).  The easiest way to do this is to call GlobalSize()
  76. // on our global handle, but since the size of our global memory may have
  77. // been padded a few bytes, we may end up writing out a few too
  78. // many bytes to the file (which may cause problems with some apps).
  79. //
  80. // So, instead let's calculate the size manually (if we can)
  81. //
  82. // First, find size of header plus size of color table.  Since the
  83. // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  84. // the size of the structure, let's use this.
  85. dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation
  86. // Now calculate the size of the image
  87. if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
  88. {
  89. // It's an RLE bitmap, we can't calculate size, so trust the
  90. // biSizeImage field
  91. dwDIBSize += lpBI->biSizeImage;
  92. }
  93. else
  94. {
  95. DWORD dwBmBitsSize;  // Size of Bitmap Bits only
  96. // It's not RLE, so size is Width (DWORD aligned) * Height
  97. dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
  98. dwDIBSize += dwBmBitsSize;
  99. // Now, since we have calculated the correct size, why don't we
  100. // fill in the biSizeImage field (this will fix any .BMP files which
  101. // have this field incorrect).
  102. lpBI->biSizeImage = dwBmBitsSize;
  103. }
  104. // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  105. bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  106. bmfHdr.bfReserved1 = 0;
  107. bmfHdr.bfReserved2 = 0;
  108. /*
  109.  * Now, calculate the offset the actual bitmap bits will be in
  110.  * the file -- It's the Bitmap file header plus the DIB header,
  111.  * plus the size of the color table.
  112.  */
  113. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
  114.   + PaletteSize((LPSTR)lpBI);
  115. #ifdef _MAC
  116. ByteSwapHeader(&bmfHdr);
  117. // First swap the size field
  118. *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  119. // Now swap the rest of the structure (we don't save < Win30 files)
  120. ByteSwapInfo((LPSTR)lpBI, TRUE);
  121. #endif
  122. TRY
  123. {
  124. // Write the file header
  125. file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  126. //
  127. // Write the DIB header and the bits
  128. //
  129. file.WriteHuge(lpBI, dwDIBSize);
  130. }
  131. CATCH (CFileException, e)
  132. {
  133. #ifdef _MAC
  134. // Swap everything back
  135. *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  136. ByteSwapInfo((LPSTR)lpBI, TRUE);
  137. #endif
  138. ::GlobalUnlock((HGLOBAL) hDib);
  139. THROW_LAST();
  140. }
  141. END_CATCH
  142. #ifdef _MAC
  143. // Swap everything back
  144. *((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
  145. ByteSwapInfo((LPSTR)lpBI, TRUE);
  146. #endif
  147. ::GlobalUnlock((HGLOBAL) hDib);
  148. return TRUE;
  149. }
  150. /*************************************************************************
  151.   Function:  ReadDIBFile (CFile&)
  152.    Purpose:  Reads in the specified DIB file into a global chunk of
  153.  memory.
  154.    Returns:  A handle to a dib (hDIB) if successful.
  155.  NULL if an error occurs.
  156.   Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  157.  from the end of the BITMAPFILEHEADER structure on is
  158.  returned in the global memory handle.
  159. *************************************************************************/
  160. HDIB WINAPI ReadDIBFile(CFile& file)
  161. {
  162. BITMAPFILEHEADER bmfHeader;
  163. DWORD dwBitsSize;
  164. HDIB hDIB;
  165. LPSTR pDIB;
  166. /*
  167.  * get length of DIB in bytes for use when reading
  168.  */
  169. dwBitsSize = file.GetLength();
  170. /*
  171.  * Go read the DIB file header and check if it's valid.
  172.  */
  173. if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  174. return NULL;
  175. #ifdef _MAC
  176. ByteSwapHeader(&bmfHeader);
  177. #endif
  178. if (bmfHeader.bfType != DIB_HEADER_MARKER)
  179. return NULL;
  180. /*
  181.  * Allocate memory for DIB
  182.  */
  183. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  184. if (hDIB == 0)
  185. {
  186. return NULL;
  187. }
  188. pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  189. /*
  190.  * Go read the bits.
  191.  */
  192. if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
  193. dwBitsSize - sizeof(BITMAPFILEHEADER) )
  194. {
  195. ::GlobalUnlock((HGLOBAL) hDIB);
  196. ::GlobalFree((HGLOBAL) hDIB);
  197. return NULL;
  198. }
  199. #ifdef _MAC
  200. // First swap the size field
  201. *((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB));
  202. // Now swap the rest of the structure
  203. ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB));
  204. #endif
  205. ::GlobalUnlock((HGLOBAL) hDIB);
  206. return hDIB;
  207. }
  208. #ifdef _MAC
  209. void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader)
  210. {
  211. bmfHeader->bfType = SWAPWORD(bmfHeader->bfType);
  212. bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize);
  213. bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits);
  214. }
  215. void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header)
  216. {
  217. // Note this doesn't swap the bcSize/biSize field.  It assumes that the
  218. // size field was swapped during read or while setting the fWin30Header
  219. // flag.
  220. if (fWin30Header)
  221. {
  222. LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader);
  223. //lpBMIH->biSize = SWAPLONG(lpBMIH->biSize);
  224. lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth);
  225. lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight);
  226. lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes);
  227. lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount);
  228. lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression);
  229. lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage);
  230. lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter);
  231. lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter);
  232. lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed);
  233. lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant);
  234. }
  235. else
  236. {
  237. LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader);
  238. lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth);
  239. lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight);
  240. lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes);
  241. lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount);
  242. }
  243. }
  244. #endif