A WM_CREATE message sent to an Edit window procedure should
[wine/gsoc_dplay.git] / objects / dib.c
blobc2108244c3676e69c0db38672eef2974d0c198fb
1 /*
2 * GDI device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
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.
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.
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
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "bitmap.h"
28 #include "selectors.h"
29 #include "gdi.h"
30 #include "wownt32.h"
31 #include "wine/debug.h"
32 #include "palette.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
36 /***********************************************************************
37 * DIB_GetDIBWidthBytes
39 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
40 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
42 int DIB_GetDIBWidthBytes( int width, int depth )
44 int words;
46 switch(depth)
48 case 1: words = (width + 31) / 32; break;
49 case 4: words = (width + 7) / 8; break;
50 case 8: words = (width + 3) / 4; break;
51 case 15:
52 case 16: words = (width + 1) / 2; break;
53 case 24: words = (width * 3 + 3)/4; break;
55 default:
56 WARN("(%d): Unsupported depth\n", depth );
57 /* fall through */
58 case 32:
59 words = width;
61 return 4 * words;
64 /***********************************************************************
65 * DIB_GetDIBImageBytes
67 * Return the number of bytes used to hold the image in a DIB bitmap.
69 int DIB_GetDIBImageBytes( int width, int height, int depth )
71 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
75 /***********************************************************************
76 * DIB_BitmapInfoSize
78 * Return the size of the bitmap info structure including color table.
80 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
82 int colors;
84 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
86 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
87 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88 return sizeof(BITMAPCOREHEADER) + colors *
89 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
91 else /* assume BITMAPINFOHEADER */
93 colors = info->bmiHeader.biClrUsed;
94 if (!colors && (info->bmiHeader.biBitCount <= 8))
95 colors = 1 << info->bmiHeader.biBitCount;
96 return sizeof(BITMAPINFOHEADER) + colors *
97 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
102 /***********************************************************************
103 * DIB_GetBitmapInfo
105 * Get the info from a bitmap header.
106 * Return 1 for INFOHEADER, 0 for COREHEADER,
107 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
109 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
110 int *height, WORD *bpp, WORD *compr )
112 if (header->biSize == sizeof(BITMAPINFOHEADER))
114 *width = header->biWidth;
115 *height = header->biHeight;
116 *bpp = header->biBitCount;
117 *compr = header->biCompression;
118 return 1;
120 if (header->biSize == sizeof(BITMAPCOREHEADER))
122 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
123 *width = core->bcWidth;
124 *height = core->bcHeight;
125 *bpp = core->bcBitCount;
126 *compr = 0;
127 return 0;
129 if (header->biSize == sizeof(BITMAPV4HEADER))
131 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
132 *width = v4hdr->bV4Width;
133 *height = v4hdr->bV4Height;
134 *bpp = v4hdr->bV4BitCount;
135 *compr = v4hdr->bV4V4Compression;
136 return 4;
138 if (header->biSize == sizeof(BITMAPV5HEADER))
140 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
141 *width = v5hdr->bV5Width;
142 *height = v5hdr->bV5Height;
143 *bpp = v5hdr->bV5BitCount;
144 *compr = v5hdr->bV5Compression;
145 return 5;
147 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
148 return -1;
152 /***********************************************************************
153 * StretchDIBits (GDI32.@)
155 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
156 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
157 INT heightSrc, const void *bits,
158 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
160 DC *dc;
162 if (!bits || !info)
163 return 0;
165 dc = DC_GetDCUpdate( hdc );
166 if(!dc) return FALSE;
168 if(dc->funcs->pStretchDIBits)
170 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
171 heightDst, xSrc, ySrc, widthSrc,
172 heightSrc, bits, info, wUsage, dwRop);
173 GDI_ReleaseObj( hdc );
175 else /* use StretchBlt */
177 HBITMAP hBitmap, hOldBitmap;
178 HDC hdcMem;
180 GDI_ReleaseObj( hdc );
181 hdcMem = CreateCompatibleDC( hdc );
182 if (info->bmiHeader.biCompression == BI_RLE4 ||
183 info->bmiHeader.biCompression == BI_RLE8) {
185 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
186 * contain all the rectangle described in bmiHeader, but only part of it.
187 * This mean that those undescribed pixels must be left untouched.
188 * So, we first copy on a memory bitmap the current content of the
189 * destination rectangle, blit the DIB bits on top of it - hence leaving
190 * the gaps untouched -, and blitting the rectangle back.
191 * This insure that gaps are untouched on the destination rectangle
192 * Not doing so leads to trashed images (the gaps contain what was on the
193 * memory bitmap => generally black or garbage)
194 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
195 * another speed vs correctness issue. Anyway, if speed is needed, then the
196 * pStretchDIBits function shall be implemented.
197 * ericP (2000/09/09)
199 hBitmap = CreateCompatibleBitmap(hdc, info->bmiHeader.biWidth,
200 info->bmiHeader.biHeight);
201 hOldBitmap = SelectObject( hdcMem, hBitmap );
203 /* copy existing bitmap from destination dc */
204 StretchBlt( hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
205 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
206 dwRop );
207 SetDIBits(hdcMem, hBitmap, 0, info->bmiHeader.biHeight, bits,
208 info, DIB_RGB_COLORS);
210 } else {
211 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
212 bits, info, wUsage );
213 hOldBitmap = SelectObject( hdcMem, hBitmap );
216 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
217 left (negative biHeight) */
218 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
219 hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
220 widthSrc, heightSrc, dwRop );
221 SelectObject( hdcMem, hOldBitmap );
222 DeleteDC( hdcMem );
223 DeleteObject( hBitmap );
225 return heightSrc;
229 /******************************************************************************
230 * SetDIBits [GDI32.@] Sets pixels in a bitmap using colors from DIB
232 * PARAMS
233 * hdc [I] Handle to device context
234 * hbitmap [I] Handle to bitmap
235 * startscan [I] Starting scan line
236 * lines [I] Number of scan lines
237 * bits [I] Array of bitmap bits
238 * info [I] Address of structure with data
239 * coloruse [I] Type of color indexes to use
241 * RETURNS
242 * Success: Number of scan lines copied
243 * Failure: 0
245 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
246 UINT lines, LPCVOID bits, const BITMAPINFO *info,
247 UINT coloruse )
249 DC *dc;
250 BITMAPOBJ *bitmap;
251 INT result = 0;
253 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
255 if (!(dc = DC_GetDCUpdate( hdc )))
257 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
258 GDI_ReleaseObj( hbitmap );
259 return 0;
262 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
264 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
265 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
266 bits, info, coloruse );
267 else
268 result = lines;
270 done:
271 GDI_ReleaseObj( hdc );
272 GDI_ReleaseObj( hbitmap );
273 return result;
277 /***********************************************************************
278 * SetDIBitsToDevice (GDI32.@)
280 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
281 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
282 UINT lines, LPCVOID bits, const BITMAPINFO *info,
283 UINT coloruse )
285 INT ret;
286 DC *dc;
288 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
290 if(dc->funcs->pSetDIBitsToDevice)
291 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
292 ySrc, startscan, lines, bits,
293 info, coloruse );
294 else {
295 FIXME("unimplemented on hdc %p\n", hdc);
296 ret = 0;
299 GDI_ReleaseObj( hdc );
300 return ret;
303 /***********************************************************************
304 * SetDIBColorTable (GDI32.@)
306 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
308 DC * dc;
309 UINT result = 0;
311 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
313 if (dc->funcs->pSetDIBColorTable)
314 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
316 GDI_ReleaseObj( hdc );
317 return result;
321 /***********************************************************************
322 * GetDIBColorTable (GDI32.@)
324 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
326 DC * dc;
327 UINT result = 0;
329 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
331 if (dc->funcs->pGetDIBColorTable)
332 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
334 GDI_ReleaseObj( hdc );
335 return result;
338 /* FIXME the following two structs should be combined with __sysPalTemplate in
339 objects/color.c - this should happen after de-X11-ing both of these
340 files.
341 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
342 and blue - sigh */
344 static RGBQUAD EGAColors[16] = {
345 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
346 { 0x00, 0x00, 0x00, 0x00 },
347 { 0x00, 0x00, 0x80, 0x00 },
348 { 0x00, 0x80, 0x00, 0x00 },
349 { 0x00, 0x80, 0x80, 0x00 },
350 { 0x80, 0x00, 0x00, 0x00 },
351 { 0x80, 0x00, 0x80, 0x00 },
352 { 0x80, 0x80, 0x00, 0x00 },
353 { 0x80, 0x80, 0x80, 0x00 },
354 { 0xc0, 0xc0, 0xc0, 0x00 },
355 { 0x00, 0x00, 0xff, 0x00 },
356 { 0x00, 0xff, 0x00, 0x00 },
357 { 0x00, 0xff, 0xff, 0x00 },
358 { 0xff, 0x00, 0x00, 0x00 },
359 { 0xff, 0x00, 0xff, 0x00 },
360 { 0xff, 0xff, 0x00, 0x00 },
361 { 0xff, 0xff, 0xff, 0x00 }
365 static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
366 /* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
367 { 0x00, 0x00, 0x00, 0x00 },
368 { 0x00, 0x00, 0x80, 0x00 },
369 { 0x00, 0x80, 0x00, 0x00 },
370 { 0x00, 0x80, 0x80, 0x00 },
371 { 0x80, 0x00, 0x00, 0x00 },
372 { 0x80, 0x00, 0x80, 0x00 },
373 { 0x80, 0x80, 0x00, 0x00 },
374 { 0xc0, 0xc0, 0xc0, 0x00 },
375 { 0xc0, 0xdc, 0xc0, 0x00 },
376 { 0xf0, 0xca, 0xa6, 0x00 },
377 { 0xf0, 0xfb, 0xff, 0x00 },
378 { 0xa4, 0xa0, 0xa0, 0x00 },
379 { 0x80, 0x80, 0x80, 0x00 },
380 { 0x00, 0x00, 0xf0, 0x00 },
381 { 0x00, 0xff, 0x00, 0x00 },
382 { 0x00, 0xff, 0xff, 0x00 },
383 { 0xff, 0x00, 0x00, 0x00 },
384 { 0xff, 0x00, 0xff, 0x00 },
385 { 0xff, 0xff, 0x00, 0x00 },
386 { 0xff, 0xff, 0xff, 0x00 }
390 /******************************************************************************
391 * GetDIBits [GDI32.@] Retrieves bits of bitmap and copies to buffer
393 * RETURNS
394 * Success: Number of scan lines copied from bitmap
395 * Failure: 0
397 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
399 INT WINAPI GetDIBits(
400 HDC hdc, /* [in] Handle to device context */
401 HBITMAP hbitmap, /* [in] Handle to bitmap */
402 UINT startscan, /* [in] First scan line to set in dest bitmap */
403 UINT lines, /* [in] Number of scan lines to copy */
404 LPVOID bits, /* [out] Address of array for bitmap bits */
405 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
406 UINT coloruse) /* [in] RGB or palette index */
408 DC * dc;
409 BITMAPOBJ * bmp;
410 int i;
412 if (!info) return 0;
413 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
414 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
416 GDI_ReleaseObj( hdc );
417 return 0;
420 /* Transfer color info */
422 if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
424 info->bmiHeader.biClrUsed = 0;
426 /* If the bitmap object already has a dib section at the
427 same color depth then get the color map from it */
428 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == info->bmiHeader.biBitCount) {
429 GetDIBColorTable(hdc, 0, 1 << info->bmiHeader.biBitCount, info->bmiColors);
431 else {
432 if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
433 /* Generate the color map from the selected palette */
434 PALETTEENTRY * palEntry;
435 PALETTEOBJ * palette;
436 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
437 GDI_ReleaseObj( hdc );
438 GDI_ReleaseObj( hbitmap );
439 return 0;
441 palEntry = palette->logpalette.palPalEntry;
442 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
443 if (coloruse == DIB_RGB_COLORS) {
444 info->bmiColors[i].rgbRed = palEntry->peRed;
445 info->bmiColors[i].rgbGreen = palEntry->peGreen;
446 info->bmiColors[i].rgbBlue = palEntry->peBlue;
447 info->bmiColors[i].rgbReserved = 0;
449 else ((WORD *)info->bmiColors)[i] = (WORD)i;
451 GDI_ReleaseObj( dc->hPalette );
452 } else {
453 switch (info->bmiHeader.biBitCount) {
454 case 1:
455 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
456 info->bmiColors[0].rgbBlue = 0;
457 info->bmiColors[0].rgbReserved = 0;
458 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
459 info->bmiColors[1].rgbBlue = 0xff;
460 info->bmiColors[1].rgbReserved = 0;
461 break;
463 case 4:
464 memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
465 break;
467 case 8:
469 INT r, g, b;
470 RGBQUAD *color;
472 memcpy(info->bmiColors, DefLogPalette,
473 10 * sizeof(RGBQUAD));
474 memcpy(info->bmiColors + 246, DefLogPalette + 10,
475 10 * sizeof(RGBQUAD));
476 color = info->bmiColors + 10;
477 for(r = 0; r <= 5; r++) /* FIXME */
478 for(g = 0; g <= 5; g++)
479 for(b = 0; b <= 5; b++) {
480 color->rgbRed = (r * 0xff) / 5;
481 color->rgbGreen = (g * 0xff) / 5;
482 color->rgbBlue = (b * 0xff) / 5;
483 color->rgbReserved = 0;
484 color++;
492 if (bits && lines)
494 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
495 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
497 /*FIXME: Only RGB dibs supported for now */
498 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
499 int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
500 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
501 unsigned int x, y;
503 if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
505 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
506 dstwidthb = -dstwidthb;
509 switch( info->bmiHeader.biBitCount ) {
511 case 15:
512 case 16: /* 16 bpp dstDIB */
514 LPWORD dstbits = (LPWORD)dbits;
515 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
517 /* FIXME: BI_BITFIELDS not supported yet */
519 switch(bmp->dib->dsBm.bmBitsPixel) {
521 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
523 /* FIXME: BI_BITFIELDS not supported yet */
524 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
525 memcpy(dbits, sbits, srcwidthb);
527 break;
529 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
531 LPBYTE srcbits = sbits;
533 for( y = 0; y < lines; y++) {
534 for( x = 0; x < srcwidth; x++, srcbits += 3)
535 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
536 (((WORD)srcbits[1] << 2) & gmask) |
537 (((WORD)srcbits[2] << 7) & rmask);
539 dstbits = (LPWORD)(dbits+=dstwidthb);
540 srcbits = (sbits += srcwidthb);
543 break;
545 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
547 LPDWORD srcbits = (LPDWORD)sbits;
548 DWORD val;
550 for( y = 0; y < lines; y++) {
551 for( x = 0; x < srcwidth; x++ ) {
552 val = *srcbits++;
553 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
554 ((val >> 9) & rmask));
556 dstbits = (LPWORD)(dbits+=dstwidthb);
557 srcbits = (LPDWORD)(sbits+=srcwidthb);
560 break;
562 default: /* ? bit bmp -> 16 bit DIB */
563 FIXME("15/16 bit DIB %d bit bitmap\n",
564 bmp->bitmap.bmBitsPixel);
565 break;
568 break;
570 case 24: /* 24 bpp dstDIB */
572 LPBYTE dstbits = dbits;
574 switch(bmp->dib->dsBm.bmBitsPixel) {
576 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
578 LPWORD srcbits = (LPWORD)sbits;
579 WORD val;
581 /* FIXME: BI_BITFIELDS not supported yet */
582 for( y = 0; y < lines; y++) {
583 for( x = 0; x < srcwidth; x++ ) {
584 val = *srcbits++;
585 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
586 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
587 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
589 dstbits = (LPBYTE)(dbits+=dstwidthb);
590 srcbits = (LPWORD)(sbits+=srcwidthb);
593 break;
595 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
597 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
598 memcpy(dbits, sbits, srcwidthb);
600 break;
602 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
604 LPBYTE srcbits = (LPBYTE)sbits;
606 for( y = 0; y < lines; y++) {
607 for( x = 0; x < srcwidth; x++, srcbits++ ) {
608 *dstbits++ = *srcbits++;
609 *dstbits++ = *srcbits++;
610 *dstbits++ = *srcbits++;
612 dstbits=(LPBYTE)(dbits+=dstwidthb);
613 srcbits = (LPBYTE)(sbits+=srcwidthb);
616 break;
618 default: /* ? bit bmp -> 24 bit DIB */
619 FIXME("24 bit DIB %d bit bitmap\n",
620 bmp->bitmap.bmBitsPixel);
621 break;
624 break;
626 case 32: /* 32 bpp dstDIB */
628 LPDWORD dstbits = (LPDWORD)dbits;
630 /* FIXME: BI_BITFIELDS not supported yet */
632 switch(bmp->dib->dsBm.bmBitsPixel) {
633 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
635 LPWORD srcbits = (LPWORD)sbits;
636 DWORD val;
638 /* FIXME: BI_BITFIELDS not supported yet */
639 for( y = 0; y < lines; y++) {
640 for( x = 0; x < srcwidth; x++ ) {
641 val = (DWORD)*srcbits++;
642 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
643 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
644 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
646 dstbits=(LPDWORD)(dbits+=dstwidthb);
647 srcbits=(LPWORD)(sbits+=srcwidthb);
650 break;
652 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
654 LPBYTE srcbits = sbits;
656 for( y = 0; y < lines; y++) {
657 for( x = 0; x < srcwidth; x++, srcbits+=3 )
658 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
659 dstbits=(LPDWORD)(dbits+=dstwidthb);
660 srcbits=(sbits+=srcwidthb);
663 break;
665 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
667 /* FIXME: BI_BITFIELDS not supported yet */
668 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
669 memcpy(dbits, sbits, srcwidthb);
671 break;
673 default: /* ? bit bmp -> 32 bit DIB */
674 FIXME("32 bit DIB %d bit bitmap\n",
675 bmp->bitmap.bmBitsPixel);
676 break;
679 break;
681 default: /* ? bit DIB */
682 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
683 break;
686 /* Otherwise, get bits from the XImage */
687 else
689 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
690 else
692 if (bmp->funcs && bmp->funcs->pGetDIBits)
693 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
694 lines, bits, info, coloruse );
695 else
696 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
700 else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
702 /* fill in struct members */
704 if( info->bmiHeader.biBitCount == 0)
706 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
707 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
708 info->bmiHeader.biPlanes = 1;
709 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
710 info->bmiHeader.biSizeImage =
711 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
712 bmp->bitmap.bmHeight,
713 bmp->bitmap.bmBitsPixel );
714 info->bmiHeader.biCompression = 0;
716 else
718 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
719 info->bmiHeader.biWidth,
720 info->bmiHeader.biHeight,
721 info->bmiHeader.biBitCount );
725 TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
726 info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
727 info->bmiHeader.biHeight);
729 GDI_ReleaseObj( hdc );
730 GDI_ReleaseObj( hbitmap );
732 return lines;
736 /***********************************************************************
737 * CreateDIBitmap (GDI32.@)
739 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
740 DWORD init, LPCVOID bits, const BITMAPINFO *data,
741 UINT coloruse )
743 HBITMAP handle;
744 BOOL fColor;
745 DWORD width;
746 int height;
747 WORD bpp;
748 WORD compr;
749 DC *dc;
751 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
752 if (height < 0) height = -height;
754 /* Check if we should create a monochrome or color bitmap. */
755 /* We create a monochrome bitmap only if it has exactly 2 */
756 /* colors, which are black followed by white, nothing else. */
757 /* In all other cases, we create a color bitmap. */
759 if (bpp != 1) fColor = TRUE;
760 else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
761 else
763 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
765 RGBQUAD *rgb = data->bmiColors;
766 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
768 /* Check if the first color of the colormap is black */
769 if ((col == RGB(0,0,0)))
771 rgb++;
772 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
773 /* If the second color is white, create a monochrome bitmap */
774 fColor = (col != RGB(0xff,0xff,0xff));
776 /* Note : If the first color of the colormap is white
777 followed by black, we have to create a color bitmap.
778 If we don't the white will be displayed in black later on!*/
779 else fColor = TRUE;
781 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
783 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
784 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
785 if ((col == RGB(0,0,0)))
787 rgb++;
788 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
789 fColor = (col != RGB(0xff,0xff,0xff));
791 else fColor = TRUE;
793 else if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
794 { /* FIXME: correct ? */
795 RGBQUAD *rgb = data->bmiColors;
796 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
798 /* Check if the first color of the colormap is black */
799 if ((col == RGB(0,0,0)))
801 rgb++;
802 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
803 /* If the second color is white, create a monochrome bitmap */
804 fColor = (col != RGB(0xff,0xff,0xff));
806 /* Note : If the first color of the colormap is white
807 followed by black, we have to create a color bitmap.
808 If we don't the white will be displayed in black later on!*/
809 else fColor = TRUE;
811 else
813 ERR("(%ld): wrong/unknown size for data\n",
814 data->bmiHeader.biSize );
815 return 0;
819 /* Now create the bitmap */
821 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
823 if (fColor)
824 handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
825 GetDeviceCaps( hdc, BITSPIXEL ), NULL );
826 else handle = CreateBitmap( width, height, 1, 1, NULL );
828 if (handle)
830 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
831 else if (!BITMAP_SetOwnerDC( handle, dc ))
833 DeleteObject( handle );
834 handle = 0;
838 GDI_ReleaseObj( hdc );
839 return handle;
842 /***********************************************************************
843 * CreateDIBSection (GDI.489)
845 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
846 SEGPTR *bits16, HANDLE section, DWORD offset)
848 LPVOID bits32;
849 HBITMAP hbitmap;
851 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
852 if (hbitmap)
854 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
855 if (bmp && bmp->dib && bits32)
857 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
858 INT height = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
859 INT width_bytes = DIB_GetDIBWidthBytes(bi->biWidth, bi->biBitCount);
860 INT size = (bi->biSizeImage && bi->biCompression != BI_RGB) ?
861 bi->biSizeImage : width_bytes * height;
863 /* calculate number of sel's needed for size with 64K steps */
864 WORD count = (size + 0xffff) / 0x10000;
865 WORD sel = AllocSelectorArray16(count);
866 int i;
868 for (i = 0; i < count; i++)
870 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
871 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
872 size -= 0x10000;
874 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
875 if (bits16) *bits16 = bmp->segptr_bits;
877 if (bmp) GDI_ReleaseObj( hbitmap );
879 return HBITMAP_16(hbitmap);
882 /***********************************************************************
883 * DIB_CreateDIBSection
885 HBITMAP DIB_CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
886 LPVOID *bits, HANDLE section,
887 DWORD offset, DWORD ovr_pitch)
889 HBITMAP hbitmap = 0;
890 DC *dc;
891 BOOL bDesktopDC = FALSE;
893 /* If the reference hdc is null, take the desktop dc */
894 if (hdc == 0)
896 hdc = CreateCompatibleDC(0);
897 bDesktopDC = TRUE;
900 if ((dc = DC_GetDCPtr( hdc )))
902 hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
903 GDI_ReleaseObj(hdc);
906 if (bDesktopDC)
907 DeleteDC(hdc);
909 return hbitmap;
912 /***********************************************************************
913 * CreateDIBSection (GDI32.@)
915 HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
916 LPVOID *bits, HANDLE section,
917 DWORD offset)
919 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
922 /***********************************************************************
923 * DIB_CreateDIBFromBitmap
924 * Allocates a packed DIB and copies the bitmap data into it.
926 HGLOBAL DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
928 BITMAPOBJ *pBmp = NULL;
929 HGLOBAL hPackedDIB = 0;
930 LPBYTE pPackedDIB = NULL;
931 LPBITMAPINFOHEADER pbmiHeader = NULL;
932 unsigned int width, height, depth, cDataSize = 0, cPackedSize = 0,
933 OffsetBits = 0, nLinesCopied = 0;
935 /* Get a pointer to the BITMAPOBJ structure */
936 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
937 if (!pBmp) return hPackedDIB;
939 /* Get the bitmap dimensions */
940 width = pBmp->bitmap.bmWidth;
941 height = pBmp->bitmap.bmHeight;
942 depth = pBmp->bitmap.bmBitsPixel;
945 * A packed DIB contains a BITMAPINFO structure followed immediately by
946 * an optional color palette and the pixel data.
949 /* Calculate the size of the packed DIB */
950 cDataSize = DIB_GetDIBImageBytes( width, height, depth );
951 cPackedSize = sizeof(BITMAPINFOHEADER)
952 + ( (depth <= 8) ? (sizeof(RGBQUAD) * (1 << depth)) : 0 )
953 + cDataSize;
954 /* Get the offset to the bits */
955 OffsetBits = cPackedSize - cDataSize;
957 /* Allocate the packed DIB */
958 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
959 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
960 cPackedSize );
961 if ( !hPackedDIB )
963 WARN("Could not allocate packed DIB!\n");
964 goto END;
967 /* A packed DIB starts with a BITMAPINFOHEADER */
968 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
969 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
971 /* Init the BITMAPINFOHEADER */
972 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
973 pbmiHeader->biWidth = width;
974 pbmiHeader->biHeight = height;
975 pbmiHeader->biPlanes = 1;
976 pbmiHeader->biBitCount = depth;
977 pbmiHeader->biCompression = BI_RGB;
978 pbmiHeader->biSizeImage = 0;
979 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
980 pbmiHeader->biClrUsed = 0;
981 pbmiHeader->biClrImportant = 0;
983 /* Retrieve the DIB bits from the bitmap and fill in the
984 * DIB color table if present */
986 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
987 hBmp, /* Handle to bitmap */
988 0, /* First scan line to set in dest bitmap */
989 height, /* Number of scan lines to copy */
990 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
991 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
992 0); /* RGB or palette index */
993 GlobalUnlock(hPackedDIB);
995 /* Cleanup if GetDIBits failed */
996 if (nLinesCopied != height)
998 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, height);
999 GlobalFree(hPackedDIB);
1000 hPackedDIB = 0;
1003 END:
1004 GDI_ReleaseObj( hBmp );
1005 return hPackedDIB;