]> Creatis software - clitk.git/blob - utilities/CxImage/ximawnd.cpp
9e75a3773793ea2729d72b661e27847be9fd3d42
[clitk.git] / utilities / CxImage / ximawnd.cpp
1 // xImaWnd.cpp : Windows functions\r
2 /* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
3  * CxImage version 6.0.0 02/Feb/2008\r
4  */\r
5 \r
6 #include "ximage.h"\r
7 \r
8 #include "ximaiter.h" \r
9 #include "ximabmp.h"\r
10 \r
11 ////////////////////////////////////////////////////////////////////////////////\r
12 #if defined (_WIN32_WCE)\r
13 \r
14 #ifndef DEFAULT_GUI_FONT\r
15 #define DEFAULT_GUI_FONT 17\r
16 #endif\r
17 \r
18 #ifndef PROOF_QUALITY\r
19 #define PROOF_QUALITY 2\r
20 #endif\r
21 \r
22 struct DIBINFO : public BITMAPINFO\r
23 {\r
24         RGBQUAD    arColors[255];    // Color table info - adds an extra 255 entries to palette\r
25         operator LPBITMAPINFO()          { return (LPBITMAPINFO) this; }\r
26         operator LPBITMAPINFOHEADER()    { return &bmiHeader;          }\r
27         RGBQUAD* ColorTable()            { return bmiColors;           }\r
28 };\r
29 \r
30 int BytesPerLine(int nWidth, int nBitsPerPixel)\r
31 {\r
32     return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;\r
33 }\r
34 \r
35 int NumColorEntries(int nBitsPerPixel, int nCompression, DWORD biClrUsed)\r
36 {\r
37         int nColors = 0;\r
38         switch (nBitsPerPixel)\r
39         {\r
40         case 1:\r
41                 nColors = 2;  break;\r
42         case 2:\r
43                 nColors = 4;  break;   // winCE only\r
44         case 4:\r
45                 nColors = 16; break;\r
46         case 8:\r
47                 nColors =256; break;\r
48         case 24:\r
49                 nColors = 0;  break;\r
50         case 16:\r
51         case 32:\r
52                 nColors = 3;  break; // I've found that PocketPCs need this regardless of BI_RGB or BI_BITFIELDS\r
53         default:\r
54                 ASSERT(FALSE);\r
55         }\r
56         // If biClrUsed is provided, and it is a legal value, use it\r
57         if (biClrUsed > 0 && biClrUsed <= (DWORD)nColors)\r
58                 return biClrUsed;\r
59         \r
60         return nColors;\r
61 }\r
62 \r
63 int GetDIBits(\r
64   HDC hdc,           // handle to DC\r
65   HBITMAP hbmp,      // handle to bitmap\r
66   UINT uStartScan,   // first scan line to set\r
67   UINT cScanLines,   // number of scan lines to copy\r
68   LPVOID lpvBits,    // array for bitmap bits\r
69   LPBITMAPINFO lpbi, // bitmap data buffer\r
70   UINT uUsage        // RGB or palette index\r
71 )\r
72 {\r
73         UINT    iColorTableSize = 0;\r
74 \r
75         if (!hbmp)\r
76                 return 0;\r
77 \r
78         // Get dimensions of bitmap\r
79         BITMAP bm;\r
80         if (!::GetObject(hbmp, sizeof(bm),(LPVOID)&bm))\r
81                 return 0;\r
82 \r
83         //3. Creating new bitmap and receive pointer to it's bits.\r
84         HBITMAP hTargetBitmap;\r
85         void *pBuffer;\r
86         \r
87         //3.1 Initilize DIBINFO structure\r
88         DIBINFO  dibInfo;\r
89         dibInfo.bmiHeader.biBitCount = 24;\r
90         dibInfo.bmiHeader.biClrImportant = 0;\r
91         dibInfo.bmiHeader.biClrUsed = 0;\r
92         dibInfo.bmiHeader.biCompression = 0;\r
93         dibInfo.bmiHeader.biHeight = bm.bmHeight;\r
94         dibInfo.bmiHeader.biPlanes = 1;\r
95         dibInfo.bmiHeader.biSize = 40;\r
96         dibInfo.bmiHeader.biSizeImage = bm.bmHeight*BytesPerLine(bm.bmWidth,24);\r
97         dibInfo.bmiHeader.biWidth = bm.bmWidth;\r
98         dibInfo.bmiHeader.biXPelsPerMeter = 3780;\r
99         dibInfo.bmiHeader.biYPelsPerMeter = 3780;\r
100         dibInfo.bmiColors[0].rgbBlue = 0;\r
101         dibInfo.bmiColors[0].rgbGreen = 0;\r
102         dibInfo.bmiColors[0].rgbRed = 0;\r
103         dibInfo.bmiColors[0].rgbReserved = 0;\r
104 \r
105         //3.2 Create bitmap and receive pointer to points into pBuffer\r
106         HDC hDC = ::GetDC(NULL);\r
107         ASSERT(hDC);\r
108         hTargetBitmap = CreateDIBSection(\r
109                 hDC,\r
110                 (const BITMAPINFO*)dibInfo,\r
111                 DIB_RGB_COLORS,\r
112                 (void**)&pBuffer,\r
113                 NULL,\r
114                 0);\r
115 \r
116         ::ReleaseDC(NULL, hDC);\r
117 \r
118         //4. Copy source bitmap into the target bitmap.\r
119 \r
120         //4.1 Create 2 device contexts\r
121         HDC memDc = CreateCompatibleDC(NULL);\r
122         if (!memDc) {\r
123                 ASSERT(FALSE);\r
124         }\r
125         \r
126         HDC targetDc = CreateCompatibleDC(NULL);\r
127         if (!targetDc) {\r
128                 ASSERT(FALSE);\r
129         }\r
130 \r
131         //4.2 Select source bitmap into one DC, target into another\r
132         HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hbmp);\r
133         HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);\r
134 \r
135         //4.3 Copy source bitmap into the target one\r
136         BitBlt(targetDc, 0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);\r
137 \r
138         //4.4 Restore device contexts\r
139         ::SelectObject(memDc, hOldBitmap1);\r
140         ::SelectObject(targetDc, hOldBitmap2);\r
141         DeleteDC(memDc);\r
142         DeleteDC(targetDc);\r
143 \r
144         //Here we can bitmap bits: pBuffer. Note:\r
145         // 1. pBuffer contains 3 bytes per point\r
146         // 2. Lines ane from the bottom to the top!\r
147         // 3. Points in the line are from the left to the right\r
148         // 4. Bytes in one point are BGR (blue, green, red) not RGB\r
149         // 5. Don't delete pBuffer, it will be automatically deleted\r
150         //    when delete hTargetBitmap\r
151         lpvBits = pBuffer;\r
152 \r
153         DeleteObject(hbmp);\r
154         //DeleteObject(hTargetBitmap);\r
155 \r
156         return 1;\r
157 }\r
158 #endif \r
159 \r
160 ////////////////////////////////////////////////////////////////////////////////\r
161 #if CXIMAGE_SUPPORT_WINDOWS\r
162 ////////////////////////////////////////////////////////////////////////////////\r
163 long CxImage::Blt(HDC pDC, long x, long y)\r
164 {\r
165         if((pDib==0)||(pDC==0)||(!info.bEnabled)) return 0;\r
166 \r
167     HBRUSH brImage = CreateDIBPatternBrushPt(pDib, DIB_RGB_COLORS);\r
168     POINT pt;\r
169     SetBrushOrgEx(pDC,x,y,&pt); //<RT>\r
170     HBRUSH brOld = (HBRUSH) SelectObject(pDC, brImage);\r
171     PatBlt(pDC, x, y, head.biWidth, head.biHeight, PATCOPY);\r
172     SelectObject(pDC, brOld);\r
173     SetBrushOrgEx(pDC,pt.x,pt.y,NULL);\r
174     DeleteObject(brImage);\r
175     return 1;\r
176 }\r
177 ////////////////////////////////////////////////////////////////////////////////\r
178 /**\r
179  * Transfer the image in a global bitmap handle (clipboard copy)\r
180  */\r
181 HANDLE CxImage::CopyToHandle()\r
182 {\r
183         HANDLE hMem=NULL;\r
184         if (pDib){\r
185                 hMem= GlobalAlloc(GHND, GetSize());\r
186                 if (hMem){\r
187                         BYTE* pDst=(BYTE*)GlobalLock(hMem);\r
188                         if (pDst){\r
189                                 memcpy(pDst,pDib,GetSize());\r
190                         }\r
191                         GlobalUnlock(hMem);\r
192                 }\r
193         }\r
194         return hMem;\r
195 }\r
196 ////////////////////////////////////////////////////////////////////////////////\r
197 /**\r
198  * Global object (clipboard paste) constructor\r
199  * \param hMem: source bitmap object, the clipboard format must be CF_DIB\r
200  * \return true if everything is ok\r
201  */\r
202 bool CxImage::CreateFromHANDLE(HANDLE hMem)\r
203 {\r
204         if (!Destroy())\r
205                 return false;\r
206 \r
207         DWORD dwSize = GlobalSize(hMem);\r
208         if (!dwSize) return false;\r
209 \r
210         BYTE *lpVoid;                                           //pointer to the bitmap\r
211         lpVoid = (BYTE *)GlobalLock(hMem);\r
212         BITMAPINFOHEADER *pHead;                        //pointer to the bitmap header\r
213         pHead = (BITMAPINFOHEADER *)lpVoid;\r
214         if (lpVoid){\r
215 \r
216                 //CxMemFile hFile(lpVoid,dwSize);\r
217 \r
218                 //copy the bitmap header\r
219                 memcpy(&head,pHead,sizeof(BITMAPINFOHEADER));\r
220                 //check if it's a top-down bitmap\r
221                 bool bTopDownDib = head.biHeight<0;\r
222                 if (bTopDownDib) head.biHeight=-head.biHeight;\r
223                 //create the image\r
224                 if(!Create(head.biWidth,head.biHeight,head.biBitCount)){\r
225                         GlobalUnlock(lpVoid);\r
226                         return false;\r
227                 }\r
228                 //preserve DPI\r
229                 SetXDPI((long)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
230                 SetYDPI((long)floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
231 \r
232                 /*//copy the pixels (old way)\r
233                 if((pHead->biCompression != BI_RGB) || (pHead->biBitCount == 32)){ //<Jรถrgen Alfredsson>\r
234                         // BITFIELD case\r
235                         // set the internal header in the dib\r
236                         memcpy(pDib,&head,sizeof(head));\r
237                         // get the bitfield masks\r
238                         DWORD bf[3];\r
239                         memcpy(bf,lpVoid+pHead->biSize,12);\r
240                         // transform into RGB\r
241                         Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);\r
242                 } else { //normal bitmap\r
243                         memcpy(pDib,lpVoid,GetSize());\r
244                 }*/\r
245 \r
246                 // <Michael Gandyra>\r
247                 // fill in color map\r
248                 bool bIsOldBmp = (head.biSize == sizeof(BITMAPCOREHEADER));\r
249                 RGBQUAD *pRgb = GetPalette();\r
250                 if (pRgb) {\r
251                         // number of colors to fill in\r
252                         int nColors = DibNumColors(pHead);\r
253                         if (bIsOldBmp) {\r
254                                 /* get pointer to BITMAPCOREINFO (old style 1.x) */\r
255                                 LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;\r
256                                 for (int i = nColors - 1; i >= 0; i--) {\r
257                                         pRgb[i].rgbRed      = lpbmc->bmciColors[i].rgbtRed;\r
258                                         pRgb[i].rgbGreen    = lpbmc->bmciColors[i].rgbtGreen;\r
259                                         pRgb[i].rgbBlue     = lpbmc->bmciColors[i].rgbtBlue;\r
260                                         pRgb[i].rgbReserved = (BYTE)0;\r
261                                 }\r
262                         } else {\r
263                                 /* get pointer to BITMAPINFO (new style 3.x) */\r
264                                 LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;\r
265                                 for (int i = nColors - 1; i >= 0; i--) {\r
266                                         pRgb[i].rgbRed      = lpbmi->bmiColors[i].rgbRed;\r
267                                         pRgb[i].rgbGreen    = lpbmi->bmiColors[i].rgbGreen;\r
268                                         pRgb[i].rgbBlue     = lpbmi->bmiColors[i].rgbBlue;\r
269                                         pRgb[i].rgbReserved = (BYTE)0;\r
270                                 }\r
271                         }\r
272                 }\r
273 \r
274                 // <Michael Gandyra>\r
275                 DWORD dwCompression = pHead->biCompression;\r
276                 // compressed bitmap ?\r
277                 if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {\r
278                         // get the bitmap bits\r
279                         LPSTR lpDIBBits = (LPSTR)((BYTE*)pHead + *(DWORD*)pHead + (WORD)(GetNumColors() * sizeof(RGBQUAD)));\r
280                         // decode and copy them to our image\r
281                         switch (pHead->biBitCount) {\r
282                         case 32 :\r
283                                 {\r
284                                         // BITFIELD case\r
285                                         if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB) {\r
286                                                 // get the bitfield masks\r
287                                                 DWORD bf[3];\r
288                                                 memcpy(bf,lpVoid+pHead->biSize,12);\r
289                                                 // transform into RGB\r
290                                                 Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);\r
291                                         } else {\r
292                                                 // "unknown compression";\r
293                                                 GlobalUnlock(lpVoid);\r
294                                                 return false;\r
295                                         }\r
296                                 }\r
297                                 break;\r
298                         case 16 :\r
299                                 {\r
300                                         // get the bitfield masks\r
301                                         long offset=0;\r
302                                         DWORD bf[3];\r
303                                         if (dwCompression == BI_BITFIELDS) {\r
304                                                 memcpy(bf,lpVoid+pHead->biSize,12);\r
305                                                 offset= 12;\r
306                                         } else {\r
307                                                 bf[0] = 0x7C00;\r
308                                                 bf[1] = 0x3E0;\r
309                                                 bf[2] = 0x1F; // RGB555\r
310                                         }\r
311                                         // copy the pixels\r
312                                         memcpy(info.pImage, lpDIBBits + offset, head.biHeight*((head.biWidth+1)/2)*4);\r
313                                         // transform into RGB\r
314                                         Bitfield2RGB(info.pImage, bf[0], bf[1], bf[2], 16);\r
315                                 }\r
316                                 break;\r
317                         case 8 :\r
318                         case 4 :\r
319                         case 1 :\r
320                                 {\r
321                                         switch (dwCompression) {\r
322                                         case BI_RLE4:\r
323                                                 {\r
324                                                         BYTE status_byte = 0;\r
325                                                         BYTE second_byte = 0;\r
326                                                         int scanline = 0;\r
327                                                         int bits = 0;\r
328                                                         BOOL low_nibble = FALSE;\r
329                                                         CImageIterator iter(this);\r
330 \r
331                                                         for (BOOL bContinue = TRUE; bContinue; ) {\r
332                                                                 status_byte = *(lpDIBBits++);\r
333                                                                 switch (status_byte) {\r
334                                                                 case RLE_COMMAND :\r
335                                                                         status_byte = *(lpDIBBits++);\r
336                                                                         switch (status_byte) {\r
337                                                                         case RLE_ENDOFLINE :\r
338                                                                                 bits = 0;\r
339                                                                                 scanline++;\r
340                                                                                 low_nibble = FALSE;\r
341                                                                                 break;\r
342                                                                         case RLE_ENDOFBITMAP :\r
343                                                                                 bContinue = FALSE;\r
344                                                                                 break;\r
345                                                                         case RLE_DELTA :\r
346                                                                                 {\r
347                                                                                         // read the delta values\r
348                                                                                         BYTE delta_x;\r
349                                                                                         BYTE delta_y;\r
350                                                                                         delta_x = *(lpDIBBits++);\r
351                                                                                         delta_y = *(lpDIBBits++);\r
352                                                                                         // apply them\r
353                                                                                         bits       += delta_x / 2;\r
354                                                                                         scanline   += delta_y;\r
355                                                                                         break;\r
356                                                                                 }\r
357                                                                         default :\r
358                                                                                 second_byte = *(lpDIBBits++);\r
359                                                                                 BYTE* sline = iter.GetRow(scanline);\r
360                                                                                 for (int i = 0; i < status_byte; i++) {\r
361                                                                                         if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
362                                                                                                 if (low_nibble) {\r
363                                                                                                         if (i&1)\r
364                                                                                                                 *(sline + bits) |= (second_byte & 0x0f);\r
365                                                                                                         else\r
366                                                                                                                 *(sline + bits) |= (second_byte & 0xf0)>>4;\r
367                                                                                                         bits++;\r
368                                                                                                 } else {\r
369                                                                                                         if (i&1)\r
370                                                                                                                 *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
371                                                                                                         else\r
372                                                                                                                 *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
373                                                                                                 }\r
374                                                                                         }\r
375 \r
376                                                                                         if ((i & 1) && (i != (status_byte - 1)))\r
377                                                                                                 second_byte = *(lpDIBBits++);\r
378 \r
379                                                                                         low_nibble = !low_nibble;\r
380                                                                                 }\r
381                                                                                 if ((((status_byte+1) >> 1) & 1 ) == 1)\r
382                                                                                         second_byte = *(lpDIBBits++);                                                                                           \r
383                                                                                 break;\r
384                                                                         };\r
385                                                                         break;\r
386                                                                         default :\r
387                                                                         {\r
388                                                                                 BYTE* sline = iter.GetRow(scanline);\r
389                                                                                 second_byte = *(lpDIBBits++);\r
390                                                                                 for (unsigned i = 0; i < status_byte; i++) {\r
391                                                                                         if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
392                                                                                                 if (low_nibble) {\r
393                                                                                                         if (i&1)\r
394                                                                                                                 *(sline + bits) |= (second_byte & 0x0f);\r
395                                                                                                         else\r
396                                                                                                                 *(sline + bits) |= (second_byte & 0xf0)>>4;\r
397                                                                                                         bits++;\r
398                                                                                                 } else {\r
399                                                                                                         if (i&1)\r
400                                                                                                                 *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
401                                                                                                         else\r
402                                                                                                                 *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
403                                                                                                 }\r
404                                                                                         }\r
405                                                                                         low_nibble = !low_nibble;\r
406                                                                                 }\r
407                                                                         }\r
408                                                                         break;\r
409                                                                 };\r
410                                                         }\r
411                                                 }\r
412                                                 break;\r
413                                         case BI_RLE8 :\r
414                                                 {\r
415                                                         BYTE status_byte = 0;\r
416                                                         BYTE second_byte = 0;\r
417                                                         int scanline = 0;\r
418                                                         int bits = 0;\r
419                                                         CImageIterator iter(this);\r
420 \r
421                                                         for (BOOL bContinue = TRUE; bContinue; ) {\r
422                                                                 status_byte = *(lpDIBBits++);\r
423                                                                 if (status_byte==RLE_COMMAND) {\r
424                                                                         status_byte = *(lpDIBBits++);\r
425                                                                         switch (status_byte) {\r
426                                                                         case RLE_ENDOFLINE :\r
427                                                                                 bits = 0;\r
428                                                                                 scanline++;\r
429                                                                                 break;\r
430                                                                         case RLE_ENDOFBITMAP :\r
431                                                                                 bContinue = FALSE;\r
432                                                                                 break;\r
433                                                                         case RLE_DELTA :\r
434                                                                                 {\r
435                                                                                         // read the delta values\r
436                                                                                         BYTE delta_x;\r
437                                                                                         BYTE delta_y;\r
438                                                                                         delta_x = *(lpDIBBits++);\r
439                                                                                         delta_y = *(lpDIBBits++);\r
440                                                                                         // apply them\r
441                                                                                         bits     += delta_x;\r
442                                                                                         scanline += delta_y;\r
443                                                                                 }\r
444                                                                                 break;\r
445                                                                         default :\r
446                                                                                 int nNumBytes = sizeof(BYTE) * status_byte;\r
447                                                                                 memcpy((void *)(iter.GetRow(scanline) + bits), lpDIBBits, nNumBytes);\r
448                                                                                 lpDIBBits += nNumBytes;\r
449                                                                                 // align run length to even number of bytes \r
450                                                                                 if ((status_byte & 1) == 1)\r
451                                                                                         second_byte = *(lpDIBBits++);\r
452                                                                                 bits += status_byte;\r
453                                                                                 break;\r
454                                                                         };\r
455                                                                 } else {\r
456                                                                         BYTE *sline = iter.GetRow(scanline);\r
457                                                                         second_byte = *(lpDIBBits++);\r
458                                                                         for (unsigned i = 0; i < status_byte; i++) {\r
459                                                                                 if ((DWORD)bits<info.dwEffWidth){\r
460                                                                                         *(sline + bits) = second_byte;\r
461                                                                                         bits++;\r
462                                                                                 } else {\r
463                                                                                         bContinue = FALSE; //don't delete: we are in memory, it is not as with files\r
464                                                                                         break;\r
465                                                                                 }\r
466                                                                         }\r
467                                                                 }\r
468                                                         }\r
469                                                 }\r
470                                                 break;\r
471                                         default :\r
472                                                 {\r
473                                                         // "compression type not supported";\r
474                                                         GlobalUnlock(lpVoid);\r
475                                                         return false;\r
476                                                 }\r
477                                         }\r
478                                 }\r
479                         }\r
480                 } else {\r
481                         //normal bitmap (not compressed)\r
482                         memcpy(pDib,lpVoid,GetSize());\r
483                 }\r
484 \r
485                 GlobalUnlock(lpVoid);\r
486 \r
487                 if (bTopDownDib) Flip();\r
488 \r
489                 return true;\r
490         }\r
491         return false;\r
492 }\r
493 ////////////////////////////////////////////////////////////////////////////////\r
494 /**\r
495  * Transfer the image in a  bitmap handle\r
496  * \param hdc: target device context (the screen, usually)\r
497  * \return bitmap handle, or NULL if an error occurs.\r
498  */\r
499 HBITMAP CxImage::MakeBitmap(HDC hdc)\r
500 {\r
501         if (!pDib)\r
502                 return NULL;\r
503 \r
504         if (!hdc){\r
505                 // this call to CreateBitmap doesn't create a DIB <jaslet>\r
506                 // // Create a device-independent bitmap <CSC>\r
507                 //  return CreateBitmap(head.biWidth,head.biHeight,     1, head.biBitCount, GetBits());\r
508                 // use instead this code\r
509                 HDC hMemDC = CreateCompatibleDC(NULL);\r
510                 LPVOID pBit32;\r
511                 HBITMAP bmp = CreateDIBSection(hMemDC,(LPBITMAPINFO)pDib,DIB_RGB_COLORS, &pBit32, NULL, 0);\r
512                 if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);\r
513                 DeleteDC(hMemDC);\r
514                 return bmp;\r
515         }\r
516 \r
517         // this single line seems to work very well\r
518         //HBITMAP bmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)pDib, CBM_INIT,\r
519         //      GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);\r
520         // this alternative works also with _WIN32_WCE\r
521         LPVOID pBit32;\r
522         HBITMAP bmp = CreateDIBSection(hdc, (LPBITMAPINFO)pDib, DIB_RGB_COLORS, &pBit32, NULL, 0);\r
523         if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);\r
524 \r
525         return bmp;\r
526 }\r
527 ////////////////////////////////////////////////////////////////////////////////\r
528 /**\r
529  * Bitmap resource constructor\r
530  * \param hbmp : bitmap resource handle\r
531  * \param hpal : (optional) palette, useful for 8bpp DC \r
532  * \return true if everything is ok\r
533  */\r
534 bool CxImage::CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal)\r
535 {\r
536         if (!Destroy())\r
537                 return false;\r
538 \r
539         if (hbmp) { \r
540         BITMAP bm;\r
541                 // get informations about the bitmap\r
542         GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);\r
543                 // create the image\r
544         if (!Create(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0))\r
545                         return false;\r
546                 // create a device context for the bitmap\r
547         HDC dc = ::GetDC(NULL);\r
548                 if (!dc)\r
549                         return false;\r
550 \r
551                 if (hpal){\r
552                         SelectObject(dc,hpal); //the palette you should get from the user or have a stock one\r
553                         RealizePalette(dc);\r
554                 }\r
555 \r
556                 // copy the pixels\r
557         if (GetDIBits(dc, hbmp, 0, head.biHeight, info.pImage,\r
558                         (LPBITMAPINFO)pDib, DIB_RGB_COLORS) == 0){ //replace &head with pDib <Wil Stark>\r
559             strcpy(info.szLastError,"GetDIBits failed");\r
560                         ::ReleaseDC(NULL, dc);\r
561                         return false;\r
562         }\r
563         ::ReleaseDC(NULL, dc);\r
564                 return true;\r
565     }\r
566         return false;\r
567 }\r
568 ////////////////////////////////////////////////////////////////////////////////\r
569 /**\r
570  * icon resource constructor\r
571  * \param hico : icon resource handle\r
572  * \return true if everything is ok\r
573  * \author []; changes [Arlen Albert Keshabian]\r
574  */\r
575 #if !defined (_WIN32_WCE)\r
576 bool CxImage::CreateFromHICON(HICON hico)\r
577 {\r
578         if (!Destroy() || !hico)\r
579                 return false;\r
580 \r
581         bool l_bResult = true;\r
582 \r
583         ICONINFO iinfo;\r
584         GetIconInfo(hico,&iinfo);\r
585 \r
586         BITMAP l_Bitmap;\r
587         GetObject(iinfo.hbmColor, sizeof(BITMAP), &l_Bitmap);\r
588 \r
589         if(l_Bitmap.bmBitsPixel == 32)\r
590         {\r
591                 BITMAPINFO l_BitmapInfo;\r
592                 l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
593                 l_BitmapInfo.bmiHeader.biWidth = l_Bitmap.bmWidth;\r
594                 l_BitmapInfo.bmiHeader.biHeight = l_Bitmap.bmHeight;\r
595                 l_BitmapInfo.bmiHeader.biPlanes = l_Bitmap.bmPlanes;\r
596                 l_BitmapInfo.bmiHeader.biBitCount = l_Bitmap.bmBitsPixel;\r
597                 l_BitmapInfo.bmiHeader.biCompression = BI_RGB;\r
598 \r
599                 RGBQUAD *l_pRawBytes = new RGBQUAD[l_Bitmap.bmWidth * l_Bitmap.bmHeight];\r
600 \r
601                 HDC dc = ::GetDC(NULL);\r
602 \r
603                 if(dc)\r
604                 {\r
605                         if(GetDIBits(dc, iinfo.hbmColor, 0, l_Bitmap.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))\r
606                                 l_bResult = CreateFromArray((BYTE*)l_pRawBytes, l_Bitmap.bmWidth, l_Bitmap.bmHeight, l_Bitmap.bmBitsPixel, l_Bitmap.bmWidthBytes, false);\r
607                         else\r
608                                 l_bResult = false;\r
609 \r
610                         ::ReleaseDC(NULL, dc);\r
611                 }\r
612                 else\r
613                         l_bResult = false;\r
614 \r
615                 delete [] l_pRawBytes;\r
616         }\r
617         else\r
618         {\r
619                 l_bResult = CreateFromHBITMAP(iinfo.hbmColor);\r
620 #if CXIMAGE_SUPPORT_ALPHA\r
621                 if(l_bResult)\r
622                 {\r
623                         CxImage mask;\r
624                         mask.CreateFromHBITMAP(iinfo.hbmMask);\r
625                         mask.GrayScale();\r
626                         mask.Negative();\r
627                         AlphaSet(mask);\r
628                 }\r
629 #endif\r
630         }\r
631 \r
632         DeleteObject(iinfo.hbmColor); //<Sims>\r
633         DeleteObject(iinfo.hbmMask);  //<Sims>\r
634         \r
635         return l_bResult;\r
636 }\r
637 #endif //_WIN32_WCE\r
638 ////////////////////////////////////////////////////////////////////////////////\r
639 long CxImage::Draw(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)\r
640 {\r
641         return Draw(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);\r
642 }\r
643 ////////////////////////////////////////////////////////////////////////////////\r
644 /**\r
645  * Draws the image in the specified device context, with support for alpha channel, alpha palette, transparency, opacity.\r
646  * \param hdc : destination device context\r
647  * \param x,y : (optional) offset\r
648  * \param cx,cy : (optional) size.\r
649  *                 - If cx or cy are not specified (or less than 0), the normal width or height will be used\r
650  *                 - If cx or cy are different than width or height, the image will be stretched\r
651  *\r
652  * \param pClipRect : limit the drawing operations inside a given rectangle in the output device context.\r
653  * \param bSmooth : activates a bilinear filter that will enhance the appearence for zommed pictures.\r
654  *                   Quite slow. Needs CXIMAGE_SUPPORT_INTERPOLATION.\r
655  * \return true if everything is ok\r
656  */\r
657 long CxImage::Draw(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)\r
658 {\r
659         if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;\r
660 \r
661         if (cx < 0) cx = head.biWidth;\r
662         if (cy < 0) cy = head.biHeight;\r
663         bool bTransparent = info.nBkgndIndex >= 0;\r
664         bool bAlpha = pAlpha != 0;\r
665 \r
666         //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]\r
667         int hdc_Restore = ::SaveDC(hdc);\r
668         if (!hdc_Restore) \r
669                 return 0;\r
670 \r
671 #if !defined (_WIN32_WCE)\r
672         RECT mainbox; // (experimental) \r
673         if (pClipRect){\r
674                 GetClipBox(hdc,&mainbox);\r
675                 HRGN rgn = CreateRectRgnIndirect(pClipRect);\r
676                 ExtSelectClipRgn(hdc,rgn,RGN_AND);\r
677                 DeleteObject(rgn);\r
678         }\r
679 #endif\r
680 \r
681         //find the smallest area to paint\r
682         RECT clipbox,paintbox;\r
683         GetClipBox(hdc,&clipbox);\r
684 \r
685         paintbox.top = min(clipbox.bottom,max(clipbox.top,y));\r
686         paintbox.left = min(clipbox.right,max(clipbox.left,x));\r
687         paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));\r
688         paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));\r
689 \r
690         long destw = paintbox.right - paintbox.left;\r
691         long desth = paintbox.bottom - paintbox.top;\r
692 \r
693         if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){\r
694                 if (cx==head.biWidth && cy==head.biHeight){ //NORMAL\r
695 #if !defined (_WIN32_WCE)\r
696                         SetStretchBltMode(hdc,COLORONCOLOR);\r
697 #endif\r
698                         SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,\r
699                                                 info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);\r
700                 } else { //STRETCH\r
701                         //pixel informations\r
702                         RGBQUAD c={0,0,0,0};\r
703                         //Preparing Bitmap Info\r
704                         BITMAPINFO bmInfo;\r
705                         memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
706                         bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
707                         bmInfo.bmiHeader.biWidth=destw;\r
708                         bmInfo.bmiHeader.biHeight=desth;\r
709                         bmInfo.bmiHeader.biPlanes=1;\r
710                         bmInfo.bmiHeader.biBitCount=24;\r
711                         BYTE *pbase;    //points to the final dib\r
712                         BYTE *pdst;             //current pixel from pbase\r
713                         BYTE *ppix;             //current pixel from image\r
714                         //get the background\r
715                         HDC TmpDC=CreateCompatibleDC(hdc);\r
716                         HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
717                         HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
718 \r
719                         if (pbase){\r
720                                 long xx,yy;\r
721                                 long sx,sy;\r
722                                 float dx,dy;\r
723                                 BYTE *psrc;\r
724 \r
725                                 long ew = ((((24 * destw) + 31) / 32) * 4);\r
726                                 long ymax = paintbox.bottom;\r
727                                 long xmin = paintbox.left;\r
728                                 float fx=(float)head.biWidth/(float)cx;\r
729                                 float fy=(float)head.biHeight/(float)cy;\r
730 \r
731                                 for(yy=0;yy<desth;yy++){\r
732                                         dy = head.biHeight-(ymax-yy-y)*fy;\r
733                                         sy = max(0L,(long)floor(dy));\r
734                                         psrc = info.pImage+sy*info.dwEffWidth;\r
735                                         pdst = pbase+yy*ew;\r
736                                         for(xx=0;xx<destw;xx++){\r
737                                                 dx = (xx+xmin-x)*fx;\r
738                                                 sx = max(0L,(long)floor(dx));\r
739 #if CXIMAGE_SUPPORT_INTERPOLATION\r
740                                                 if (bSmooth){\r
741                                                         if (fx > 1 && fy > 1) { \r
742                                                                 c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
743                                                         } else { \r
744                                                                 c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
745                                                         } \r
746                                                 } else\r
747 #endif //CXIMAGE_SUPPORT_INTERPOLATION\r
748                                                 {\r
749                                                         if (head.biClrUsed){\r
750                                                                 c=GetPaletteColor(GetPixelIndex(sx,sy));\r
751                                                         } else {\r
752                                                                 ppix = psrc + sx*3;\r
753                                                                 c.rgbBlue = *ppix++;\r
754                                                                 c.rgbGreen= *ppix++;\r
755                                                                 c.rgbRed  = *ppix;\r
756                                                         }\r
757                                                 }\r
758                                                 *pdst++=c.rgbBlue;\r
759                                                 *pdst++=c.rgbGreen;\r
760                                                 *pdst++=c.rgbRed;\r
761                                         }\r
762                                 }\r
763                         }\r
764                         //paint the image & cleanup\r
765                         SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);\r
766                         DeleteObject(SelectObject(TmpDC,TmpObj));\r
767                         DeleteDC(TmpDC);\r
768                 }\r
769         } else {        // draw image with transparent/alpha blending\r
770         //////////////////////////////////////////////////////////////////\r
771                 //Alpha blend - Thanks to Florian Egel\r
772 \r
773                 //pixel informations\r
774                 RGBQUAD c={0,0,0,0};\r
775                 RGBQUAD ct = GetTransColor();\r
776                 long* pc = (long*)&c;\r
777                 long* pct= (long*)&ct;\r
778                 long cit = GetTransIndex();\r
779                 long ci = 0;\r
780 \r
781                 //Preparing Bitmap Info\r
782                 BITMAPINFO bmInfo;\r
783                 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
784                 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
785                 bmInfo.bmiHeader.biWidth=destw;\r
786                 bmInfo.bmiHeader.biHeight=desth;\r
787                 bmInfo.bmiHeader.biPlanes=1;\r
788                 bmInfo.bmiHeader.biBitCount=24;\r
789 \r
790                 BYTE *pbase;    //points to the final dib\r
791                 BYTE *pdst;             //current pixel from pbase\r
792                 BYTE *ppix;             //current pixel from image\r
793 \r
794                 //get the background\r
795                 HDC TmpDC=CreateCompatibleDC(hdc);\r
796                 HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
797                 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
798                 BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);\r
799 \r
800                 if (pbase){\r
801                         long xx,yy,alphaoffset,ix,iy;\r
802                         BYTE a,a1,*psrc;\r
803                         long ew = ((((24 * destw) + 31) / 32) * 4);\r
804                         long ymax = paintbox.bottom;\r
805                         long xmin = paintbox.left;\r
806 \r
807                         if (cx!=head.biWidth || cy!=head.biHeight){\r
808                                 //STRETCH\r
809                                 float fx=(float)head.biWidth/(float)cx;\r
810                                 float fy=(float)head.biHeight/(float)cy;\r
811                                 float dx,dy;\r
812                                 long sx,sy;\r
813                                 \r
814                                 for(yy=0;yy<desth;yy++){\r
815                                         dy = head.biHeight-(ymax-yy-y)*fy;\r
816                                         sy = max(0L,(long)floor(dy));\r
817 \r
818                                         alphaoffset = sy*head.biWidth;\r
819                                         pdst = pbase + yy*ew;\r
820                                         psrc = info.pImage + sy*info.dwEffWidth;\r
821 \r
822                                         for(xx=0;xx<destw;xx++){\r
823                                                 dx = (xx+xmin-x)*fx;\r
824                                                 sx = max(0L,(long)floor(dx));\r
825 \r
826                                                 if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;\r
827                                                 a =(BYTE)((a*(1+info.nAlphaMax))>>8);\r
828 \r
829                                                 if (head.biClrUsed){\r
830                                                         ci = GetPixelIndex(sx,sy);\r
831 #if CXIMAGE_SUPPORT_INTERPOLATION\r
832                                                         if (bSmooth){\r
833                                                                 if (fx > 1 && fy > 1) { \r
834                                                                         c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
835                                                                 } else { \r
836                                                                         c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
837                                                                 } \r
838                                                         } else\r
839 #endif //CXIMAGE_SUPPORT_INTERPOLATION\r
840                                                         {\r
841                                                                 c = GetPaletteColor(GetPixelIndex(sx,sy));\r
842                                                         }\r
843                                                         if (info.bAlphaPaletteEnabled){\r
844                                                                 a = (BYTE)((a*(1+c.rgbReserved))>>8);\r
845                                                         }\r
846                                                 } else {\r
847 #if CXIMAGE_SUPPORT_INTERPOLATION\r
848                                                         if (bSmooth){\r
849                                                                 if (fx > 1 && fy > 1) { \r
850                                                                         c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
851                                                                 } else { \r
852                                                                         c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
853                                                                 } \r
854                                                         } else\r
855 #endif //CXIMAGE_SUPPORT_INTERPOLATION\r
856                                                         {\r
857                                                                 ppix = psrc + sx*3;\r
858                                                                 c.rgbBlue = *ppix++;\r
859                                                                 c.rgbGreen= *ppix++;\r
860                                                                 c.rgbRed  = *ppix;\r
861                                                         }\r
862                                                 }\r
863                                                 //if (*pc!=*pct || !bTransparent){\r
864                                                 //if ((head.biClrUsed && ci!=cit) || ((!head.biClrUsed||bSmooth) && *pc!=*pct) || !bTransparent){\r
865                                                 if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){\r
866                                                         // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication\r
867                                                         if (a == 0) {                   // Transparent, retain dest \r
868                                                                 pdst+=3; \r
869                                                         } else if (a == 255) {  // opaque, ignore dest \r
870                                                                 *pdst++= c.rgbBlue; \r
871                                                                 *pdst++= c.rgbGreen; \r
872                                                                 *pdst++= c.rgbRed; \r
873                                                         } else {                                // semi transparent \r
874                                                                 a1=(BYTE)~a;\r
875                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); \r
876                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); \r
877                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); \r
878                                                         } \r
879                                                 } else {\r
880                                                         pdst+=3;\r
881                                                 }\r
882                                         }\r
883                                 }\r
884                         } else {\r
885                                 //NORMAL\r
886                                 iy=head.biHeight-ymax+y;\r
887                                 for(yy=0;yy<desth;yy++,iy++){\r
888                                         alphaoffset=iy*head.biWidth;\r
889                                         ix=xmin-x;\r
890                                         pdst=pbase+yy*ew;\r
891                                         ppix=info.pImage+iy*info.dwEffWidth+ix*3;\r
892                                         for(xx=0;xx<destw;xx++,ix++){\r
893 \r
894                                                 if (bAlpha) a=pAlpha[alphaoffset+ix]; else a=255;\r
895                                                 a = (BYTE)((a*(1+info.nAlphaMax))>>8);\r
896 \r
897                                                 if (head.biClrUsed){\r
898                                                         ci = GetPixelIndex(ix,iy);\r
899                                                         c = GetPaletteColor((BYTE)ci);\r
900                                                         if (info.bAlphaPaletteEnabled){\r
901                                                                 a = (BYTE)((a*(1+c.rgbReserved))>>8);\r
902                                                         }\r
903                                                 } else {\r
904                                                         c.rgbBlue = *ppix++;\r
905                                                         c.rgbGreen= *ppix++;\r
906                                                         c.rgbRed  = *ppix++;\r
907                                                 }\r
908 \r
909                                                 //if (*pc!=*pct || !bTransparent){\r
910                                                 if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){\r
911                                                         // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication\r
912                                                         if (a == 0) {                   // Transparent, retain dest \r
913                                                                 pdst+=3; \r
914                                                         } else if (a == 255) {  // opaque, ignore dest \r
915                                                                 *pdst++= c.rgbBlue; \r
916                                                                 *pdst++= c.rgbGreen; \r
917                                                                 *pdst++= c.rgbRed; \r
918                                                         } else {                                // semi transparent \r
919                                                                 a1=(BYTE)~a;\r
920                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); \r
921                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); \r
922                                                                 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); \r
923                                                         } \r
924                                                 } else {\r
925                                                         pdst+=3;\r
926                                                 }\r
927                                         }\r
928                                 }\r
929                         }\r
930                 }\r
931                 //paint the image & cleanup\r
932                 SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);\r
933                 DeleteObject(SelectObject(TmpDC,TmpObj));\r
934                 DeleteDC(TmpDC);\r
935         }\r
936 \r
937 #if !defined (_WIN32_WCE)\r
938         if (pClipRect){  // (experimental)\r
939                 HRGN rgn = CreateRectRgnIndirect(&mainbox);\r
940                 ExtSelectClipRgn(hdc,rgn,RGN_OR);\r
941                 DeleteObject(rgn);\r
942         }\r
943 #endif\r
944 \r
945         ::RestoreDC(hdc,hdc_Restore);\r
946         return 1;\r
947 }\r
948 ////////////////////////////////////////////////////////////////////////////////\r
949 long CxImage::Draw2(HDC hdc, const RECT& rect)\r
950 {\r
951         return Draw2(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);\r
952 }\r
953 ////////////////////////////////////////////////////////////////////////////////\r
954 /**\r
955  * Draws (stretch) the image with single transparency support\r
956  * \param hdc : destination device context\r
957  * \param x,y : (optional) offset\r
958  * \param cx,cy : (optional) size.\r
959  *                 - If cx or cy are not specified (or less than 0), the normal width or height will be used\r
960  *                 - If cx or cy are different than width or height, the image will be stretched\r
961  *\r
962  * \return true if everything is ok\r
963  */\r
964 long CxImage::Draw2(HDC hdc, long x, long y, long cx, long cy)\r
965 {\r
966         if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;\r
967         if (cx < 0) cx = head.biWidth;\r
968         if (cy < 0) cy = head.biHeight;\r
969         bool bTransparent = (info.nBkgndIndex >= 0);\r
970 \r
971         //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]\r
972         int hdc_Restore = ::SaveDC(hdc);\r
973         if (!hdc_Restore) \r
974                 return 0;\r
975 \r
976         if (!bTransparent){\r
977 #if !defined (_WIN32_WCE)\r
978                 SetStretchBltMode(hdc,COLORONCOLOR);    \r
979 #endif\r
980                 StretchDIBits(hdc, x, y, cx, cy, 0, 0, head.biWidth, head.biHeight,\r
981                                                 info.pImage,(BITMAPINFO*)pDib, DIB_RGB_COLORS,SRCCOPY);\r
982         } else {\r
983                 // draw image with transparent background\r
984                 const int safe = 0; // or else GDI fails in the following - sometimes \r
985                 RECT rcDst = {x+safe, y+safe, x+cx, y+cy};\r
986                 if (RectVisible(hdc, &rcDst)){\r
987                 /////////////////////////////////////////////////////////////////\r
988                         // True Mask Method - Thanks to Paul Reynolds and Ron Gery\r
989                         int nWidth = head.biWidth;\r
990                         int nHeight = head.biHeight;\r
991                         // Create two memory dcs for the image and the mask\r
992                         HDC dcImage=CreateCompatibleDC(hdc);\r
993                         HDC dcTrans=CreateCompatibleDC(hdc);\r
994                         // Select the image into the appropriate dc\r
995                         HBITMAP bm = CreateCompatibleBitmap(hdc, nWidth, nHeight);\r
996                         HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(dcImage,bm);\r
997 #if !defined (_WIN32_WCE)\r
998                         SetStretchBltMode(dcImage,COLORONCOLOR);\r
999 #endif\r
1000                         StretchDIBits(dcImage, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,\r
1001                                                         info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,SRCCOPY);\r
1002 \r
1003                         // Create the mask bitmap\r
1004                         HBITMAP bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);\r
1005                         // Select the mask bitmap into the appropriate dc\r
1006                         HBITMAP pOldBitmapTrans = (HBITMAP)SelectObject(dcTrans, bitmapTrans);\r
1007                         // Build mask based on transparent colour\r
1008                         RGBQUAD rgbBG;\r
1009                         if (head.biBitCount<24) rgbBG = GetPaletteColor((BYTE)info.nBkgndIndex);\r
1010                         else rgbBG = info.nBkgndColor;\r
1011                         COLORREF crColour = RGB(rgbBG.rgbRed, rgbBG.rgbGreen, rgbBG.rgbBlue);\r
1012                         COLORREF crOldBack = SetBkColor(dcImage,crColour);\r
1013                         BitBlt(dcTrans,0, 0, nWidth, nHeight, dcImage, 0, 0, SRCCOPY);\r
1014 \r
1015                         // Do the work - True Mask method - cool if not actual display\r
1016                         StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);\r
1017                         StretchBlt(hdc,x, y,cx,cy, dcTrans, 0, 0, nWidth, nHeight, SRCAND);\r
1018                         StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);\r
1019 \r
1020                         // Restore settings\r
1021                         SelectObject(dcImage,pOldBitmapImage);\r
1022                         SelectObject(dcTrans,pOldBitmapTrans);\r
1023                         SetBkColor(hdc,crOldBack);\r
1024                         DeleteObject( bitmapTrans );  // RG 29/01/2002\r
1025                         DeleteDC(dcImage);\r
1026                         DeleteDC(dcTrans);\r
1027                         DeleteObject(bm);\r
1028                 }\r
1029         }\r
1030         ::RestoreDC(hdc,hdc_Restore);\r
1031         return 1;\r
1032 }\r
1033 ////////////////////////////////////////////////////////////////////////////////\r
1034 long CxImage::Stretch(HDC hdc, const RECT& rect, DWORD dwRop)\r
1035 {\r
1036         return Stretch(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, dwRop);\r
1037 }\r
1038 ////////////////////////////////////////////////////////////////////////////////\r
1039 /**\r
1040  * Stretch the image. Obsolete: use Draw() or Draw2()\r
1041  * \param hdc : destination device context\r
1042  * \param xoffset,yoffset : (optional) offset\r
1043  * \param xsize,ysize : size.\r
1044  * \param dwRop : raster operation code (see BitBlt documentation)\r
1045  * \return true if everything is ok\r
1046  */\r
1047 long CxImage::Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop)\r
1048 {\r
1049         if((pDib)&&(hdc)) {\r
1050                 //palette must be correctly filled\r
1051 #if !defined (_WIN32_WCE)\r
1052                 SetStretchBltMode(hdc,COLORONCOLOR);    \r
1053 #endif\r
1054                 StretchDIBits(hdc, xoffset, yoffset,\r
1055                                         xsize, ysize, 0, 0, head.biWidth, head.biHeight,\r
1056                                         info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,dwRop);\r
1057                 return 1;\r
1058         }\r
1059         return 0;\r
1060 }\r
1061 ////////////////////////////////////////////////////////////////////////////////\r
1062 /**\r
1063  * Tiles the device context in the specified rectangle with the image.\r
1064  * \param hdc : destination device context\r
1065  * \param rc : tiled rectangle in the output device context\r
1066  * \return true if everything is ok\r
1067  */\r
1068 long CxImage::Tile(HDC hdc, RECT *rc)\r
1069 {\r
1070         if((pDib)&&(hdc)&&(rc)) {\r
1071                 int w = rc->right - rc->left;\r
1072                 int h = rc->bottom - rc->top;\r
1073                 int x,y,z;\r
1074                 int bx=head.biWidth;\r
1075                 int by=head.biHeight;\r
1076                 for (y = 0 ; y < h ; y += by){\r
1077                         if ((y+by)>h) by=h-y;\r
1078                         z=bx;\r
1079                         for (x = 0 ; x < w ; x += z){\r
1080                                 if ((x+z)>w) z=w-x;\r
1081                                 RECT r = {rc->left + x,rc->top + y,rc->left + x + z,rc->top + y + by};\r
1082                                 Draw(hdc,rc->left + x, rc->top + y,-1,-1,&r);\r
1083                         }\r
1084                 }\r
1085                 return 1;\r
1086         }\r
1087         return 0;\r
1088 }\r
1089 ////////////////////////////////////////////////////////////////////////////////\r
1090 // For UNICODE support: char -> TCHAR\r
1091 long CxImage::DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)\r
1092 //long CxImage::DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)\r
1093 {\r
1094         if (IsValid()){\r
1095                 //get the background\r
1096                 HDC pDC;\r
1097                 if (hdc) pDC=hdc; else pDC = ::GetDC(0);\r
1098                 if (pDC==NULL) return 0;\r
1099                 HDC TmpDC=CreateCompatibleDC(pDC);\r
1100                 if (hdc==NULL) ::ReleaseDC(0, pDC);\r
1101                 if (TmpDC==NULL) return 0;\r
1102                 //choose the font\r
1103                 HFONT m_Font;\r
1104                 LOGFONT* m_pLF;\r
1105                 m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));\r
1106                 _tcsncpy(m_pLF->lfFaceName,font,31);    // For UNICODE support\r
1107                 //strncpy(m_pLF->lfFaceName,font,31);\r
1108                 m_pLF->lfHeight=lSize;\r
1109                 m_pLF->lfWeight=lWeight;\r
1110                 m_pLF->lfItalic=bItalic;\r
1111                 m_pLF->lfUnderline=bUnderline;\r
1112                 m_Font=CreateFontIndirect(m_pLF);\r
1113                 //select the font in the dc\r
1114                 HFONT pOldFont=NULL;\r
1115                 if (m_Font)\r
1116                         pOldFont = (HFONT)SelectObject(TmpDC,m_Font);\r
1117                 else\r
1118                         pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));\r
1119 \r
1120                 //Set text color\r
1121                 SetTextColor(TmpDC,RGB(255,255,255));\r
1122                 SetBkColor(TmpDC,RGB(0,0,0));\r
1123                 //draw the text\r
1124                 SetBkMode(TmpDC,OPAQUE);\r
1125                 //Set text position;\r
1126                 RECT pos = {0,0,0,0};\r
1127                 //long len = (long)strlen(text);\r
1128                 long len = (long)_tcslen(text); // For UNICODE support\r
1129                 ::DrawText(TmpDC,text,len,&pos,DT_CALCRECT);\r
1130                 pos.right+=pos.bottom; //for italics\r
1131 \r
1132                 //Preparing Bitmap Info\r
1133                 long width=pos.right;\r
1134                 long height=pos.bottom;\r
1135                 BITMAPINFO bmInfo;\r
1136                 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
1137                 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
1138                 bmInfo.bmiHeader.biWidth=width;\r
1139                 bmInfo.bmiHeader.biHeight=height;\r
1140                 bmInfo.bmiHeader.biPlanes=1;\r
1141                 bmInfo.bmiHeader.biBitCount=24;\r
1142                 BYTE *pbase; //points to the final dib\r
1143 \r
1144                 HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
1145                 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
1146                 memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));\r
1147 \r
1148                 ::DrawText(TmpDC,text,len,&pos,0);\r
1149 \r
1150                 CxImage itext;\r
1151                 itext.CreateFromHBITMAP(TmpBmp);\r
1152 \r
1153                 y=head.biHeight-y-1;\r
1154                 for (long ix=0;ix<width;ix++){\r
1155                         for (long iy=0;iy<height;iy++){\r
1156                                 if (itext.GetPixelColor(ix,iy).rgbBlue) SetPixelColor(x+ix,y+iy,color,bSetAlpha);\r
1157                         }\r
1158                 }\r
1159 \r
1160                 //cleanup\r
1161                 if (pOldFont) SelectObject(TmpDC,pOldFont);\r
1162                 DeleteObject(m_Font);\r
1163                 free(m_pLF);\r
1164                 DeleteObject(SelectObject(TmpDC,TmpObj));\r
1165                 DeleteDC(TmpDC);\r
1166         }\r
1167 \r
1168         return 1;\r
1169 }\r
1170 ////////////////////////////////////////////////////////////////////////////////\r
1171 // <VATI>\r
1172 long CxImage::DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha )\r
1173 {\r
1174         if (!IsValid())\r
1175         return -1;\r
1176     \r
1177         //get the background\r
1178         HDC pDC;\r
1179         if (hdc) pDC=hdc; else pDC = ::GetDC(0);\r
1180         if (pDC==NULL) return 0;\r
1181         HDC TmpDC=CreateCompatibleDC(pDC);\r
1182         if (hdc==NULL) ::ReleaseDC(0, pDC);\r
1183         if (TmpDC==NULL) return 0;\r
1184 \r
1185     //choose the font\r
1186         HFONT m_Font;\r
1187     m_Font=CreateFontIndirect( &pTextType->lfont );\r
1188     \r
1189     // get colors in RGBQUAD\r
1190     RGBQUAD p_forecolor = RGBtoRGBQUAD(pTextType->fcolor);\r
1191     RGBQUAD p_backcolor = RGBtoRGBQUAD(pTextType->bcolor);\r
1192 \r
1193     // check alignment and re-set default if necessary\r
1194     if ( pTextType->align != DT_CENTER &&\r
1195          pTextType->align != DT_LEFT &&\r
1196          pTextType->align != DT_RIGHT )\r
1197         pTextType->align = DT_CENTER;\r
1198 \r
1199     // check rounding radius and re-set default if necessary\r
1200     if ( pTextType->b_round > 50 )\r
1201         pTextType->b_round = 10;\r
1202 \r
1203     // check opacity and re-set default if necessary\r
1204     if ( pTextType->b_opacity > 1. || pTextType->b_opacity < .0 )\r
1205         pTextType->b_opacity = 0.;\r
1206 \r
1207     //select the font in the dc\r
1208         HFONT pOldFont=NULL;\r
1209         if (m_Font)\r
1210                 pOldFont = (HFONT)SelectObject(TmpDC,m_Font);\r
1211         else\r
1212                 pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));\r
1213 \r
1214         //Set text color\r
1215     SetTextColor(TmpDC,RGB(255,255,255));\r
1216         SetBkColor(TmpDC,RGB(0,0,0));\r
1217         SetBkMode(TmpDC,OPAQUE);\r
1218         //Set text position;\r
1219         RECT pos = {0,0,0,0};\r
1220         \r
1221     // get text length and number of lines\r
1222     long i=0, numlines=1, len=(long)_tcsclen(pTextType->text);\r
1223     while (i<len)\r
1224     {\r
1225         if ( pTextType->text[i++]==13 )\r
1226             numlines++;\r
1227     }\r
1228 \r
1229         ::DrawText(TmpDC, pTextType->text, len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX | DT_CALCRECT );\r
1230 \r
1231     // increase only if it's really italics, and only one line height\r
1232         if ( pTextType->lfont.lfItalic ) \r
1233         pos.right += pos.bottom/2/numlines; \r
1234 \r
1235     // background frame and rounding radius\r
1236         int frame = 0, roundR = 0;\r
1237     if ( pTextType->opaque )\r
1238     {\r
1239         roundR= (int)(pos.bottom/numlines * pTextType->b_round / 100 ) ;\r
1240         frame = (int)(/*3.5 + */0.29289*roundR ) ;\r
1241         pos.right += pos.bottom/numlines/3 ; // JUST FOR BEAUTY\r
1242     }\r
1243 \r
1244         //Preparing Bitmap Info\r
1245         long width=pos.right +frame*2;\r
1246         long height=pos.bottom +frame*2;\r
1247         BITMAPINFO bmInfo;\r
1248         memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
1249         bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
1250         bmInfo.bmiHeader.biWidth=width;\r
1251         bmInfo.bmiHeader.biHeight=height;\r
1252         bmInfo.bmiHeader.biPlanes=1;\r
1253         bmInfo.bmiHeader.biBitCount=24;\r
1254         BYTE *pbase; //points to the final dib\r
1255 \r
1256         HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
1257         HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
1258         memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));\r
1259 \r
1260         ::DrawText(TmpDC,pTextType->text,len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX| pTextType->align );\r
1261     \r
1262         CxImage itext;\r
1263         itext.CreateFromHBITMAP(TmpBmp);\r
1264     y=head.biHeight-y-1;\r
1265 \r
1266         itext.Negative();\r
1267 \r
1268         if (pTextType->smooth==FALSE){\r
1269                 itext.Threshold(128);\r
1270         } else {\r
1271                 //itext.TextBlur();\r
1272         }\r
1273 \r
1274     //move the insertion point according to alignment type\r
1275     // DT_CENTER: cursor points to the center of text rectangle\r
1276     // DT_RIGHT:  cursor points to right side end of text rectangle\r
1277     // DT_LEFT:   cursor points to left end of text rectangle\r
1278     if ( pTextType->align == DT_CENTER )\r
1279         x -= width/2;\r
1280     else if ( pTextType->align == DT_RIGHT )\r
1281         x -= width;\r
1282     if (x<0) x=0;\r
1283     \r
1284     //draw the background first, if it exists\r
1285     long ix,iy;\r
1286     if ( pTextType->opaque )\r
1287     {\r
1288         int ixf=0; \r
1289         for (ix=0;ix<width;ix++)\r
1290         {\r
1291             if ( ix<=roundR )\r
1292                 ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(ix-roundR)*(ix-roundR))));\r
1293             else if ( ix>=width-roundR-1 )\r
1294                 ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(width-1-ix-roundR)*(width-1-ix-roundR))));\r
1295             else\r
1296                 ixf=0;\r
1297 \r
1298             for (iy=0;iy<height;iy++)\r
1299             {\r
1300                 if ( (ix<=roundR && ( iy > height-ixf-1 || iy < ixf )) ||\r
1301                      (ix>=width-roundR-1 && ( iy > height-ixf-1 || iy < ixf )) )\r
1302                     continue;\r
1303                 else\r
1304                     if ( pTextType->b_opacity > 0.0 && pTextType->b_opacity < 1.0 )\r
1305                     {\r
1306                         RGBQUAD bcolor, pcolor;\r
1307                         // calculate a transition color from original image to background color:\r
1308                         pcolor = GetPixelColor(x+ix,y+iy);\r
1309                                                 bcolor.rgbBlue = (unsigned char)(pTextType->b_opacity * pcolor.rgbBlue + (1.0-pTextType->b_opacity) * p_backcolor.rgbBlue );\r
1310                         bcolor.rgbRed = (unsigned char)(pTextType->b_opacity * pcolor.rgbRed + (1.0-pTextType->b_opacity) * p_backcolor.rgbRed ) ;\r
1311                         bcolor.rgbGreen = (unsigned char)(pTextType->b_opacity * pcolor.rgbGreen + (1.0-pTextType->b_opacity) * p_backcolor.rgbGreen ) ;\r
1312                         bcolor.rgbReserved = 0;\r
1313                         SetPixelColor(x+ix,y+iy,bcolor,bSetAlpha);\r
1314                     }\r
1315                     else\r
1316                         SetPixelColor(x+ix,y+iy,p_backcolor,bSetAlpha);\r
1317                         }\r
1318                 }\r
1319     }\r
1320 \r
1321     // draw the text itself\r
1322     for (ix=0;ix<width;ix++)\r
1323     {\r
1324                 for (iy=0;iy<height;iy++)\r
1325         {\r
1326                         RGBQUAD pcolor = GetPixelColor(x+ix,y+iy);\r
1327                         RGBQUAD tcolor = itext.GetPixelColor(ix,iy);\r
1328             if (tcolor.rgbBlue!=255){\r
1329                                 float a = tcolor.rgbBlue/255.0f;\r
1330                                 pcolor.rgbBlue  = (unsigned char)(a * (pcolor.rgbBlue  - p_forecolor.rgbBlue)  + p_forecolor.rgbBlue );\r
1331                 pcolor.rgbRed   = (unsigned char)(a * (pcolor.rgbRed   - p_forecolor.rgbRed)   + p_forecolor.rgbRed ) ;\r
1332                 pcolor.rgbGreen = (unsigned char)(a * (pcolor.rgbGreen - p_forecolor.rgbGreen) + p_forecolor.rgbGreen );\r
1333                 pcolor.rgbReserved = 0;\r
1334                 SetPixelColor(x+ix+frame,y+iy-frame,pcolor,bSetAlpha);\r
1335               //SetPixelColor(x+ix+frame,y+iy-frame,p_forecolor,bSetAlpha);\r
1336                         }\r
1337                 }\r
1338         }\r
1339 \r
1340         //cleanup\r
1341     if (pOldFont) SelectObject(TmpDC,pOldFont);\r
1342         DeleteObject(m_Font);\r
1343         DeleteObject(SelectObject(TmpDC,TmpObj));\r
1344         DeleteDC(TmpDC);\r
1345         return 1;\r
1346 }\r
1347 \r
1348 //////////////////////////////////////////////////////////////////////////////\r
1349 void CxImage::InitTextInfo( CXTEXTINFO *txt )\r
1350 {\r
1351 \r
1352     memset( txt, 0, sizeof(CXTEXTINFO));\r
1353     \r
1354     // LOGFONT defaults\r
1355     txt->lfont.lfHeight        = -36; \r
1356     txt->lfont.lfCharSet       = EASTEUROPE_CHARSET; // just for Central-European users \r
1357     txt->lfont.lfWeight        = FW_NORMAL;\r
1358     txt->lfont.lfWidth         = 0; \r
1359     txt->lfont.lfEscapement    = 0; \r
1360     txt->lfont.lfOrientation   = 0; \r
1361     txt->lfont.lfItalic        = FALSE; \r
1362     txt->lfont.lfUnderline     = FALSE; \r
1363     txt->lfont.lfStrikeOut     = FALSE; \r
1364     txt->lfont.lfOutPrecision  = OUT_DEFAULT_PRECIS; \r
1365     txt->lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; \r
1366     txt->lfont.lfQuality       = PROOF_QUALITY; \r
1367     txt->lfont.lfPitchAndFamily= DEFAULT_PITCH | FF_DONTCARE ; \r
1368     _stprintf( txt->lfont.lfFaceName, _T("Arial")); //use TCHAR mappings <Cesar M>\r
1369 \r
1370     // initial colors\r
1371     txt->fcolor = RGB( 255,255,160 );  // default foreground: light goldyellow\r
1372     txt->bcolor = RGB(   0, 80,160 );  // default background: light blue\r
1373 \r
1374     // background\r
1375     txt->opaque    = TRUE;  // text has a non-transparent background;\r
1376         txt->smooth    = TRUE;\r
1377     txt->b_opacity = 0.0;   // default: opaque background\r
1378     txt->b_outline = 0;     // default: no outline (OUTLINE NOT IMPLEMENTED AT THIS TIME)\r
1379     txt->b_round   = 20;    // default: rounding radius is 20% of the rectangle height\r
1380     // the text \r
1381     _stprintf( txt->text, _T("Sample Text 01234รตรป")); // text use TCHAR mappings <Cesar M>\r
1382     txt->align = DT_CENTER;\r
1383     return;\r
1384 }\r
1385 \r
1386 #if CXIMAGE_SUPPORT_LAYERS\r
1387 ////////////////////////////////////////////////////////////////////////////////\r
1388 long CxImage::LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)\r
1389 {\r
1390         return LayerDrawAll(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);\r
1391 }\r
1392 ////////////////////////////////////////////////////////////////////////////////\r
1393 long CxImage::LayerDrawAll(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)\r
1394 {\r
1395         long n=0;\r
1396         CxImage* pLayer;\r
1397         while(pLayer=GetLayer(n++)){\r
1398                 if (pLayer->Draw(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)\r
1399                         return 0;\r
1400                 if (pLayer->LayerDrawAll(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)\r
1401                         return 0;\r
1402         }\r
1403         return 1;\r
1404 }\r
1405 #endif //CXIMAGE_SUPPORT_LAYERS\r
1406 \r
1407 ////////////////////////////////////////////////////////////////////////////////\r
1408 #endif //CXIMAGE_SUPPORT_WINDOWS\r
1409 ////////////////////////////////////////////////////////////////////////////////\r