summaryrefslogtreecommitdiff
path: root/src/wincap/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wincap/file.c')
-rw-r--r--src/wincap/file.c410
1 files changed, 410 insertions, 0 deletions
diff --git a/src/wincap/file.c b/src/wincap/file.c
new file mode 100644
index 0000000..e24f0ec
--- /dev/null
+++ b/src/wincap/file.c
@@ -0,0 +1,410 @@
+/*
+ * file.c
+ *
+ * Source file for Device-Independent Bitmap (DIB) API. Provides
+ * the following functions:
+ *
+ * SaveDIB() - Saves the specified dib in a file
+ * LoadDIB() - Loads a DIB from a file
+ * DestroyDIB() - Deletes DIB when finished using it
+ *
+ * Development Team: Mark Bader
+ * Patrick Schreiber
+ * Garrett McAuliffe
+ * Eric Flo
+ * Tony Claflin
+ *
+ * Written by Microsoft Product Support Services, Developer Support.
+ * Copyright (c) 1991 Microsoft Corporation. All rights reserved.
+ *
+ * Modified by Frank J. Lhota to use Win32 CreateFile handles
+ * whenever WIN32 is defined.
+ */
+#include <windows.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <io.h>
+/* #include <direct.h> */
+#include <stdlib.h>
+#include <fcntl.h>
+#include "errors.h"
+#include "dibutil.h"
+#include "dibapi.h"
+
+/*
+ * Dib Header Marker - used in writing DIBs to files
+ */
+#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
+
+#ifdef WIN32
+typedef HANDLE MYHFILE;
+#else /* WIN32 */
+typedef int MYHFILE;
+#endif /* WIN32 */
+
+/*********************************************************************
+ *
+ * Local Function Prototypes
+ *
+ *********************************************************************/
+
+
+HANDLE ReadDIBFile(MYHFILE);
+BOOL MyRead(MYHFILE, LPSTR, DWORD);
+BOOL SaveDIBFile(void);
+/* BOOL WriteDIB(LPSTR, HANDLE); */
+DWORD PASCAL MyWrite(MYHFILE, VOID FAR *, DWORD);
+
+/*************************************************************************
+ *
+ * LoadDIB()
+ *
+ * Loads the specified DIB from a file, allocates memory for it,
+ * and reads the disk file into the memory.
+ *
+ * Parameters:
+ *
+ * LPSTR lpFileName - specifies the file to load a DIB from
+ *
+ * Returns: A handle to a DIB, or NULL if unsuccessful.
+ *
+ *************************************************************************/
+
+HDIB LoadDIB(LPSTR lpFileName)
+{
+ HDIB hDIB;
+ MYHFILE hFile;
+ OFSTRUCT ofs;
+
+ /*
+ * Set the cursor to a hourglass, in case the loading operation
+ * takes more than a sec, the user will know what's going on.
+ */
+
+ SetCursor(LoadCursor(NULL, IDC_WAIT));
+#ifdef WIN32
+ hFile = CreateFile(
+ lpFileName, /* lpFileName */
+ GENERIC_READ, /* dwDesiredAccess */
+ FILE_SHARE_READ, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_EXISTING, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL, /* dwFlagsAndAttributes */
+ NULL ); /* hTemplateFile */
+
+ if (hFile != INVALID_HANDLE_VALUE)
+#else /* WIN32 */
+ if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)
+#endif /* WIN32 */
+ {
+ hDIB = ReadDIBFile(hFile);
+#ifdef WIN32
+ CloseHandle(hFile);
+#else /* WIN32 */
+ _lclose(hFile);
+#endif /* WIN32 */
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ return hDIB;
+ }
+ else
+ {
+#if 0
+ DIBError(ERR_FILENOTFOUND);
+#endif
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ return NULL;
+ }
+}
+
+
+/*************************************************************************
+ *
+ * SaveDIB()
+ *
+ * Saves the specified DIB into the specified file name on disk. No
+ * error checking is done, so if the file already exists, it will be
+ * written over.
+ *
+ * Parameters:
+ *
+ * HDIB hDib - Handle to the dib to save
+ *
+ * LPSTR lpFileName - pointer to full pathname to save DIB under
+ *
+ * Return value: 0 if successful, or one of:
+ * ERR_INVALIDHANDLE
+ * ERR_OPEN
+ * ERR_LOCK
+ *
+ *************************************************************************/
+
+
+WORD SaveDIB(HDIB hDib, LPSTR lpFileName)
+{
+ BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
+ LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
+ MYHFILE fh; // file handle for opened file
+#ifdef WIN32
+ DWORD dwNumberOfBytesWritten;
+#else /* WIN32 */
+ OFSTRUCT of; // OpenFile structure
+#endif /* WIN32 */
+
+ if (!hDib)
+ return ERR_INVALIDHANDLE;
+#ifdef WIN32
+ fh = CreateFile(
+ lpFileName, /* lpFileName */
+ GENERIC_WRITE, /* dwDesiredAccess */
+ 0, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ CREATE_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL, /* dwFlagsAndAttributes */
+ NULL ); /* hTemplateFile */
+ if (fh == INVALID_HANDLE_VALUE)
+#else /* WIN32 */
+ fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);
+ if (fh == -1)
+#endif /* WIN32 */
+ return ERR_OPEN;
+
+ /*
+ * Get a pointer to the DIB memory, the first of which contains
+ * a BITMAPINFO structure
+ */
+ lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
+ if (!lpBI)
+ return ERR_LOCK;
+
+ /*
+ * 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"
+
+ /* Size is size of packed dib in memory plus size of file header */
+ bmfHdr.bfSize = GlobalSize(hDib) + 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);
+
+ /* Write the file header */
+#ifdef WIN32
+ WriteFile(fh, (LPCVOID)&bmfHdr, sizeof(BITMAPFILEHEADER),
+ &dwNumberOfBytesWritten, NULL);
+#else /* WIN32 */
+ _lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
+#endif /* WIN32 */
+
+ /*
+ * Write the DIB header and the bits -- use local version of
+ * MyWrite, so we can write more than 32767 bytes of data
+ */
+ MyWrite(fh, (LPSTR)lpBI, GlobalSize(hDib));
+ GlobalUnlock(hDib);
+#ifdef WIN32
+ CloseHandle(fh);
+#else /* WIN32 */
+ _lclose(fh);
+#endif /* WIN32 */
+ return 0; // Success code
+}
+
+
+/*************************************************************************
+ *
+ * DestroyDIB ()
+ *
+ * Purpose: Frees memory associated with a DIB
+ *
+ * Returns: Nothing
+ *
+ *************************************************************************/
+
+
+WORD DestroyDIB(HDIB hDib)
+{
+ GlobalFree(hDib);
+ return 0;
+}
+
+
+//************************************************************************
+//
+// Auxiliary Functions which the above procedures use
+//
+//************************************************************************
+
+
+/*************************************************************************
+
+ Function: ReadDIBFile (MYHFILE)
+
+ 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.
+
+*************************************************************************/
+
+
+HANDLE ReadDIBFile(MYHFILE hFile)
+{
+ BITMAPFILEHEADER bmfHeader;
+ DWORD dwBitsSize;
+#ifdef WIN32
+ DWORD dwNumberOfBytesRead = 0;
+#endif /* WIN32 */
+
+ HANDLE hDIB;
+ LPSTR pDIB;
+
+ /*
+ * get length of DIB in bytes for use when reading
+ */
+
+#ifdef WIN32
+ dwBitsSize = GetFileSize(hFile, NULL);
+#else /* WIN32 */
+ dwBitsSize = filelength(hFile);
+#endif /* WIN32 */
+
+ /*
+ * Go read the DIB file header and check if it's valid.
+ */
+#ifdef WIN32
+ ReadFile(hFile, (LPVOID)&bmfHeader, sizeof(bmfHeader),
+ &dwNumberOfBytesRead, NULL);
+ if (dwNumberOfBytesRead != sizeof(bmfHeader)) {
+#else /* WIN32 */
+ if ((_lread(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(
+ bmfHeader))) {
+#endif /* WIN32 */
+ return NULL;
+ }
+ if (bmfHeader.bfType != DIB_HEADER_MARKER)
+ {
+ return NULL;
+ }
+ /*
+ * Allocate memory for DIB
+ */
+ hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
+ if (hDIB == 0)
+ {
+ return NULL;
+ }
+ pDIB = GlobalLock(hDIB);
+
+ /*
+ * Go read the bits.
+ */
+ if (!MyRead(hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
+ {
+ GlobalUnlock(hDIB);
+ GlobalFree(hDIB);
+ return NULL;
+ }
+ GlobalUnlock(hDIB);
+ return hDIB;
+}
+
+/*************************************************************************
+
+ Function: MyRead (MYHFILE, LPSTR, DWORD)
+
+ Purpose: Routine to read files greater than 64K in size.
+
+ Returns: TRUE if successful.
+ FALSE if an error occurs.
+
+ Comments:
+
+*************************************************************************/
+
+
+BOOL MyRead(MYHFILE hFile, LPSTR lpBuffer, DWORD dwSize)
+{
+#ifdef WIN32
+ DWORD dwNumberOfBytesRead;
+
+ if(!ReadFile(hFile, (LPVOID)lpBuffer, dwSize, &dwNumberOfBytesRead, NULL))
+ return FALSE;
+ return (dwNumberOfBytesRead == dwSize);
+#else /* WIN32 */
+ char huge *lpInBuf = (char huge *)lpBuffer;
+ int nBytes;
+
+ /*
+ * Read in the data in 32767 byte chunks (or a smaller amount if it's
+ * the last chunk of data read)
+ */
+
+ while (dwSize)
+ {
+ nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));
+ if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)
+ return FALSE;
+ dwSize -= nBytes;
+ lpInBuf += nBytes;
+ }
+ return TRUE;
+#endif /* WIN32 */
+}
+
+
+/****************************************************************************
+
+ FUNCTION : MyWrite(MYHFILE fh, VOID FAR *pv, DWORD ul)
+
+ PURPOSE : Writes data in steps of 32k till all the data is written.
+ Normal _lwrite uses a WORD as 3rd parameter, so it is
+ limited to 32767 bytes, but this procedure is not.
+
+ RETURNS : 0 - If write did not proceed correctly.
+ number of bytes written otherwise.
+
+ ****************************************************************************/
+
+
+DWORD PASCAL MyWrite(MYHFILE iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)
+{
+ DWORD dwBytesTmp = dwBytes; // Save # of bytes for return value
+#ifdef WIN32
+ if(!WriteFile(iFileHandle, (LPCVOID)lpBuffer, dwBytes, &dwBytesTmp, NULL))
+ return 0;
+#else /* WIN32 */
+ BYTE huge *hpBuffer = lpBuffer; // make a huge pointer to the data
+
+ /*
+ * Write out the data in 32767 byte chunks.
+ */
+
+ while (dwBytes > 32767)
+ {
+ if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)
+ return 0;
+ dwBytes -= 32767;
+ hpBuffer += 32767;
+ }
+
+ /* Write out the last chunk (which is < 32767 bytes) */
+ if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)
+ return 0;
+#endif /* WIN32 */
+ return dwBytesTmp;
+}