--- /dev/null
+/***********************************************************************/
+/* */
+/* Objective Caml */
+/* */
+/* Developed by Jacob Navia */
+/* Copyright 2001 Institut National de Recherche en Informatique et */
+/* en Automatique. All rights reserved. This file is distributed */
+/* under the terms of the GNU Library General Public License, with */
+/* the special exception on linking described in file ../../LICENSE. */
+/* */
+/***********************************************************************/
+
+/* $Id: dib.c 5029 2002-07-23 14:12:03Z doligez $ */
+
+//-----------------------------------------------------------------------------
+// DIB.C
+//
+// This is a collection of useful DIB manipulation/information gathering
+// functions. Many functions are supplied simply to take the burden
+// of taking into account whether a DIB is a Win30 style or OS/2 style
+// DIB away from the application.
+//
+// The functions in this module assume that the DIB pointers or handles
+// passed to them point to a block of memory in one of two formats:
+//
+// a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB)
+// b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style)
+//
+// The SDK Reference, Volume 2 describes these data structures.
+//
+// A number of functions in this module were lifted from SHOWDIB,
+// and modified to handle OS/2 DIBs.
+//
+// The functions in this module could be streamlined (made faster and
+// smaller) by removing the OS/2 DIB specific code, and assuming all
+// DIBs passed to it are Win30 style DIBs. The DIB file reading code
+// would need to be modified to always convert DIBs to Win30 style
+// DIBs. The only reason this isn't done in DIBView is because DIBView
+// was written to test display and printer drivers (which are supposed
+// to support OS/2 DIBs wherever they support Win30 style DIBs). SHOWDIB
+// is a great example of how to go about doing this.
+//-----------------------------------------------------------------------------
+
+
+#include <windows.h>
+#include <memory.h>
+#include <string.h>
+#include <io.h>
+#include <stdio.h>
+ // Size of window extra bytes (we store a handle to a PALINFO structure).
+
+#define PAL_CBWNDEXTRA (1 * sizeof (WORD))
+
+
+typedef struct
+ {
+ HPALETTE hPal; // Handle to palette being displayed.
+ WORD wEntries; // # of entries in the palette.
+ int nSquareSize; // Size of palette square (see PAL_SIZE)
+ HWND hInfoWnd; // Handle to the info bar window.
+ int nRows, nCols; // # of Rows/Columns in window.
+ int cxSquare, cySquare; // Pixel width/height of palette square.
+ WORD wEntry; // Currently selected palette square.
+ } PALINFO, FAR *LPPALINFO;
+ // Window Words.
+#define WW_PAL_HPALINFO 0 // Handle to PALINFO structure.
+ // The following define is for CopyPaletteChangingFlags().
+#define DONT_CHANGE_FLAGS -1
+ // The following is the palette version that goes in a
+ // LOGPALETTE's palVersion field.
+#define PALVERSION 0x300
+// This is an enumeration for the various ways we can display
+// a palette in PaletteWndProc().
+enum PAL_SIZE
+ {
+ PALSIZE_TINY = 0,
+ PALSIZE_SMALL,
+ PALSIZE_MEDIUM,
+ PALSIZE_LARGE
+ };
+#define CopyPalette(hPal) CopyPaletteChangingFlags (hPal, DONT_CHANGE_FLAGS)
+#define CopyPalForAnimation(hPal) CopyPaletteChangingFlags (hPal, PC_RESERVED)
+// WIDTHBYTES takes # of bits in a scan line and rounds up to nearest
+// word.
+#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
+
+ // Given a pointer to a DIB header, return TRUE if is a Windows 3.0 style
+ // DIB, false if otherwise (PM style DIB).
+#define IS_WIN30_DIB(lpbi) ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER))
+
+static WORD PaletteSize (LPSTR lpbi);
+
+extern void ShowDbgMsg(char *);
+static BOOL MyRead (int, LPSTR, DWORD);
+/*-------------- DIB header Marker Define -------------------------*/
+#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
+/*-------------- MyRead Function Define ---------------------------*/
+
+// When we read in a DIB, we read it in in chunks. We read half a segment
+// at a time. This way we insure that we don't cross any segment
+// boundries in _lread() during a read. We don't read in a full segment
+// at a time, since _lread takes some "int" type parms instead of
+// WORD type params (it'd work, but the compiler would give you warnings)...
+
+#define BYTES_PER_READ 32767
+
+/*-------------- Define for PM DIB -------------------------------*/
+// The constants for RGB, RLE4, RLE8 are already defined inside
+// of Windows.h
+
+#define BI_PM 3L
+
+
+/*-------------- Magic numbers -------------------------------------*/
+// Maximum length of a filename for DOS is 128 characters.
+
+#define MAX_FILENAME 129
+
+
+/*-------------- TypeDef Structures -------------------------------*/
+
+typedef struct InfoStruct
+ {
+ char szName[13];
+ char szType[15];
+ DWORD cbWidth;
+ DWORD cbHeight;
+ DWORD cbColors;
+ char szCompress[5];
+ } INFOSTRUCT;
+
+// Some macros.
+#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
+#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
+//---------------------------------------------------------------------
+//
+// Function: FindDIBBits
+//
+// Purpose: Given a pointer to a DIB, returns a pointer to the
+// DIB's bitmap bits.
+//
+// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
+// or BITMAPCOREHEADER)
+//
+// History: Date Reason
+// 6/01/91 Created
+//
+//---------------------------------------------------------------------
+static LPSTR FindDIBBits (LPSTR lpbi)
+{
+ return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi));
+}
+
+
+//---------------------------------------------------------------------
+//
+// Function: DIBNumColors
+//
+// Purpose: Given a pointer to a DIB, returns a number of colors in
+// the DIB's color table.
+//
+// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
+// or BITMAPCOREHEADER)
+//
+// History: Date Reason
+// 6/01/91 Created
+//
+//---------------------------------------------------------------------
+static WORD DIBNumColors (LPSTR lpbi)
+{
+ WORD wBitCount;
+
+
+ // If this is a Windows style DIB, the number of colors in the
+ // color table can be less than the number of bits per pixel
+ // allows for (i.e. lpbi->biClrUsed can be set to some value).
+ // If this is the case, return the appropriate value.
+
+ if (IS_WIN30_DIB (lpbi))
+ {
+ DWORD dwClrUsed;
+
+ dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
+
+ if (dwClrUsed)
+ return (WORD) dwClrUsed;
+ }
+
+
+ // Calculate the number of colors in the color table based on
+ // the number of bits per pixel for the DIB.
+
+ if (IS_WIN30_DIB (lpbi))
+ wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
+ else
+ wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
+
+ switch (wBitCount)
+ {
+ case 1:
+ return 2;
+
+ case 4:
+ return 16;
+
+ case 8:
+ return 256;
+
+ default:
+ return 0;
+ }
+}
+
+//---------------------------------------------------------------------
+//
+// Function: PaletteSize
+//
+// Purpose: Given a pointer to a DIB, returns number of bytes
+// in the DIB's color table.
+//
+// Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
+// or BITMAPCOREHEADER)
+//
+// History: Date Reason
+// 6/01/91 Created
+//
+//---------------------------------------------------------------------
+static WORD PaletteSize (LPSTR lpbi)
+{
+ if (IS_WIN30_DIB (lpbi))
+ return (DIBNumColors (lpbi) * sizeof (RGBQUAD));
+ else
+ return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE));
+}
+
+//---------------------------------------------------------------------
+//
+// Function: DIBHeight
+//
+// Purpose: Given a pointer to a DIB, returns its height. Note
+// that it returns a DWORD (since a Win30 DIB can have
+// a DWORD in its height field), but under Win30, the
+// high order word isn't used!
+//
+// Parms: lpDIB == pointer to DIB header (either BITMAPINFOHEADER
+// or BITMAPCOREHEADER)
+//
+// History: Date Reason
+// 6/01/91 Created
+//
+//---------------------------------------------------------------------
+static DWORD DIBHeight (LPSTR lpDIB)
+{
+ LPBITMAPINFOHEADER lpbmi;
+ LPBITMAPCOREHEADER lpbmc;
+
+ lpbmi = (LPBITMAPINFOHEADER) lpDIB;
+ lpbmc = (LPBITMAPCOREHEADER) lpDIB;
+
+ if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
+ return lpbmi->biHeight;
+ else
+ return (DWORD) lpbmc->bcHeight;
+}
+
+/*************************************************************************
+
+ Function: ReadDIBFile (int)
+
+ 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.
+
+ History: Date Author Reason
+
+ 6/1/91 Created
+ 6/27/91 Removed PM bitmap conversion routines.
+ 6/31/91 Removed logic which overallocated memory
+ (to account for bad display drivers).
+ 11/08/91 Again removed logic which overallocated
+ memory (it had creeped back in!)
+
+*************************************************************************/
+static HANDLE ReadDIBFile (int hFile,int dwBitsSize)
+{
+ BITMAPFILEHEADER bmfHeader;
+ HANDLE hDIB;
+ LPSTR pDIB;
+
+
+
+ // Go read the DIB file header and check if it's valid.
+
+ if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) ||
+ (bmfHeader.bfType != DIB_HEADER_MARKER))
+ {
+ // ShowDbgMsg("Not a DIB file!");
+ return NULL;
+ }
+
+ // Allocate memory for DIB
+
+ hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER));
+
+ if (hDIB == 0)
+ {
+ // ShowDbgMsg("Couldn't allocate memory!");
+ return NULL;
+ }
+
+ pDIB = GlobalLock (hDIB);
+
+ // Go read the bits.
+
+ if (!MyRead (hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
+ {
+ GlobalUnlock (hDIB);
+ GlobalFree (hDIB);
+ // ShowDbgMsg("Error reading file!");
+ return NULL;
+ }
+
+
+ GlobalUnlock (hDIB);
+ return hDIB;
+}
+
+/*************************************************************************
+
+ Function: MyRead (int, LPSTR, DWORD)
+
+ Purpose: Routine to read files greater than 64K in size.
+
+ Returns: TRUE if successful.
+ FALSE if an error occurs.
+
+ Comments:
+
+ History: Date Reason
+
+ 6/1/91 Created
+
+*************************************************************************/
+static BOOL MyRead (int hFile, LPSTR lpBuffer, DWORD dwSize)
+{
+ char *lpInBuf = (char *) lpBuffer;
+ int nBytes;
+
+
+ while (dwSize)
+ {
+ nBytes = (int) (dwSize > (DWORD) BYTES_PER_READ ? BYTES_PER_READ :
+ LOWORD (dwSize));
+
+ if (_lread (hFile, (LPSTR) lpInBuf, nBytes) != (WORD) nBytes)
+ return FALSE;
+
+ dwSize -= nBytes;
+ lpInBuf += nBytes;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------
+//
+// Function: DIBPaint
+//
+// Purpose: Painting routine for a DIB. Calls StretchDIBits() or
+// SetDIBitsToDevice() to paint the DIB. The DIB is
+// output to the specified DC, at the coordinates given
+// in lpDCRect. The area of the DIB to be output is
+// given by lpDIBRect. The specified palette is used.
+//
+// Parms: hDC == DC to do output to.
+// lpDCRect == Rectangle on DC to do output to.
+// hDIB == Handle to global memory with a DIB spec
+// in it (either a BITMAPINFO or BITMAPCOREINFO
+// followed by the DIB bits).
+// lpDIBRect == Rect of DIB to output into lpDCRect.
+// hPal == Palette to be used.
+//
+// History: Date Reason
+// 6/01/91 Created
+//
+//---------------------------------------------------------------------
+static void DIBPaint (HDC hDC,LPRECT lpDCRect,HANDLE hDIB)
+{
+ LPSTR lpDIBHdr, lpDIBBits;
+
+ if (!hDIB)
+ return;
+ // Lock down the DIB, and get a pointer to the beginning of the bit
+ // buffer.
+ lpDIBHdr = GlobalLock (hDIB);
+ lpDIBBits = FindDIBBits (lpDIBHdr);
+ // Make sure to use the stretching mode best for color pictures.
+ SetStretchBltMode (hDC, COLORONCOLOR);
+ SetDIBitsToDevice (hDC, // hDC
+ lpDCRect->left, // DestX
+ lpDCRect->top, // DestY
+ RECTWIDTH (lpDCRect), // nDestWidth
+ RECTHEIGHT (lpDCRect), // nDestHeight
+ 0, // SrcX
+ 0,
+ // (int) DIBHeight (lpDIBHdr), // SrcY
+ 0, // nStartScan
+ (WORD) DIBHeight (lpDIBHdr), // nNumScans
+ lpDIBBits, // lpBits
+ (LPBITMAPINFO) lpDIBHdr, // lpBitsInfo
+ DIB_RGB_COLORS); // wUsage
+
+ GlobalUnlock (hDIB);
+}
+
+static unsigned int Getfilesize(char *name)
+{
+ FILE *f;
+ unsigned int size;
+
+ f = fopen(name,"rb");
+ if (f == NULL)
+ return 0;
+ fseek(f,0,SEEK_END);
+ size = ftell(f);
+ fclose(f);
+ return size;
+}
+
+
+HANDLE ChargerBitmap(char *FileName,POINT *lppt)
+{
+ HFILE hFile;
+ OFSTRUCT ofstruct;
+ HANDLE result;
+ LPSTR lpDIBHdr;
+ unsigned int size;
+
+ size = Getfilesize(FileName);
+ hFile=OpenFile((LPSTR) FileName, &ofstruct, OF_READ | OF_SHARE_DENY_WRITE);
+ result = ReadDIBFile(hFile,size);
+ if (hFile) _lclose(hFile);
+ if (result) {
+ LPBITMAPINFOHEADER lpbmi;
+ LPBITMAPCOREHEADER lpbmc;
+
+ lpDIBHdr = GlobalLock (result);
+ lpbmi = (LPBITMAPINFOHEADER) lpDIBHdr;
+ lpbmc = (LPBITMAPCOREHEADER) lpDIBHdr;
+
+ if (lpbmi->biSize == sizeof (BITMAPINFOHEADER)) {
+ lppt->y = lpbmi->biHeight;
+ lppt->x = lpbmi->biWidth;
+ }
+ else {
+ lppt->y = lpbmc->bcHeight;
+ lppt->x = lpbmc->bcWidth;
+ }
+ GlobalUnlock(result);
+ }
+ return(result);
+}
+
+void DessinerBitmap(HANDLE hDIB,HDC hDC,LPRECT lpDCRect)
+{
+ DIBPaint (hDC,
+ lpDCRect,
+ hDIB);
+}
+
+void AfficheBitmap(char *filename,HDC hDC,int x,int y)
+{
+ RECT rc;
+ HANDLE hdib;
+ POINT pt;
+ char titi[60];
+
+ hdib = ChargerBitmap(filename,&pt);
+ if (hdib == NULL) {
+ return;
+ }
+ rc.top = y;
+ rc.left = x;
+ rc.right = pt.x+x;
+ rc.bottom = pt.y+y;
+ pt.y += GetSystemMetrics(SM_CYCAPTION);
+ DessinerBitmap(hdib,hDC,&rc);
+ GlobalFree(hdib);
+}
+