]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ocaml/ocaml/contrib/otherlibs/win32graph/dib.c
Update
[l4.git] / l4 / pkg / ocaml / ocaml / contrib / otherlibs / win32graph / dib.c
1 /***********************************************************************/
2 /*                                                                     */
3 /*                           Objective Caml                            */
4 /*                                                                     */
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.  */
10 /*                                                                     */
11 /***********************************************************************/
12
13 /* $Id: dib.c 5029 2002-07-23 14:12:03Z doligez $ */
14
15 //-----------------------------------------------------------------------------
16 // DIB.C
17 //
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.
22 //
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:
25 //
26 //       a) BITMAPINFOHEADER + color table + DIB bits (3.0 style DIB)
27 //       b) BITMAPCOREHEADER + color table + DIB bits (OS/2 PM style)
28 //
29 // The SDK Reference, Volume 2 describes these data structures.
30 //
31 // A number of functions in this module were lifted from SHOWDIB,
32 // and modified to handle OS/2 DIBs.
33 //
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 //-----------------------------------------------------------------------------
43
44
45 #include <windows.h>
46 #include <memory.h>
47 #include <string.h>
48 #include <io.h>
49 #include <stdio.h>
50    // Size of window extra bytes (we store a handle to a PALINFO structure).
51
52 #define PAL_CBWNDEXTRA  (1 * sizeof (WORD))
53
54
55 typedef struct
56    {
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;
65    // Window Words.
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().
74 enum PAL_SIZE
75    {
76    PALSIZE_TINY = 0,
77    PALSIZE_SMALL,
78    PALSIZE_MEDIUM,
79    PALSIZE_LARGE
80    };
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
84 //  word.
85 #define WIDTHBYTES(bits)      (((bits) + 31) / 32 * 4)
86
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))
90
91 static WORD     PaletteSize          (LPSTR lpbi);
92
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 ---------------------------*/
98
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)...
104
105 #define BYTES_PER_READ  32767
106
107 /*--------------  Define for PM DIB  -------------------------------*/
108 // The constants for RGB, RLE4, RLE8 are already defined inside
109 // of Windows.h
110
111 #define BI_PM       3L
112
113
114 /*-------------- Magic numbers -------------------------------------*/
115 // Maximum length of a filename for DOS is 128 characters.
116
117 #define MAX_FILENAME 129
118
119
120 /*--------------  TypeDef Structures -------------------------------*/
121
122 typedef struct InfoStruct
123   {
124   char  szName[13];
125   char  szType[15];
126   DWORD cbWidth;
127   DWORD cbHeight;
128   DWORD cbColors;
129   char  szCompress[5];
130   }  INFOSTRUCT;
131
132 // Some macros.
133 #define RECTWIDTH(lpRect)     ((lpRect)->right - (lpRect)->left)
134 #define RECTHEIGHT(lpRect)    ((lpRect)->bottom - (lpRect)->top)
135 //---------------------------------------------------------------------
136 //
137 // Function:   FindDIBBits
138 //
139 // Purpose:    Given a pointer to a DIB, returns a pointer to the
140 //             DIB's bitmap bits.
141 //
142 // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
143 //                       or BITMAPCOREHEADER)
144 //
145 // History:   Date      Reason
146 //             6/01/91  Created
147 //
148 //---------------------------------------------------------------------
149 static LPSTR FindDIBBits (LPSTR lpbi)
150 {
151    return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi));
152 }
153
154
155 //---------------------------------------------------------------------
156 //
157 // Function:   DIBNumColors
158 //
159 // Purpose:    Given a pointer to a DIB, returns a number of colors in
160 //             the DIB's color table.
161 //
162 // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
163 //                       or BITMAPCOREHEADER)
164 //
165 // History:   Date      Reason
166 //             6/01/91  Created
167 //
168 //---------------------------------------------------------------------
169 static WORD DIBNumColors (LPSTR lpbi)
170 {
171    WORD wBitCount;
172
173
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.
178
179    if (IS_WIN30_DIB (lpbi))
180       {
181       DWORD dwClrUsed;
182
183       dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
184
185       if (dwClrUsed)
186          return (WORD) dwClrUsed;
187       }
188
189
190       // Calculate the number of colors in the color table based on
191       //  the number of bits per pixel for the DIB.
192
193    if (IS_WIN30_DIB (lpbi))
194       wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
195    else
196       wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
197
198    switch (wBitCount)
199       {
200       case 1:
201          return 2;
202
203       case 4:
204          return 16;
205
206       case 8:
207          return 256;
208
209       default:
210          return 0;
211       }
212 }
213
214 //---------------------------------------------------------------------
215 //
216 // Function:   PaletteSize
217 //
218 // Purpose:    Given a pointer to a DIB, returns number of bytes
219 //             in the DIB's color table.
220 //
221 // Parms:      lpbi == pointer to DIB header (either BITMAPINFOHEADER
222 //                       or BITMAPCOREHEADER)
223 //
224 // History:   Date      Reason
225 //             6/01/91  Created
226 //
227 //---------------------------------------------------------------------
228 static WORD PaletteSize (LPSTR lpbi)
229 {
230    if (IS_WIN30_DIB (lpbi))
231       return (DIBNumColors (lpbi) * sizeof (RGBQUAD));
232    else
233       return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE));
234 }
235
236 //---------------------------------------------------------------------
237 //
238 // Function:   DIBHeight
239 //
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!
244 //
245 // Parms:      lpDIB == pointer to DIB header (either BITMAPINFOHEADER
246 //                       or BITMAPCOREHEADER)
247 //
248 // History:   Date      Reason
249 //             6/01/91  Created
250 //
251 //---------------------------------------------------------------------
252 static DWORD DIBHeight (LPSTR lpDIB)
253 {
254    LPBITMAPINFOHEADER lpbmi;
255    LPBITMAPCOREHEADER lpbmc;
256
257    lpbmi = (LPBITMAPINFOHEADER) lpDIB;
258    lpbmc = (LPBITMAPCOREHEADER) lpDIB;
259
260    if (lpbmi->biSize == sizeof (BITMAPINFOHEADER))
261       return lpbmi->biHeight;
262    else
263       return (DWORD) lpbmc->bcHeight;
264 }
265
266 /*************************************************************************
267
268   Function:  ReadDIBFile (int)
269
270    Purpose:  Reads in the specified DIB file into a global chunk of
271              memory.
272
273    Returns:  A handle to a dib (hDIB) if successful.
274              NULL if an error occurs.
275
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.
279
280    History:   Date      Author      Reason
281
282              6/1/91    Created
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!)
288
289 *************************************************************************/
290 static HANDLE ReadDIBFile (int hFile,int dwBitsSize)
291 {
292    BITMAPFILEHEADER   bmfHeader;
293    HANDLE             hDIB;
294    LPSTR              pDIB;
295
296
297
298    // Go read the DIB file header and check if it's valid.
299
300    if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) ||
301         (bmfHeader.bfType != DIB_HEADER_MARKER))
302       {
303         //              ShowDbgMsg("Not a DIB file!");
304                 return NULL;
305       }
306
307    // Allocate memory for DIB
308
309    hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER));
310
311    if (hDIB == 0)
312      {
313        //       ShowDbgMsg("Couldn't allocate memory!");
314                 return NULL;
315      }
316
317    pDIB = GlobalLock (hDIB);
318
319    // Go read the bits.
320
321    if (!MyRead (hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
322       {
323       GlobalUnlock (hDIB);
324       GlobalFree   (hDIB);
325       //  ShowDbgMsg("Error reading file!");
326       return NULL;
327       }
328
329
330    GlobalUnlock (hDIB);
331    return hDIB;
332 }
333
334 /*************************************************************************
335
336   Function:  MyRead (int, LPSTR, DWORD)
337
338    Purpose:  Routine to read files greater than 64K in size.
339
340    Returns:  TRUE if successful.
341              FALSE if an error occurs.
342
343   Comments:
344
345    History:   Date     Reason
346
347              6/1/91    Created
348
349 *************************************************************************/
350 static BOOL MyRead (int hFile, LPSTR lpBuffer, DWORD dwSize)
351 {
352    char *lpInBuf = (char *) lpBuffer;
353    int       nBytes;
354
355
356    while (dwSize)
357       {
358       nBytes = (int) (dwSize > (DWORD) BYTES_PER_READ ? BYTES_PER_READ :
359                                                         LOWORD (dwSize));
360
361       if (_lread (hFile, (LPSTR) lpInBuf, nBytes) != (WORD) nBytes)
362          return FALSE;
363
364       dwSize  -= nBytes;
365       lpInBuf += nBytes;
366       }
367
368    return TRUE;
369 }
370
371 //---------------------------------------------------------------------
372 //
373 // Function:   DIBPaint
374 //
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.
380 //
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.
388 //
389 // History:   Date      Reason
390 //             6/01/91  Created
391 //
392 //---------------------------------------------------------------------
393 static void DIBPaint (HDC hDC,LPRECT lpDCRect,HANDLE hDIB)
394 {
395    LPSTR    lpDIBHdr, lpDIBBits;
396
397    if (!hDIB)
398       return;
399       // Lock down the DIB, and get a pointer to the beginning of the bit
400       //  buffer.
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
410                                                                  0,              // SrcX
411                          0,
412  //                        (int) DIBHeight (lpDIBHdr),   // SrcY
413                                                                  0,                            // nStartScan
414                          (WORD) DIBHeight (lpDIBHdr),  // nNumScans
415                          lpDIBBits,                    // lpBits
416                          (LPBITMAPINFO) lpDIBHdr,      // lpBitsInfo
417                          DIB_RGB_COLORS);              // wUsage
418
419    GlobalUnlock (hDIB);
420 }
421
422 static unsigned int Getfilesize(char *name)
423 {
424         FILE *f;
425         unsigned int size;
426
427         f = fopen(name,"rb");
428         if (f == NULL)
429                 return 0;
430         fseek(f,0,SEEK_END);
431         size = ftell(f);
432         fclose(f);
433         return size;
434 }
435
436
437 HANDLE ChargerBitmap(char *FileName,POINT *lppt)
438 {
439         HFILE hFile;
440         OFSTRUCT ofstruct;
441         HANDLE result;
442         LPSTR    lpDIBHdr;
443         unsigned int size;
444
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);
449         if (result) {
450                 LPBITMAPINFOHEADER lpbmi;
451                 LPBITMAPCOREHEADER lpbmc;
452
453                 lpDIBHdr  = GlobalLock (result);
454                 lpbmi = (LPBITMAPINFOHEADER) lpDIBHdr;
455                 lpbmc = (LPBITMAPCOREHEADER) lpDIBHdr;
456
457                 if (lpbmi->biSize == sizeof (BITMAPINFOHEADER)) {
458                         lppt->y = lpbmi->biHeight;
459                         lppt->x = lpbmi->biWidth;
460                 }
461                 else {
462                         lppt->y = lpbmc->bcHeight;
463                         lppt->x = lpbmc->bcWidth;
464                 }
465                 GlobalUnlock(result);
466         }
467         return(result);
468 }
469
470 void DessinerBitmap(HANDLE hDIB,HDC hDC,LPRECT lpDCRect)
471 {
472         DIBPaint (hDC,
473              lpDCRect,
474              hDIB);
475 }
476
477 void AfficheBitmap(char *filename,HDC hDC,int x,int y)
478 {
479         RECT rc;
480         HANDLE hdib;
481         POINT pt;
482         char titi[60];
483
484         hdib = ChargerBitmap(filename,&pt);
485         if (hdib == NULL) {
486                 return;
487     }
488         rc.top = y;
489         rc.left = x;
490         rc.right = pt.x+x;
491         rc.bottom = pt.y+y;
492         pt.y += GetSystemMetrics(SM_CYCAPTION);
493         DessinerBitmap(hdib,hDC,&rc);
494         GlobalFree(hdib);
495 }
496