- Extended support for BITMAPCOREINFO / BITMAPCOREHEADER structures.
[wine] / dlls / gdi / tests / bitmap.c
1 /*
2  * Unit test suite for bitmaps
3  *
4  * Copyright 2004 Huw Davies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <assert.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28
29 #include "wine/test.h"
30
31
32 static void test_createdibitmap(void)
33 {
34     HDC hdc, hdcmem;
35     BITMAPINFOHEADER bmih;
36     BITMAP bm;
37     HBITMAP hbm, hbm_colour, hbm_old;
38     INT screen_depth;
39
40     hdc = GetDC(0);
41     screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
42     memset(&bmih, 0, sizeof(bmih));
43     bmih.biSize = sizeof(bmih);
44     bmih.biWidth = 10;
45     bmih.biHeight = 10;
46     bmih.biPlanes = 1;
47     bmih.biBitCount = 32;
48     bmih.biCompression = BI_RGB;
49  
50     /* First create an un-initialised bitmap.  The depth of the bitmap
51        should match that of the hdc and not that supplied in bmih.
52     */
53
54     /* First try 32 bits */
55     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
56     ok(hbm != NULL, "CreateDIBitmap failed\n");
57     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
58
59     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
60     DeleteObject(hbm);
61     
62     /* Then 16 */
63     bmih.biBitCount = 16;
64     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
65     ok(hbm != NULL, "CreateDIBitmap failed\n");
66     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
67
68     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
69     DeleteObject(hbm);
70
71     /* Then 1 */
72     bmih.biBitCount = 1;
73     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
74     ok(hbm != NULL, "CreateDIBitmap failed\n");
75     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
76
77     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
78     DeleteObject(hbm);
79
80     /* Now with a monochrome dc we expect a monochrome bitmap */
81     hdcmem = CreateCompatibleDC(hdc);
82
83     /* First try 32 bits */
84     bmih.biBitCount = 32;
85     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
86     ok(hbm != NULL, "CreateDIBitmap failed\n");
87     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
88
89     ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
90     DeleteObject(hbm);
91     
92     /* Then 16 */
93     bmih.biBitCount = 16;
94     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
95     ok(hbm != NULL, "CreateDIBitmap failed\n");
96     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
97
98     ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
99     DeleteObject(hbm);
100     
101     /* Then 1 */
102     bmih.biBitCount = 1;
103     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
104     ok(hbm != NULL, "CreateDIBitmap failed\n");
105     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
106
107     ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
108     DeleteObject(hbm);
109
110     /* Now select a polychrome bitmap into the dc and we expect
111        screen_depth bitmaps again */
112     hbm_colour = CreateCompatibleBitmap(hdc, 1, 1);
113     hbm_old = SelectObject(hdcmem, hbm_colour);
114
115     /* First try 32 bits */
116     bmih.biBitCount = 32;
117     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
118     ok(hbm != NULL, "CreateDIBitmap failed\n");
119     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
120
121     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
122     DeleteObject(hbm);
123     
124     /* Then 16 */
125     bmih.biBitCount = 16;
126     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
127     ok(hbm != NULL, "CreateDIBitmap failed\n");
128     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
129
130     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
131     DeleteObject(hbm);
132     
133     /* Then 1 */
134     bmih.biBitCount = 1;
135     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
136     ok(hbm != NULL, "CreateDIBitmap failed\n");
137     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
138
139     ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
140     DeleteObject(hbm);
141
142     SelectObject(hdcmem, hbm_old);
143     DeleteObject(hbm_colour);
144     DeleteDC(hdcmem);
145
146     /* If hdc == 0 then we get a 1 bpp bitmap */
147     bmih.biBitCount = 32;
148     hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0);
149     ok(hbm != NULL, "CreateDIBitmap failed\n");
150     ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
151
152     ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
153     DeleteObject(hbm);
154     
155     ReleaseDC(0, hdc);
156 }
157
158 static void test_dibsections(void)
159 {
160     HDC hdc, hdcmem, hdcmem2;
161     HBITMAP hdib, oldbm, hdib2, oldbm2;
162     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
163     char bcibuf[sizeof(BITMAPCOREINFO) + 256 * sizeof(RGBTRIPLE)];
164     BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
165     BITMAPCOREINFO *pbci = (BITMAPCOREINFO *)bcibuf;
166     HBITMAP hcoredib;
167     char coreBits[256];
168     BYTE *bits;
169     RGBQUAD rgb[256];
170     int ret;
171     char logpalbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
172     LOGPALETTE *plogpal = (LOGPALETTE*)logpalbuf;
173     WORD *index;
174     DWORD *bits32;
175     HPALETTE hpal, oldpal;
176
177     hdc = GetDC(0);
178     memset(pbmi, 0, sizeof(bmibuf));
179     pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
180     pbmi->bmiHeader.biHeight = 16;
181     pbmi->bmiHeader.biWidth = 16;
182     pbmi->bmiHeader.biBitCount = 1;
183     pbmi->bmiHeader.biPlanes = 1;
184     pbmi->bmiHeader.biCompression = BI_RGB;
185     pbmi->bmiColors[0].rgbRed = 0xff;
186     pbmi->bmiColors[0].rgbGreen = 0;
187     pbmi->bmiColors[0].rgbBlue = 0;
188     pbmi->bmiColors[1].rgbRed = 0;
189     pbmi->bmiColors[1].rgbGreen = 0;
190     pbmi->bmiColors[1].rgbBlue = 0xff;
191
192     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
193     ok(hdib != NULL, "CreateDIBSection failed\n");
194
195     /* Test if the old BITMAPCOREINFO structure is supported */    
196         
197     pbci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
198     pbci->bmciHeader.bcBitCount = 0;
199
200     ret = GetDIBits(hdc, hdib, 0, 16, NULL, (BITMAPINFO*) pbci, DIB_RGB_COLORS);    
201     ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
202     ok((pbci->bmciHeader.bcWidth == 16) && (pbci->bmciHeader.bcHeight == 16)
203         && (pbci->bmciHeader.bcBitCount == 1) && (pbci->bmciHeader.bcPlanes == 1),
204         "GetDIBits did't fill in the BITMAPCOREHEADER structure properly\n");
205
206     ret = GetDIBits(hdc, hdib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
207     ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
208     ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
209        (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
210        (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
211        "The color table has not been translated to the old BITMAPCOREINFO format\n");
212
213     hcoredib = CreateDIBSection(hdc, (BITMAPINFO*) pbci, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
214     ok(hcoredib != NULL, "CreateDIBSection failed with a BITMAPCOREINFO\n");
215
216     ZeroMemory(pbci->bmciColors, 256 * sizeof(RGBTRIPLE));
217     ret = GetDIBits(hdc, hcoredib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
218     ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
219     ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
220        (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
221        (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
222        "The color table has not been translated to the old BITMAPCOREINFO format\n");    
223
224     DeleteObject(hcoredib);
225
226     hdcmem = CreateCompatibleDC(hdc);
227     oldbm = SelectObject(hdcmem, hdib);
228
229     ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
230     ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
231     ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
232        "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
233        rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
234        rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
235
236     SelectObject(hdcmem, oldbm);
237     DeleteObject(hdib);
238
239     /* Now create a palette and a palette indexed dib section */
240     memset(plogpal, 0, sizeof(logpalbuf));
241     plogpal->palVersion = 0x300;
242     plogpal->palNumEntries = 2;
243     plogpal->palPalEntry[0].peRed = 0xff;
244     plogpal->palPalEntry[0].peBlue = 0xff;
245     plogpal->palPalEntry[1].peGreen = 0xff;
246
247     index = (WORD*)pbmi->bmiColors;
248     *index++ = 0;
249     *index = 1;
250     hpal = CreatePalette(plogpal);
251     ok(hpal != NULL, "CreatePalette failed\n");
252     oldpal = SelectPalette(hdc, hpal, TRUE);
253     hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
254     ok(hdib != NULL, "CreateDIBSection failed\n");
255
256     /* The colour table has already been grabbed from the dc, so we select back the
257        old palette */
258
259     SelectPalette(hdc, oldpal, TRUE);
260     oldbm = SelectObject(hdcmem, hdib);
261
262     ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
263     ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
264     ok(rgb[0].rgbRed == 0xff && rgb[0].rgbBlue == 0xff && rgb[0].rgbGreen == 0 &&
265        rgb[1].rgbRed == 0    && rgb[1].rgbBlue == 0    && rgb[1].rgbGreen == 0xff,
266        "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
267        rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
268        rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
269
270     /* Bottom and 2nd row from top green, everything else magenta */
271     bits[0] = bits[1] = 0xff;
272     bits[13 * 4] = bits[13*4 + 1] = 0xff;
273
274
275     pbmi->bmiHeader.biBitCount = 32;
276
277     hdib2 = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, (void **)&bits32, NULL, 0);
278     ok(hdib2 != NULL, "CreateDIBSection failed\n");
279     hdcmem2 = CreateCompatibleDC(hdc);
280     oldbm2 = SelectObject(hdcmem2, hdib2);
281
282     BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY);
283
284     ok(bits32[0] == 0xff00, "lower left pixel is %08lx\n", bits32[0]);
285     ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08lx\n", bits32[17]);
286
287     SelectObject(hdcmem2, oldbm2);
288     DeleteObject(hdib2);
289
290     SelectObject(hdcmem, oldbm);
291     DeleteObject(hdib);
292
293
294     DeleteDC(hdcmem);
295     ReleaseDC(0, hdc);
296 }    
297
298 START_TEST(bitmap)
299 {
300     test_createdibitmap();
301     test_dibsections();
302 }