1 /***********************************************************************/
5 /* Developed by Jacob Navia */
6 /* Copyright 2001 Institut National de Recherche en Informatique et */
7 /* en Automatique. All rights reserved. This file is distributed */
8 /* under the terms of the GNU Library General Public License, with */
9 /* the special exception on linking described in file ../../LICENSE. */
11 /***********************************************************************/
13 /* $Id: dib.c 5029 2002-07-23 14:12:03Z doligez $ */
15 //-----------------------------------------------------------------------------
18 // This is a collection of useful DIB manipulation/information gathering
19 // functions. Many functions are supplied simply to take the burden
20 // of taking into account whether a DIB is a Win30 style or OS/2 style
21 // DIB away from the application.
23 // The functions in this module assume that the DIB pointers or handles
24 // passed to them point to a block of memory in one of two formats:
26 // a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB)
27 // b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style)
29 // The SDK Reference, Volume 2 describes these data structures.
31 // A number of functions in this module were lifted from SHOWDIB,
32 // and modified to handle OS/2 DIBs.
34 // The functions in this module could be streamlined (made faster and
35 // smaller) by removing the OS/2 DIB specific code, and assuming all
36 // DIBs passed to it are Win30 style DIBs. The DIB file reading code
37 // would need to be modified to always convert DIBs to Win30 style
38 // DIBs. The only reason this isn't done in DIBView is because DIBView
39 // was written to test display and printer drivers (which are supposed
40 // to support OS/2 DIBs wherever they support Win30 style DIBs). SHOWDIB
41 // is a great example of how to go about doing this.
42 //-----------------------------------------------------------------------------
50 // Size of window extra bytes (we store a handle to a PALINFO structure).
52 #define PAL_CBWNDEXTRA (1 * sizeof (WORD))
57 HPALETTE hPal; // Handle to palette being displayed.
58 WORD wEntries; // # of entries in the palette.
59 int nSquareSize; // Size of palette square (see PAL_SIZE)
60 HWND hInfoWnd; // Handle to the info bar window.
61 int nRows, nCols; // # of Rows/Columns in window.
62 int cxSquare, cySquare; // Pixel width/height of palette square.
63 WORD wEntry; // Currently selected palette square.
64 } PALINFO, FAR *LPPALINFO;
66 #define WW_PAL_HPALINFO 0 // Handle to PALINFO structure.
67 // The following define is for CopyPaletteChangingFlags().
68 #define DONT_CHANGE_FLAGS -1
69 // The following is the palette version that goes in a
70 // LOGPALETTE's palVersion field.
71 #define PALVERSION 0x300
72 // This is an enumeration for the various ways we can display
73 // a palette in PaletteWndProc().
81 #define CopyPalette(hPal) CopyPaletteChangingFlags (hPal, DONT_CHANGE_FLAGS)
82 #define CopyPalForAnimation(hPal) CopyPaletteChangingFlags (hPal, PC_RESERVED)
83 // WIDTHBYTES takes # of bits in a scan line and rounds up to nearest
85 #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
87 // Given a pointer to a DIB header, return TRUE if is a Windows 3.0 style
88 // DIB, false if otherwise (PM style DIB).
89 #define IS_WIN30_DIB(lpbi) ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER))
91 static WORD PaletteSize (LPSTR lpbi);
93 extern void ShowDbgMsg(char *);
94 static BOOL MyRead (int, LPSTR, DWORD);
95 /*-------------- DIB header Marker Define -------------------------*/
96 #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
97 /*-------------- MyRead Function Define ---------------------------*/
99 // When we read in a DIB, we read it in in chunks. We read half a segment
100 // at a time. This way we insure that we don't cross any segment
101 // boundries in _lread() during a read. We don't read in a full segment
102 // at a time, since _lread takes some "int" type parms instead of
103 // WORD type params (it'd work, but the compiler would give you warnings)...
105 #define BYTES_PER_READ 32767
107 /*-------------- Define for PM DIB -------------------------------*/
108 // The constants for RGB, RLE4, RLE8 are already defined inside
114 /*-------------- Magic numbers -------------------------------------*/
115 // Maximum length of a filename for DOS is 128 characters.
117 #define MAX_FILENAME 129
120 /*-------------- TypeDef Structures -------------------------------*/
122 typedef struct InfoStruct
133 #define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
134 #define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
135 //---------------------------------------------------------------------
137 // Function: FindDIBBits
139 // Purpose: Given a pointer to a DIB, returns a pointer to the
140 // DIB's bitmap bits.
142 // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
143 // or BITMAPCOREHEADER)
145 // History: Date Reason
148 //---------------------------------------------------------------------
149 static LPSTR FindDIBBits (LPSTR lpbi)
151 return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi));
155 //---------------------------------------------------------------------
157 // Function: DIBNumColors
159 // Purpose: Given a pointer to a DIB, returns a number of colors in
160 // the DIB's color table.
162 // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
163 // or BITMAPCOREHEADER)
165 // History: Date Reason
168 //---------------------------------------------------------------------
169 static WORD DIBNumColors (LPSTR lpbi)
174 // If this is a Windows style DIB, the number of colors in the
175 // color table can be less than the number of bits per pixel
176 // allows for (i.e. lpbi->biClrUsed can be set to some value).
177 // If this is the case, return the appropriate value.
179 if (IS_WIN30_DIB (lpbi))
183 dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
186 return (WORD) dwClrUsed;
190 // Calculate the number of colors in the color table based on
191 // the number of bits per pixel for the DIB.
193 if (IS_WIN30_DIB (lpbi))
194 wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
196 wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
214 //---------------------------------------------------------------------
216 // Function: PaletteSize
218 // Purpose: Given a pointer to a DIB, returns number of bytes
219 // in the DIB's color table.
221 // Parms: lpbi == pointer to DIB header (either BITMAPINFOHEADER
222 // or BITMAPCOREHEADER)
224 // History: Date Reason
227 //---------------------------------------------------------------------
228 static WORD PaletteSize (LPSTR lpbi)
230 if (IS_WIN30_DIB (lpbi))
231 return (DIBNumColors (lpbi) * sizeof (RGBQUAD));
233 return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE));
236 //---------------------------------------------------------------------
238 // Function: DIBHeight
240 // Purpose: Given a pointer to a DIB, returns its height. Note
241 // that it returns a DWORD (since a Win30 DIB can have
242 // a DWORD in its height field), but under Win30, the
243 // high order word isn't used!
245 // Parms: lpDIB == pointer to DIB header (either BITMAPINFOHEADER
246 // or BITMAPCOREHEADER)
248 // History: Date Reason
251 //---------------------------------------------------------------------
252 static DWORD DIBHeight (LPSTR lpDIB)
254 LPBITMAPINFOHEADER lpbmi;
255 LPBITMAPCOREHEADER lpbmc;
257 lpbmi = (LPBITMAPINFOHEADER) lpDIB;
258 lpbmc = (LPBITMAPCOREHEADER) lpDIB;
260 if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
261 return lpbmi->biHeight;
263 return (DWORD) lpbmc->bcHeight;
266 /*************************************************************************
268 Function: ReadDIBFile (int)
270 Purpose: Reads in the specified DIB file into a global chunk of
273 Returns: A handle to a dib (hDIB) if successful.
274 NULL if an error occurs.
276 Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
277 from the end of the BITMAPFILEHEADER structure on is
278 returned in the global memory handle.
280 History: Date Author Reason
283 6/27/91 Removed PM bitmap conversion routines.
284 6/31/91 Removed logic which overallocated memory
285 (to account for bad display drivers).
286 11/08/91 Again removed logic which overallocated
287 memory (it had creeped back in!)
289 *************************************************************************/
290 static HANDLE ReadDIBFile (int hFile,int dwBitsSize)
292 BITMAPFILEHEADER bmfHeader;
298 // Go read the DIB file header and check if it's valid.
300 if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) ||
301 (bmfHeader.bfType != DIB_HEADER_MARKER))
303 // ShowDbgMsg("Not a DIB file!");
307 // Allocate memory for DIB
309 hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER));
313 // ShowDbgMsg("Couldn't allocate memory!");
317 pDIB = GlobalLock (hDIB);
321 if (!MyRead (hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
325 // ShowDbgMsg("Error reading file!");
334 /*************************************************************************
336 Function: MyRead (int, LPSTR, DWORD)
338 Purpose: Routine to read files greater than 64K in size.
340 Returns: TRUE if successful.
341 FALSE if an error occurs.
349 *************************************************************************/
350 static BOOL MyRead (int hFile, LPSTR lpBuffer, DWORD dwSize)
352 char *lpInBuf = (char *) lpBuffer;
358 nBytes = (int) (dwSize > (DWORD) BYTES_PER_READ ? BYTES_PER_READ :
361 if (_lread (hFile, (LPSTR) lpInBuf, nBytes) != (WORD) nBytes)
371 //---------------------------------------------------------------------
373 // Function: DIBPaint
375 // Purpose: Painting routine for a DIB. Calls StretchDIBits() or
376 // SetDIBitsToDevice() to paint the DIB. The DIB is
377 // output to the specified DC, at the coordinates given
378 // in lpDCRect. The area of the DIB to be output is
379 // given by lpDIBRect. The specified palette is used.
381 // Parms: hDC == DC to do output to.
382 // lpDCRect == Rectangle on DC to do output to.
383 // hDIB == Handle to global memory with a DIB spec
384 // in it (either a BITMAPINFO or BITMAPCOREINFO
385 // followed by the DIB bits).
386 // lpDIBRect == Rect of DIB to output into lpDCRect.
387 // hPal == Palette to be used.
389 // History: Date Reason
392 //---------------------------------------------------------------------
393 static void DIBPaint (HDC hDC,LPRECT lpDCRect,HANDLE hDIB)
395 LPSTR lpDIBHdr, lpDIBBits;
399 // Lock down the DIB, and get a pointer to the beginning of the bit
401 lpDIBHdr = GlobalLock (hDIB);
402 lpDIBBits = FindDIBBits (lpDIBHdr);
403 // Make sure to use the stretching mode best for color pictures.
404 SetStretchBltMode (hDC, COLORONCOLOR);
405 SetDIBitsToDevice (hDC, // hDC
406 lpDCRect->left, // DestX
407 lpDCRect->top, // DestY
408 RECTWIDTH (lpDCRect), // nDestWidth
409 RECTHEIGHT (lpDCRect), // nDestHeight
412 // (int) DIBHeight (lpDIBHdr), // SrcY
414 (WORD) DIBHeight (lpDIBHdr), // nNumScans
416 (LPBITMAPINFO) lpDIBHdr, // lpBitsInfo
417 DIB_RGB_COLORS); // wUsage
422 static unsigned int Getfilesize(char *name)
427 f = fopen(name,"rb");
437 HANDLE ChargerBitmap(char *FileName,POINT *lppt)
445 size = Getfilesize(FileName);
446 hFile=OpenFile((LPSTR) FileName, &ofstruct, OF_READ | OF_SHARE_DENY_WRITE);
447 result = ReadDIBFile(hFile,size);
448 if (hFile) _lclose(hFile);
450 LPBITMAPINFOHEADER lpbmi;
451 LPBITMAPCOREHEADER lpbmc;
453 lpDIBHdr = GlobalLock (result);
454 lpbmi = (LPBITMAPINFOHEADER) lpDIBHdr;
455 lpbmc = (LPBITMAPCOREHEADER) lpDIBHdr;
457 if (lpbmi->biSize == sizeof (BITMAPINFOHEADER)) {
458 lppt->y = lpbmi->biHeight;
459 lppt->x = lpbmi->biWidth;
462 lppt->y = lpbmc->bcHeight;
463 lppt->x = lpbmc->bcWidth;
465 GlobalUnlock(result);
470 void DessinerBitmap(HANDLE hDIB,HDC hDC,LPRECT lpDCRect)
477 void AfficheBitmap(char *filename,HDC hDC,int x,int y)
484 hdib = ChargerBitmap(filename,&pt);
492 pt.y += GetSystemMetrics(SM_CYCAPTION);
493 DessinerBitmap(hdib,hDC,&rc);