www.pudn.com > PositionInBmp.rar > myfile.cpp


//  myfile.cpp 
// 
//  Source file for Device-Independent Bitmap (DIB) API.  Provides 
//  the following functions: 
// 
//  SaveDIB()           - Saves the specified dib in a file 
//  ReadDIBFile()       - Loads a DIB from a file 
// 
// 
// This is a part of the Microsoft Foundation Classes C++ library. 
// Copyright (C) 1992-1998 Microsoft Corporation 
// All rights reserved. 
// 
// This source code is only intended as a supplement to the 
// Microsoft Foundation Classes Reference and related 
// electronic documentation provided with the library. 
// See these sources for detailed information regarding the 
// Microsoft Foundation Classes product. 
 
#include "stdafx.h" 
#include  
#include  
#include  
#include "dibapi.h" 
 
/* 
 * Dib Header Marker - used in writing DIBs to files 
 */ 
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B') 
 
 
/************************************************************************* 
 * 
 * SaveDIB() 
 * 
 * Saves the specified DIB into the specified CFile.  The CFile 
 * is opened and closed by the caller. 
 * 
 * Parameters: 
 * 
 * HDIB hDib - Handle to the dib to save 
 * 
 * CFile& file - open CFile used to save DIB 
 * 
 * Return value: TRUE if successful, else FALSE or CFileException 
 * 
 *************************************************************************/ 
 
 
BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) 
{ 
	BITMAPFILEHEADER bmfHdr; // Header for Bitmap file 
	LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure 
	DWORD dwDIBSize; 
 
	if (hDib == NULL) 
		return FALSE; 
 
	/* 
	 * Get a pointer to the DIB memory, the first of which contains 
	 * a BITMAPINFO structure 
	 */ 
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); 
	if (lpBI == NULL) 
		return FALSE; 
 
	if (!IS_WIN30_DIB(lpBI)) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		return FALSE;       // It's an other-style DIB (save not supported) 
	} 
 
	/* 
	 * Fill in the fields of the file header 
	 */ 
 
	/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ 
	bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
 
	// Calculating the size of the DIB is a bit tricky (if we want to 
	// do it right).  The easiest way to do this is to call GlobalSize() 
	// on our global handle, but since the size of our global memory may have 
	// been padded a few bytes, we may end up writing out a few too 
	// many bytes to the file (which may cause problems with some apps). 
	// 
	// So, instead let's calculate the size manually (if we can) 
	// 
	// First, find size of header plus size of color table.  Since the 
	// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains 
	// the size of the structure, let's use this. 
 
	dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation 
 
	// Now calculate the size of the image 
 
	if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) 
	{ 
		// It's an RLE bitmap, we can't calculate size, so trust the 
		// biSizeImage field 
 
		dwDIBSize += lpBI->biSizeImage; 
	} 
	else 
	{ 
		DWORD dwBmBitsSize;  // Size of Bitmap Bits only 
 
		// It's not RLE, so size is Width (DWORD aligned) * Height 
 
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; 
 
		dwDIBSize += dwBmBitsSize; 
 
		// Now, since we have calculated the correct size, why don't we 
		// fill in the biSizeImage field (this will fix any .BMP files which 
		// have this field incorrect). 
 
		lpBI->biSizeImage = dwBmBitsSize; 
	} 
 
 
	// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) 
 
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	/* 
	 * Now, calculate the offset the actual bitmap bits will be in 
	 * the file -- It's the Bitmap file header plus the DIB header, 
	 * plus the size of the color table. 
	 */ 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize 
											  + PaletteSize((LPSTR)lpBI); 
	TRY 
	{ 
		// Write the file header 
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
		// 
		// Write the DIB header and the bits 
		// 
		file.WriteHuge(lpBI, dwDIBSize); 
	} 
	CATCH (CFileException, e) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		THROW_LAST(); 
	} 
	END_CATCH 
 
	::GlobalUnlock((HGLOBAL) hDib); 
	return TRUE; 
} 
 
 
/************************************************************************* 
 
  Function:  ReadDIBFile (CFile&) 
 
   Purpose:  Reads in the specified DIB file into a global chunk of 
			 memory. 
 
   Returns:  A handle to a dib (hDIB) if successful. 
			 NULL if an error occurs. 
 
  Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything 
			 from the end of the BITMAPFILEHEADER structure on is 
			 returned in the global memory handle. 
 
*************************************************************************/ 
 
 
HDIB WINAPI ReadDIBFile(CFile& file) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	DWORD dwBitsSize; 
	HDIB hDIB; 
	LPSTR pDIB; 
 
	/* 
	 * get length of DIB in bytes for use when reading 
	 */ 
 
	dwBitsSize = file.GetLength(); 
 
	/* 
	 * Go read the DIB file header and check if it's valid. 
	 */ 
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
		return NULL; 
 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
		return NULL; 
 
	/* 
	 * Allocate memory for DIB 
	 */ 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
	if (hDIB == 0) 
	{ 
		return NULL; 
	} 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
 
	/* 
	 * Go read the bits. 
	 */ 
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
		dwBitsSize - sizeof(BITMAPFILEHEADER) ) 
	{ 
		::GlobalUnlock((HGLOBAL) hDIB); 
		::GlobalFree((HGLOBAL) hDIB); 
		return NULL; 
	} 
	::GlobalUnlock((HGLOBAL) hDIB); 
	return hDIB; 
}