/****************************************************************************/
/* */
/* Copyright (C) 1987-1996 Microsoft Corp. */
/* All Rights Reserved */
/* */
/****************************************************************************/
/****************************** Module Header *******************************
* Module Name: rwbmp.c
*
* Routines for reading and writing bitmap files.
*
* History:
*
****************************************************************************/
#include "imagedit.h"
#include <stdio.h>
#include <io.h>
#include <fcntl.h> // For NT fstat().
#include <sys\types.h> // For fstat() types.
#include <sys\stat.h> // For fstat() function.
/************************************************************************
* LoadBitmapFile
*
* Loads the specified bitmap file. With ImagEdit, this must be a
* Windows 3.0 DIB.
*
* Arguments:
* PSTR pszFullFileName - Name of the bitmap file to load.
*
* Returns:
* TRUE if successful, FALSE otherwise.
*
* History:
*
************************************************************************/
BOOL LoadBitmapFile(
PSTR pszFullFileName)
{
HFILE hf;
OFSTRUCT OfStruct;
struct stat FileStatus;
DWORD dwFileSize;
DWORD dwDIBSize;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
PIMAGEINFO pImage;
INT nColors;
HANDLE hDIB;
PDEVICE pDevice;
if ((hf = (HFILE)OpenFile(pszFullFileName, (LPOFSTRUCT)&OfStruct, OF_READ))
== (HFILE)-1) {
Message(MSG_CANTOPEN, pszFullFileName);
return FALSE;
}
fstat((INT)_open_osfhandle((long)(hf), (int)(O_RDONLY)), &FileStatus);
dwFileSize = (DWORD)FileStatus.st_size;
ImageLinkFreeList();
/*
* Read the Bitmap File Header.
*/
if (!MyFileRead(hf, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER),
pszFullFileName, FT_BITMAP))
goto Error1;
/*
* Check for the "BM" at the start of the file, and the file size
* in the header must match the real file size.
*/
if (bfh.bfType != 0x4D42 || bfh.bfSize != dwFileSize) {
Message(MSG_BADBMPFILE, pszFullFileName);
goto Error1;
}
/*
* Read the Bitmap Info Header.
*/
if (!MyFileRead(hf, (LPSTR)&bih, sizeof(BITMAPINFOHEADER),
pszFullFileName, FT_BITMAP))
goto Error1;
/*
* The DIB size should be the size of the file less the bitmap
* file header.
*/
dwDIBSize = dwFileSize - sizeof(BITMAPFILEHEADER);
if (!IsValidDIB((LPBITMAPINFO)&bih, dwDIBSize, FALSE)) {
Message(MSG_BADBMPFILE, pszFullFileName);
goto Error1;
}
/*
* There is a limit to the size of image we will edit. For icons
* and cursors, the field that carries the dimensions is a byte,
* so the size cannot be greater than 256. This is also what
* we limit bitmaps to.
*/
if (bih.biWidth > MAXIMAGEDIM || bih.biHeight > MAXIMAGEDIM) {
Message(MSG_BADBMPSIZE, MAXIMAGEDIM, MAXIMAGEDIM);
goto Error1;
}
switch (bih.biBitCount) {
case 1:
nColors = 2;
break;
case 4:
nColors = 16;
break;
default:
Message(MSG_NOTSUPPORT);
goto Error1;
}
if (!(pDevice = DeviceLinkAlloc(FT_BITMAP, NULL, nColors,
(INT)bih.biWidth, (INT)bih.biHeight))) {
goto Error1;
}
if (!(pImage = ImageLinkAlloc(pDevice,
(INT)bih.biWidth, (INT)bih.biHeight, 0, 0, nColors)))
goto Error1;
/*
* Allocate space for the DIB for this image.
*/
if (!(hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize))) {
Message(MSG_OUTOFMEMORY);
goto Error2;
}
pImage->DIBSize = dwDIBSize;
pImage->DIBhandle = hDIB;
pImage->DIBPtr = (LPSTR)GlobalLock(hDIB);
/*
* Jump back to the start of the DIB.
*/
SetFilePointer((HANDLE)hf, sizeof(BITMAPFILEHEADER), NULL, (DWORD)0);
/*
* Read the entire DIB (including info and color table) into
* the allocated memory for it.
*/
if (!MyFileRead(hf, pImage->DIBPtr, (DWORD)pImage->DIBSize,
pszFullFileName, FT_BITMAP))
goto Error2;
_lclose((HFILE)hf);
fFileDirty = FALSE;
SetFileName(pszFullFileName);
giType = FT_BITMAP;
/*
* Bitmaps only have one "image" in the file.
*/
gnImages = 1;
ImageOpen2(pImage);
return TRUE;
Error2:
ImageLinkFreeList();
Error1:
_lclose((HFILE)hf);
return FALSE;
}
/************************************************************************
* SaveBitmapFile
*
*
*
* Arguments:
*
* Returns:
* TRUE if successful, FALSE otherwise.
*
* History:
*
************************************************************************/
BOOL SaveBitmapFile(
PSTR pszFullFileName)
{
HCURSOR hcurOld;
BITMAPFILEHEADER bfh;
HFILE hf;
OFSTRUCT OfStruct;
hcurOld = SetCursor(hcurWait);
/*
* Save the bits of the current image.
*/
ImageSave();
/*
* Open the file for writing.
*/
if ((hf = (HFILE)OpenFile(pszFullFileName, &OfStruct, OF_CREATE | OF_READWRITE))
== (HFILE)-1) {
Message(MSG_CANTCREATE, pszFullFileName);
goto Error1;
}
bfh.bfType = 0x4D42;
bfh.bfSize = sizeof(BITMAPFILEHEADER) + gpImageCur->DIBSize;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
(gpImageCur->nColors * sizeof(RGBQUAD));
/*
* Write the header to disk.
*/
if (!MyFileWrite(hf, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER),
pszFullFileName))
goto Error2;
/*
* Now write the DIB (a bitmap file only has one).
*/
if (!MyFileWrite(hf, (LPSTR)gpImageCur->DIBPtr,
(DWORD)gpImageCur->DIBSize, pszFullFileName))
goto Error2;
_lclose((HFILE)hf);
fFileDirty = FALSE;
SetFileName(pszFullFileName);
SetCursor(hcurOld);
return TRUE;
Error2:
_lclose((HFILE)hf);
Error1:
SetCursor(hcurOld);
return FALSE;
}