]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dibutils.cpp
Removed floor() references
[wxWidgets.git] / src / msw / dibutils.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dibutils.cpp
3// Purpose: Utilities for DIBs
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Microsoft, Julian Smart and Markus Holzem
3f4a0c5b 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "dibutils.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <stdio.h>
25#include "wx/setup.h"
26#include "wx/defs.h"
27#endif
28
29#include <windows.h>
30#include <windowsx.h>
31#include <stdio.h>
3f4a0c5b
VZ
32
33#include "wx/msw/dibutils.h"
2bda0e17
KB
34
35#if defined(__WIN32__)
ce3ed50d 36#if !defined(__MWERKS__) && !defined(__SALFORDC__)
2bda0e17 37 #include <memory.h> // for _fmemcpy()
17dff81c 38#endif
3f4a0c5b 39 #define _huge
2bda0e17
KB
40#ifndef hmemcpy
41 #define hmemcpy memcpy
42#endif
43#endif
44
45#define BFT_ICON 0x4349 /* 'IC' */
46#define BFT_BITMAP 0x4d42 /* 'BM' */
47#define BFT_CURSOR 0x5450 /* 'PT' */
48
49/* flags for _lseek */
50#define SEEK_CUR 1
51#define SEEK_END 2
52#define SEEK_SET 0
53
54
55/*
56 * Clear the System Palette so that we can ensure an identity palette
57 * mapping for fast performance.
58 */
59
60void ClearSystemPalette(void)
61{
62 //*** A dummy palette setup
63 struct
64 {
65 WORD Version;
66 WORD NumberOfEntries;
67 PALETTEENTRY aEntries[256];
68 } Palette =
69 {
70 0x300,
71 256
72 };
73
74 HPALETTE ScreenPalette = 0;
75 HDC ScreenDC;
76 int Counter;
77 UINT nMapped = 0;
78 BOOL bOK = FALSE;
79 int nOK = 0;
80
81 //*** Reset everything in the system palette to black
82 for(Counter = 0; Counter < 256; Counter++)
83 {
84 Palette.aEntries[Counter].peRed = 0;
3f4a0c5b 85 Palette.aEntries[Counter].peGreen = 0;
2bda0e17
KB
86 Palette.aEntries[Counter].peBlue = 0;
87 Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
88 }
89
90 //*** Create, select, realize, deselect, and delete the palette
91 ScreenDC = GetDC(NULL);
92 ScreenPalette = CreatePalette((LOGPALETTE *)&Palette);
93
94 if (ScreenPalette)
95 {
3f4a0c5b
VZ
96 ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
97 nMapped = RealizePalette(ScreenDC);
2bda0e17
KB
98 ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
99 bOK = DeleteObject(ScreenPalette);
100 }
101
102 nOK = ReleaseDC(NULL, ScreenDC);
103
104 return;
105}
106
107
108/*
109 * Open a DIB file and return a MEMORY DIB, a memory handle containing..
110 *
111 * BITMAP INFO bi
112 * palette data
113 * bits....
114 */
115
116int DibWriteFile(LPSTR szFile, LPBITMAPINFOHEADER lpbi)
117{
3f4a0c5b
VZ
118 HFILE fh;
119 OFSTRUCT of;
2bda0e17 120
3f4a0c5b 121 fh = OpenFile(szFile, &of, OF_WRITE | OF_CREATE);
2bda0e17
KB
122
123 if (!fh) {
3f4a0c5b
VZ
124// printf("la regamos0");
125 return 0;
2bda0e17
KB
126 }
127
128 long size = DibSize(lpbi);
129
130 // write file header
131 BITMAPFILEHEADER bmf;
132 bmf.bfType = 'BM';
133 bmf.bfSize = sizeof(bmf) + size;
134 bmf.bfReserved1 = 0;
135 bmf.bfReserved2 = 0;
136 bmf.bfOffBits = sizeof(bmf) + (char far*)(DibPtr(lpbi)) - (char far*)lpbi;
e3065973 137#if defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__)
2bda0e17 138 if (_hwrite(fh, (LPCSTR)(&bmf), sizeof(bmf))<0 ||
3f4a0c5b
VZ
139 _hwrite(fh, (LPCSTR)lpbi, size)<0) {
140 _lclose(fh);
141// printf("la regamos1");
142 return 0;
2bda0e17
KB
143 }
144#else
145 if (_hwrite(fh, (LPBYTE)(&bmf), sizeof(bmf))<0 ||
3f4a0c5b
VZ
146 _hwrite(fh, (LPBYTE)lpbi, size)<0) {
147 _lclose(fh);
148// printf("la regamos1");
149 return 0;
2bda0e17
KB
150 }
151#endif
152
153 _lclose(fh);
154 return 1;
155}
156
157PDIB DibOpenFile(LPSTR szFile)
158{
3f4a0c5b
VZ
159 HFILE fh;
160 DWORD dwLen;
161 DWORD dwBits;
162 PDIB pdib;
163 LPVOID p;
164 OFSTRUCT of;
2bda0e17
KB
165
166#if defined(WIN32) || defined(_WIN32)
3f4a0c5b 167 #define GetCurrentInstance() GetModuleHandle(NULL)
2bda0e17 168#else
3f4a0c5b 169 #define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
2bda0e17
KB
170#endif
171
3f4a0c5b 172 fh = OpenFile(szFile, &of, OF_READ);
2bda0e17 173
3f4a0c5b
VZ
174 if (fh == -1)
175 {
176 HRSRC h;
2bda0e17
KB
177
178 // TODO: Unicode version
62448488 179#ifdef __WIN16__
3f4a0c5b 180 h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
62448488 181#else
3f4a0c5b 182 h = FindResourceA(GetCurrentInstance(), szFile, RT_BITMAP);
62448488 183#endif
2bda0e17 184
62448488 185#if defined(__WIN32__)
3f4a0c5b
VZ
186 //!!! can we call GlobalFree() on this? is it the right format.
187 //!!! can we write to this resource?
188 if (h)
189 return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
2bda0e17 190#else
3f4a0c5b
VZ
191 if (h)
192 fh = AccessResource(GetCurrentInstance(), h);
2bda0e17 193#endif
3f4a0c5b 194 }
2bda0e17 195
3f4a0c5b
VZ
196 if (fh == -1)
197 return NULL;
2bda0e17 198
3f4a0c5b 199 pdib = DibReadBitmapInfo(fh);
2bda0e17 200
3f4a0c5b
VZ
201 if (!pdib)
202 return NULL;
2bda0e17
KB
203
204 /* How much memory do we need to hold the DIB */
205
206 dwBits = pdib->biSizeImage;
207 dwLen = pdib->biSize + DibPaletteSize(pdib) + dwBits;
208
209 /* Can we get more memory? */
210
3f4a0c5b 211 p = GlobalReAllocPtr(pdib,dwLen,0);
2bda0e17
KB
212
213 if (!p)
214 {
3f4a0c5b 215 GlobalFreePtr(pdib);
2bda0e17
KB
216 pdib = NULL;
217 }
218 else
219 {
220 pdib = (PDIB)p;
221 }
222
223 if (pdib)
224 {
3f4a0c5b
VZ
225 /* read in the bits */
226 _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib), dwBits);
2bda0e17
KB
227 }
228
229 _lclose(fh);
230
231 return pdib;
232}
233
234
235/*
236 * ReadDibBitmapInfo()
237 *
238 * Will read a file in DIB format and return a global HANDLE to its
239 * BITMAPINFO. This function will work with both "old" and "new"
240 * bitmap formats, but will always return a "new" BITMAPINFO.
241 */
242
243PDIB DibReadBitmapInfo(HFILE fh)
244{
245 DWORD off;
2bda0e17
KB
246 int size;
247 int i;
248 int nNumColors;
249
250 RGBQUAD FAR *pRgb;
251 BITMAPINFOHEADER bi;
252 BITMAPCOREHEADER bc;
253 BITMAPFILEHEADER bf;
254 PDIB pdib;
255
256 if (fh == -1)
257 return NULL;
258
259 off = _llseek(fh,0L,SEEK_CUR);
260
261 if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
262 return FALSE;
263
264 /*
265 * do we have a RC HEADER?
266 */
267 if (bf.bfType != BFT_BITMAP)
268 {
269 bf.bfOffBits = 0L;
270 _llseek(fh,off,SEEK_SET);
271 }
272
273 if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
274 return FALSE;
275
276 /*
277 * what type of bitmap info is this?
278 */
279 switch (size = (int)bi.biSize)
280 {
281 default:
282 case sizeof(BITMAPINFOHEADER):
283 break;
284
285 case sizeof(BITMAPCOREHEADER):
286 bc = *(BITMAPCOREHEADER*)&bi;
287 bi.biSize = sizeof(BITMAPINFOHEADER);
288 bi.biWidth = (DWORD)bc.bcWidth;
289 bi.biHeight = (DWORD)bc.bcHeight;
290 bi.biPlanes = (UINT)bc.bcPlanes;
291 bi.biBitCount = (UINT)bc.bcBitCount;
292 bi.biCompression = BI_RGB;
293 bi.biSizeImage = 0;
294 bi.biXPelsPerMeter = 0;
295 bi.biYPelsPerMeter = 0;
296 bi.biClrUsed = 0;
297 bi.biClrImportant = 0;
298
299 _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
300
301 break;
302 }
303
304 nNumColors = DibNumColors(&bi);
305
306#if 0
307 if (bi.biSizeImage == 0)
308 bi.biSizeImage = DibSizeImage(&bi);
309
310 if (bi.biClrUsed == 0)
311 bi.biClrUsed = DibNumColors(&bi);
312#else
313 FixBitmapInfo(&bi);
314#endif
315
316 pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
317
318 if (!pdib)
319 return NULL;
320
321 *pdib = bi;
322
323 pRgb = DibColors(pdib);
324
325 if (nNumColors)
326 {
327 if (size == sizeof(BITMAPCOREHEADER))
328 {
329 /*
330 * convert a old color table (3 byte entries) to a new
331 * color table (4 byte entries)
332 */
333 _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
334
335 for (i=nNumColors-1; i>=0; i--)
336 {
337 RGBQUAD rgb;
338
339 rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
340 rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
341 rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
342 rgb.rgbReserved = (BYTE)0;
343
344 pRgb[i] = rgb;
345 }
346 }
347 else
348 {
349 _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
350 }
351 }
352
353 if (bf.bfOffBits != 0L)
354 _llseek(fh,off + bf.bfOffBits,SEEK_SET);
355
356 return pdib;
357}
358
359/*
360 * DibSetUsage(hdib,hpal,wUsage)
361 *
362 * Modifies the color table of the passed DIB for use with the wUsage
363 * parameter specifed.
364 *
365 * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
366 * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
367 * in the passed palette
368 */
369
370BOOL DibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
371{
372 PALETTEENTRY ape[256];
373 RGBQUAD FAR * pRgb;
374 WORD FAR * pw;
375 int nColors;
376 int n;
377
378 if (hpal == NULL)
379 hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
380
381 if (!pdib)
382 return FALSE;
383
384 nColors = DibNumColors(pdib);
385
386 if (nColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
387 nColors = 0;
388
389 if (nColors > 0)
390 {
391 pRgb = DibColors(pdib);
392
393 switch (wUsage)
394 {
395 //
396 // Set the DIB color table to palette indexes
397 //
398 case DIB_PAL_COLORS:
399 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
400 *pw = n;
401 break;
402
403 //
404 // Set the DIB color table to RGBQUADS
405 //
406 default:
407 case DIB_RGB_COLORS:
408 nColors = (nColors < 256) ? nColors: 256;
409
410 GetPaletteEntries(hpal,0,nColors,ape);
411
412 for (n=0; n<nColors; n++)
413 {
414 pRgb[n].rgbRed = ape[n].peRed;
415 pRgb[n].rgbGreen = ape[n].peGreen;
416 pRgb[n].rgbBlue = ape[n].peBlue;
417 pRgb[n].rgbReserved = 0;
418 }
419 break;
420 }
421 }
422 return TRUE;
423}
424
425/*
426 * DibCreate(bits, dx, dy)
427 *
428 * Creates a new packed DIB with the given dimensions and the
429 * given number of bits per pixel
430 */
431
432PDIB DibCreate(int bits, int dx, int dy)
433{
434 LPBITMAPINFOHEADER lpbi ;
435 DWORD dwSizeImage;
436 int i;
437 DWORD FAR *pdw;
438
439 dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
440
441 lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
442
443 if (lpbi == NULL)
444 return NULL;
445
446 lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
447 lpbi->biWidth = dx;
448 lpbi->biHeight = dy;
449 lpbi->biPlanes = 1;
450 lpbi->biBitCount = bits ;
451 lpbi->biCompression = BI_RGB ;
452 lpbi->biSizeImage = dwSizeImage;
453 lpbi->biXPelsPerMeter = 0 ;
454 lpbi->biYPelsPerMeter = 0 ;
455 lpbi->biClrUsed = 0 ;
456 lpbi->biClrImportant = 0 ;
457
458 if (bits == 4)
459 lpbi->biClrUsed = 16;
460
461 else if (bits == 8)
462 lpbi->biClrUsed = 256;
463
464 pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
465
466 for (i=0; i<(int)lpbi->biClrUsed/16; i++)
467 {
468 *pdw++ = 0x00000000; // 0000 black
469 *pdw++ = 0x00800000; // 0001 dark red
470 *pdw++ = 0x00008000; // 0010 dark green
3f4a0c5b 471 *pdw++ = 0x00808000; // 0011 mustard
2bda0e17
KB
472 *pdw++ = 0x00000080; // 0100 dark blue
473 *pdw++ = 0x00800080; // 0101 purple
474 *pdw++ = 0x00008080; // 0110 dark turquoise
475 *pdw++ = 0x00C0C0C0; // 1000 gray
476 *pdw++ = 0x00808080; // 0111 dark gray
477 *pdw++ = 0x00FF0000; // 1001 red
478 *pdw++ = 0x0000FF00; // 1010 green
3f4a0c5b 479 *pdw++ = 0x00FFFF00; // 1011 yellow
2bda0e17
KB
480 *pdw++ = 0x000000FF; // 1100 blue
481 *pdw++ = 0x00FF00FF; // 1101 pink (magenta)
482 *pdw++ = 0x0000FFFF; // 1110 cyan
483 *pdw++ = 0x00FFFFFF; // 1111 white
484 }
485
486 return (PDIB)lpbi;
487}
488
489static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
490{
491 DWORD dw;
492
493#ifdef __cplusplus
494 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
495#else
496 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
497#endif
498 *pb = xlat[*pb];
499}
500
501static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
502{
503 DWORD dw;
504
505#ifdef __cplusplus
506 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
507#else
508 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
509#endif
510 *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
511}
512
513#define RLE_ESCAPE 0
514#define RLE_EOL 0
515#define RLE_EOF 1
516#define RLE_JMP 2
517
518static void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
519{
520 BYTE cnt;
521 BYTE b;
522 BYTE _huge *prle = pb;
523
524 for(;;)
525 {
526 cnt = *prle++;
527 b = *prle;
528
529 if (cnt == RLE_ESCAPE)
530 {
531 prle++;
532
533 switch (b)
534 {
535 case RLE_EOF:
536 return;
537
538 case RLE_EOL:
539 break;
540
541 case RLE_JMP:
542 prle++; // skip dX
543 prle++; // skip dY
544 break;
545
546 default:
547 cnt = b;
548 for (b=0; b<cnt; b++,prle++)
549 *prle = xlat[*prle];
550
551 if (cnt & 1)
552 prle++;
553
554 break;
555 }
556 }
557 else
558 {
559 *prle++ = xlat[b];
560 }
561 }
562}
563
564static void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
565{
566}
567
568static void hmemmove(BYTE _huge *d, BYTE _huge *s, LONG len)
569{
570 d += len-1;
571 s += len-1;
572
573 while (len--)
574 *d-- = *s--;
575}
576
577/*
578 * DibMapToPalette(pdib, hpal)
579 *
580 * Map the colors of the DIB, using GetNearestPaletteIndex, to
581 * the colors of the given palette.
582 */
583
584BOOL DibMapToPalette(PDIB pdib, HPALETTE hpal)
585{
3f4a0c5b
VZ
586 LPBITMAPINFOHEADER lpbi;
587 PALETTEENTRY pe;
588 int n;
589 int nDibColors;
590 int nPalColors=0;
591 BYTE FAR * lpBits;
592 RGBQUAD FAR * lpRgb;
593 BYTE xlat[256];
594 DWORD SizeImage;
595
596 if (!hpal || !pdib)
597 return FALSE;
598
599 lpbi = (LPBITMAPINFOHEADER)pdib;
600 lpRgb = DibColors(pdib);
601
602 GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
603 nDibColors = DibNumColors(pdib);
604
605 if ((SizeImage = lpbi->biSizeImage) == 0)
606 SizeImage = DibSizeImage(lpbi);
607
608 //
609 // build a xlat table. from the current DIB colors to the given
610 // palette.
611 //
612 for (n=0; n<nDibColors; n++)
613 xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
614
615 lpBits = (LPBYTE)DibPtr(lpbi);
616 lpbi->biClrUsed = nPalColors;
617
618 //
619 // re-size the DIB
620 //
621 if (nPalColors > nDibColors)
622 {
623 GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
624 hmemmove((BYTE _huge *)DibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
625 lpBits = (LPBYTE)DibPtr(lpbi);
626 }
627 else if (nPalColors < nDibColors)
628 {
629 hmemcpy(DibPtr(lpbi), lpBits, SizeImage);
630 GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
631 lpBits = (LPBYTE)DibPtr(lpbi);
632 }
633
634 //
635 // translate the DIB bits
636 //
637 switch (lpbi->biCompression)
638 {
639 case BI_RLE8:
640 xlatRle8(lpBits, SizeImage, xlat);
641 break;
642
643 case BI_RLE4:
644 xlatRle4(lpBits, SizeImage, xlat);
645 break;
2bda0e17
KB
646
647 case BI_RGB:
3f4a0c5b 648 if (lpbi->biBitCount == 8)
2bda0e17
KB
649 xlatClut8(lpBits, SizeImage, xlat);
650 else
651 xlatClut4(lpBits, SizeImage, xlat);
652 break;
653 }
654
655 //
656 // Now copy the RGBs in the logical palette to the dib color table
657 //
658 for (n=0; n<nPalColors; n++)
659 {
660 GetPaletteEntries(hpal,n,1,&pe);
661
662 lpRgb[n].rgbRed = pe.peRed;
3f4a0c5b
VZ
663 lpRgb[n].rgbGreen = pe.peGreen;
664 lpRgb[n].rgbBlue = pe.peBlue;
665 lpRgb[n].rgbReserved = (BYTE)0;
666 }
2bda0e17 667
3f4a0c5b 668 return TRUE;
2bda0e17
KB
669}
670
671
672HPALETTE MakePalette(const BITMAPINFO FAR* Info, UINT flags)
673{
674 HPALETTE hPalette;
675 const RGBQUAD far* rgb = Info->bmiColors;
676
677 WORD nColors = Info->bmiHeader.biClrUsed;
678 if (nColors) {
3f4a0c5b
VZ
679 LOGPALETTE* logPal = (LOGPALETTE*)
680 new BYTE[sizeof(LOGPALETTE) + (nColors-1)*sizeof(PALETTEENTRY)];
681
682 logPal->palVersion = 0x300; // Windows 3.0 version
683 logPal->palNumEntries = nColors;
684 for (short n = 0; n < nColors; n++) {
685 logPal->palPalEntry[n].peRed = rgb[n].rgbRed;
686 logPal->palPalEntry[n].peGreen = rgb[n].rgbGreen;
687 logPal->palPalEntry[n].peBlue = rgb[n].rgbBlue;
688 logPal->palPalEntry[n].peFlags = (BYTE)flags;
689 }
690 hPalette = ::CreatePalette(logPal);
691 delete logPal;
2bda0e17 692 } else
3f4a0c5b 693 hPalette = 0;
2bda0e17
KB
694
695 return hPalette;
696}
697