Implement NtAccessCheck.
[wine/gsoc-2012-control.git] / dlls / gdi / dib.c
blob97dcaa8ec4b2d6b5a1b47019c8644a2164abc0fb
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
22 Important information:
24 * Current Windows versions support two different DIB structures:
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
29 Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30 accept the old "core" structures, and so must WINE.
31 You can distinguish them by looking at the first member (bcSize/biSize),
32 or use the internal function DIB_GetBitmapInfo.
35 * The palettes are stored in different formats:
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
47 * You should never access the color table using the bmiColors member,
48 because the passed structure may have one of the extended headers
49 mentioned above. Use this to calculate the location:
51 BITMAPINFO* info;
52 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
55 * More information:
56 Search for "Bitmap Structures" in MSDN
59 #include <stdarg.h>
60 #include <stdlib.h>
61 #include <string.h>
63 #include "windef.h"
64 #include "winbase.h"
65 #include "gdi.h"
66 #include "wownt32.h"
67 #include "gdi_private.h"
68 #include "wine/debug.h"
70 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
74 Some of the following helper functions are duplicated in
75 dlls/x11drv/dib.c
78 /***********************************************************************
79 * DIB_GetDIBWidthBytes
81 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
82 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
84 int DIB_GetDIBWidthBytes( int width, int depth )
86 int words;
88 switch(depth)
90 case 1: words = (width + 31) / 32; break;
91 case 4: words = (width + 7) / 8; break;
92 case 8: words = (width + 3) / 4; break;
93 case 15:
94 case 16: words = (width + 1) / 2; break;
95 case 24: words = (width * 3 + 3)/4; break;
97 default:
98 WARN("(%d): Unsupported depth\n", depth );
99 /* fall through */
100 case 32:
101 words = width;
103 return 4 * words;
106 /***********************************************************************
107 * DIB_GetDIBImageBytes
109 * Return the number of bytes used to hold the image in a DIB bitmap.
111 int DIB_GetDIBImageBytes( int width, int height, int depth )
113 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
117 /***********************************************************************
118 * DIB_BitmapInfoSize
120 * Return the size of the bitmap info structure including color table.
122 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
124 int colors;
126 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
128 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
129 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
130 return sizeof(BITMAPCOREHEADER) + colors *
131 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
133 else /* assume BITMAPINFOHEADER */
135 colors = info->bmiHeader.biClrUsed;
136 if (colors > 256) colors = 256;
137 if (!colors && (info->bmiHeader.biBitCount <= 8))
138 colors = 1 << info->bmiHeader.biBitCount;
139 return sizeof(BITMAPINFOHEADER) + colors *
140 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
145 /***********************************************************************
146 * DIB_GetBitmapInfo
148 * Get the info from a bitmap header.
149 * Return 1 for INFOHEADER, 0 for COREHEADER,
150 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
152 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
153 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
155 if (header->biSize == sizeof(BITMAPINFOHEADER))
157 *width = header->biWidth;
158 *height = header->biHeight;
159 *planes = header->biPlanes;
160 *bpp = header->biBitCount;
161 *compr = header->biCompression;
162 *size = header->biSizeImage;
163 return 1;
165 if (header->biSize == sizeof(BITMAPCOREHEADER))
167 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
168 *width = core->bcWidth;
169 *height = core->bcHeight;
170 *planes = core->bcPlanes;
171 *bpp = core->bcBitCount;
172 *compr = 0;
173 *size = 0;
174 return 0;
176 if (header->biSize == sizeof(BITMAPV4HEADER))
178 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
179 *width = v4hdr->bV4Width;
180 *height = v4hdr->bV4Height;
181 *planes = v4hdr->bV4Planes;
182 *bpp = v4hdr->bV4BitCount;
183 *compr = v4hdr->bV4V4Compression;
184 *size = v4hdr->bV4SizeImage;
185 return 4;
187 if (header->biSize == sizeof(BITMAPV5HEADER))
189 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
190 *width = v5hdr->bV5Width;
191 *height = v5hdr->bV5Height;
192 *planes = v5hdr->bV5Planes;
193 *bpp = v5hdr->bV5BitCount;
194 *compr = v5hdr->bV5Compression;
195 *size = v5hdr->bV5SizeImage;
196 return 5;
198 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
199 return -1;
203 /***********************************************************************
204 * StretchDIBits (GDI32.@)
206 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
207 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
208 INT heightSrc, const void *bits,
209 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
211 DC *dc;
213 if (!bits || !info)
214 return 0;
216 dc = DC_GetDCUpdate( hdc );
217 if(!dc) return FALSE;
219 if(dc->funcs->pStretchDIBits)
221 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
222 heightDst, xSrc, ySrc, widthSrc,
223 heightSrc, bits, info, wUsage, dwRop);
224 GDI_ReleaseObj( hdc );
226 else /* use StretchBlt */
228 HBITMAP hBitmap, hOldBitmap;
229 HPALETTE hpal = NULL;
230 HDC hdcMem;
231 LONG height;
232 LONG width;
233 WORD planes, bpp;
234 DWORD compr, size;
236 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
238 ERR("Invalid bitmap\n");
239 return 0;
242 if (width < 0)
244 ERR("Bitmap has a negative width\n");
245 return 0;
248 GDI_ReleaseObj( hdc );
249 hdcMem = CreateCompatibleDC( hdc );
250 hBitmap = CreateCompatibleBitmap(hdc, width, height);
251 hOldBitmap = SelectObject( hdcMem, hBitmap );
252 if(wUsage == DIB_PAL_COLORS)
254 hpal = GetCurrentObject(hdc, OBJ_PAL);
255 hpal = SelectPalette(hdcMem, hpal, FALSE);
258 if (info->bmiHeader.biCompression == BI_RLE4 ||
259 info->bmiHeader.biCompression == BI_RLE8) {
261 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
262 * contain all the rectangle described in bmiHeader, but only part of it.
263 * This mean that those undescribed pixels must be left untouched.
264 * So, we first copy on a memory bitmap the current content of the
265 * destination rectangle, blit the DIB bits on top of it - hence leaving
266 * the gaps untouched -, and blitting the rectangle back.
267 * This insure that gaps are untouched on the destination rectangle
268 * Not doing so leads to trashed images (the gaps contain what was on the
269 * memory bitmap => generally black or garbage)
270 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
271 * another speed vs correctness issue. Anyway, if speed is needed, then the
272 * pStretchDIBits function shall be implemented.
273 * ericP (2000/09/09)
276 /* copy existing bitmap from destination dc */
277 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
278 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
279 dwRop );
282 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
284 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
285 left (negative biHeight) */
286 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
287 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
288 widthSrc, heightSrc, dwRop );
289 if(hpal)
290 SelectPalette(hdcMem, hpal, FALSE);
291 SelectObject( hdcMem, hOldBitmap );
292 DeleteDC( hdcMem );
293 DeleteObject( hBitmap );
295 return heightSrc;
299 /******************************************************************************
300 * SetDIBits [GDI32.@]
302 * Sets pixels in a bitmap using colors from DIB.
304 * PARAMS
305 * hdc [I] Handle to device context
306 * hbitmap [I] Handle to bitmap
307 * startscan [I] Starting scan line
308 * lines [I] Number of scan lines
309 * bits [I] Array of bitmap bits
310 * info [I] Address of structure with data
311 * coloruse [I] Type of color indexes to use
313 * RETURNS
314 * Success: Number of scan lines copied
315 * Failure: 0
317 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
318 UINT lines, LPCVOID bits, const BITMAPINFO *info,
319 UINT coloruse )
321 DC *dc;
322 BITMAPOBJ *bitmap;
323 INT result = 0;
325 if (!(dc = DC_GetDCUpdate( hdc )))
327 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
328 return 0;
331 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
333 GDI_ReleaseObj( hdc );
334 return 0;
337 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
339 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
340 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
341 bits, info, coloruse );
342 else
343 result = lines;
345 done:
346 GDI_ReleaseObj( hbitmap );
347 GDI_ReleaseObj( hdc );
348 return result;
352 /***********************************************************************
353 * SetDIBitsToDevice (GDI32.@)
355 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
356 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
357 UINT lines, LPCVOID bits, const BITMAPINFO *info,
358 UINT coloruse )
360 INT ret;
361 DC *dc;
363 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
365 if(dc->funcs->pSetDIBitsToDevice)
366 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
367 ySrc, startscan, lines, bits,
368 info, coloruse );
369 else {
370 FIXME("unimplemented on hdc %p\n", hdc);
371 ret = 0;
374 GDI_ReleaseObj( hdc );
375 return ret;
378 /***********************************************************************
379 * SetDIBColorTable (GDI32.@)
381 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
383 DC * dc;
384 UINT result = 0;
386 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
388 if (dc->funcs->pSetDIBColorTable)
389 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
391 GDI_ReleaseObj( hdc );
392 return result;
396 /***********************************************************************
397 * GetDIBColorTable (GDI32.@)
399 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
401 DC * dc;
402 UINT result = 0;
404 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
406 if (dc->funcs->pGetDIBColorTable)
407 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
409 GDI_ReleaseObj( hdc );
410 return result;
413 /* FIXME the following two structs should be combined with __sysPalTemplate in
414 objects/color.c - this should happen after de-X11-ing both of these
415 files.
416 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
417 and blue - sigh */
419 static RGBQUAD EGAColorsQuads[16] = {
420 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
421 { 0x00, 0x00, 0x00, 0x00 },
422 { 0x00, 0x00, 0x80, 0x00 },
423 { 0x00, 0x80, 0x00, 0x00 },
424 { 0x00, 0x80, 0x80, 0x00 },
425 { 0x80, 0x00, 0x00, 0x00 },
426 { 0x80, 0x00, 0x80, 0x00 },
427 { 0x80, 0x80, 0x00, 0x00 },
428 { 0x80, 0x80, 0x80, 0x00 },
429 { 0xc0, 0xc0, 0xc0, 0x00 },
430 { 0x00, 0x00, 0xff, 0x00 },
431 { 0x00, 0xff, 0x00, 0x00 },
432 { 0x00, 0xff, 0xff, 0x00 },
433 { 0xff, 0x00, 0x00, 0x00 },
434 { 0xff, 0x00, 0xff, 0x00 },
435 { 0xff, 0xff, 0x00, 0x00 },
436 { 0xff, 0xff, 0xff, 0x00 }
439 static RGBTRIPLE EGAColorsTriples[16] = {
440 /* rgbBlue, rgbGreen, rgbRed */
441 { 0x00, 0x00, 0x00 },
442 { 0x00, 0x00, 0x80 },
443 { 0x00, 0x80, 0x00 },
444 { 0x00, 0x80, 0x80 },
445 { 0x80, 0x00, 0x00 },
446 { 0x80, 0x00, 0x80 },
447 { 0x80, 0x80, 0x00 },
448 { 0x80, 0x80, 0x80 },
449 { 0xc0, 0xc0, 0xc0 },
450 { 0x00, 0x00, 0xff },
451 { 0x00, 0xff, 0x00 },
452 { 0x00, 0xff, 0xff },
453 { 0xff, 0x00, 0x00 } ,
454 { 0xff, 0x00, 0xff },
455 { 0xff, 0xff, 0x00 },
456 { 0xff, 0xff, 0xff }
459 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
460 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
461 { 0x00, 0x00, 0x00, 0x00 },
462 { 0x00, 0x00, 0x80, 0x00 },
463 { 0x00, 0x80, 0x00, 0x00 },
464 { 0x00, 0x80, 0x80, 0x00 },
465 { 0x80, 0x00, 0x00, 0x00 },
466 { 0x80, 0x00, 0x80, 0x00 },
467 { 0x80, 0x80, 0x00, 0x00 },
468 { 0xc0, 0xc0, 0xc0, 0x00 },
469 { 0xc0, 0xdc, 0xc0, 0x00 },
470 { 0xf0, 0xca, 0xa6, 0x00 },
471 { 0xf0, 0xfb, 0xff, 0x00 },
472 { 0xa4, 0xa0, 0xa0, 0x00 },
473 { 0x80, 0x80, 0x80, 0x00 },
474 { 0x00, 0x00, 0xf0, 0x00 },
475 { 0x00, 0xff, 0x00, 0x00 },
476 { 0x00, 0xff, 0xff, 0x00 },
477 { 0xff, 0x00, 0x00, 0x00 },
478 { 0xff, 0x00, 0xff, 0x00 },
479 { 0xff, 0xff, 0x00, 0x00 },
480 { 0xff, 0xff, 0xff, 0x00 }
483 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
484 /* rgbBlue, rgbGreen, rgbRed */
485 { 0x00, 0x00, 0x00 },
486 { 0x00, 0x00, 0x80 },
487 { 0x00, 0x80, 0x00 },
488 { 0x00, 0x80, 0x80 },
489 { 0x80, 0x00, 0x00 },
490 { 0x80, 0x00, 0x80 },
491 { 0x80, 0x80, 0x00 },
492 { 0xc0, 0xc0, 0xc0 },
493 { 0xc0, 0xdc, 0xc0 },
494 { 0xf0, 0xca, 0xa6 },
495 { 0xf0, 0xfb, 0xff },
496 { 0xa4, 0xa0, 0xa0 },
497 { 0x80, 0x80, 0x80 },
498 { 0x00, 0x00, 0xf0 },
499 { 0x00, 0xff, 0x00 },
500 { 0x00, 0xff, 0xff },
501 { 0xff, 0x00, 0x00 },
502 { 0xff, 0x00, 0xff },
503 { 0xff, 0xff, 0x00 },
504 { 0xff, 0xff, 0xff}
508 /******************************************************************************
509 * GetDIBits [GDI32.@]
511 * Retrieves bits of bitmap and copies to buffer.
513 * RETURNS
514 * Success: Number of scan lines copied from bitmap
515 * Failure: 0
517 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
519 INT WINAPI GetDIBits(
520 HDC hdc, /* [in] Handle to device context */
521 HBITMAP hbitmap, /* [in] Handle to bitmap */
522 UINT startscan, /* [in] First scan line to set in dest bitmap */
523 UINT lines, /* [in] Number of scan lines to copy */
524 LPVOID bits, /* [out] Address of array for bitmap bits */
525 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
526 UINT coloruse) /* [in] RGB or palette index */
528 DC * dc;
529 BITMAPOBJ * bmp;
530 int i;
531 HDC memdc;
532 int bitmap_type;
533 BOOL core_header;
534 LONG width;
535 LONG height;
536 WORD planes, bpp;
537 DWORD compr, size;
538 void* colorPtr;
539 RGBTRIPLE* rgbTriples;
540 RGBQUAD* rgbQuads;
542 if (!info) return 0;
544 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
545 if (bitmap_type == -1)
547 ERR("Invalid bitmap format\n");
548 return 0;
550 core_header = (bitmap_type == 0);
551 memdc = CreateCompatibleDC(hdc);
552 if (!(dc = DC_GetDCUpdate( hdc )))
554 DeleteDC(memdc);
555 return 0;
557 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
559 GDI_ReleaseObj( hdc );
560 DeleteDC(memdc);
561 return 0;
564 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
565 rgbTriples = (RGBTRIPLE *) colorPtr;
566 rgbQuads = (RGBQUAD *) colorPtr;
568 /* Transfer color info */
570 if (bpp <= 8 && bpp > 0)
572 if (!core_header) info->bmiHeader.biClrUsed = 0;
574 /* If the bitmap object already has a dib section at the
575 same color depth then get the color map from it */
576 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
577 if(coloruse == DIB_RGB_COLORS) {
578 HBITMAP oldbm = SelectObject(memdc, hbitmap);
579 unsigned int colors = 1 << bpp;
581 if (core_header)
583 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
584 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
586 if (buffer)
588 RGBTRIPLE* index = rgbTriples;
589 GetDIBColorTable(memdc, 0, colors, buffer);
591 for (i=0; i < colors; i++, index++)
593 index->rgbtRed = buffer[i].rgbRed;
594 index->rgbtGreen = buffer[i].rgbGreen;
595 index->rgbtBlue = buffer[i].rgbBlue;
598 HeapFree(GetProcessHeap(), 0, buffer);
601 else
603 GetDIBColorTable(memdc, 0, colors, colorPtr);
605 SelectObject(memdc, oldbm);
607 else {
608 WORD *index = colorPtr;
609 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
610 *index = i;
613 else {
614 if(bpp >= bmp->bitmap.bmBitsPixel) {
615 /* Generate the color map from the selected palette */
616 PALETTEENTRY * palEntry;
617 PALETTEOBJ * palette;
618 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
619 GDI_ReleaseObj( hdc );
620 GDI_ReleaseObj( hbitmap );
621 DeleteDC(memdc);
622 return 0;
624 palEntry = palette->logpalette.palPalEntry;
625 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
626 if (coloruse == DIB_RGB_COLORS) {
627 if (core_header)
629 rgbTriples[i].rgbtRed = palEntry->peRed;
630 rgbTriples[i].rgbtGreen = palEntry->peGreen;
631 rgbTriples[i].rgbtBlue = palEntry->peBlue;
633 else
635 rgbQuads[i].rgbRed = palEntry->peRed;
636 rgbQuads[i].rgbGreen = palEntry->peGreen;
637 rgbQuads[i].rgbBlue = palEntry->peBlue;
638 rgbQuads[i].rgbReserved = 0;
641 else ((WORD *)colorPtr)[i] = (WORD)i;
643 GDI_ReleaseObj( dc->hPalette );
644 } else {
645 switch (bpp) {
646 case 1:
647 if (core_header)
649 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
650 rgbTriples[0].rgbtBlue = 0;
651 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
652 rgbTriples[1].rgbtBlue = 0xff;
654 else
656 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
657 rgbQuads[0].rgbBlue = 0;
658 rgbQuads[0].rgbReserved = 0;
659 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
660 rgbQuads[1].rgbBlue = 0xff;
661 rgbQuads[1].rgbReserved = 0;
663 break;
665 case 4:
666 if (core_header)
667 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
668 else
669 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
671 break;
673 case 8:
675 if (core_header)
677 INT r, g, b;
678 RGBTRIPLE *color;
680 memcpy(rgbTriples, DefLogPaletteTriples,
681 10 * sizeof(RGBTRIPLE));
682 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
683 10 * sizeof(RGBTRIPLE));
684 color = rgbTriples + 10;
685 for(r = 0; r <= 5; r++) /* FIXME */
686 for(g = 0; g <= 5; g++)
687 for(b = 0; b <= 5; b++) {
688 color->rgbtRed = (r * 0xff) / 5;
689 color->rgbtGreen = (g * 0xff) / 5;
690 color->rgbtBlue = (b * 0xff) / 5;
691 color++;
694 else
696 INT r, g, b;
697 RGBQUAD *color;
699 memcpy(rgbQuads, DefLogPaletteQuads,
700 10 * sizeof(RGBQUAD));
701 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
702 10 * sizeof(RGBQUAD));
703 color = rgbQuads + 10;
704 for(r = 0; r <= 5; r++) /* FIXME */
705 for(g = 0; g <= 5; g++)
706 for(b = 0; b <= 5; b++) {
707 color->rgbRed = (r * 0xff) / 5;
708 color->rgbGreen = (g * 0xff) / 5;
709 color->rgbBlue = (b * 0xff) / 5;
710 color->rgbReserved = 0;
711 color++;
720 if (bits && lines)
722 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
723 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
725 /*FIXME: Only RGB dibs supported for now */
726 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
727 unsigned int dstwidth = width;
728 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
729 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
730 unsigned int x, y, width, widthb;
732 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
734 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
735 dstwidthb = -dstwidthb;
738 switch( bpp ) {
740 case 15:
741 case 16: /* 16 bpp dstDIB */
743 LPWORD dstbits = (LPWORD)dbits;
744 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
746 /* FIXME: BI_BITFIELDS not supported yet */
748 switch(bmp->dib->dsBm.bmBitsPixel) {
750 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
752 widthb = min(srcwidthb, abs(dstwidthb));
753 /* FIXME: BI_BITFIELDS not supported yet */
754 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
755 memcpy(dbits, sbits, widthb);
757 break;
759 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
761 LPBYTE srcbits = sbits;
763 width = min(srcwidth, dstwidth);
764 for( y = 0; y < lines; y++) {
765 for( x = 0; x < width; x++, srcbits += 3)
766 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
767 (((WORD)srcbits[1] << 2) & gmask) |
768 (((WORD)srcbits[2] << 7) & rmask);
770 dstbits = (LPWORD)(dbits+=dstwidthb);
771 srcbits = (sbits += srcwidthb);
774 break;
776 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
778 LPDWORD srcbits = (LPDWORD)sbits;
779 DWORD val;
781 width = min(srcwidth, dstwidth);
782 for( y = 0; y < lines; y++) {
783 for( x = 0; x < width; x++ ) {
784 val = *srcbits++;
785 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
786 ((val >> 9) & rmask));
788 dstbits = (LPWORD)(dbits+=dstwidthb);
789 srcbits = (LPDWORD)(sbits+=srcwidthb);
792 break;
794 default: /* ? bit bmp -> 16 bit DIB */
795 FIXME("15/16 bit DIB %d bit bitmap\n",
796 bmp->bitmap.bmBitsPixel);
797 break;
800 break;
802 case 24: /* 24 bpp dstDIB */
804 LPBYTE dstbits = dbits;
806 switch(bmp->dib->dsBm.bmBitsPixel) {
808 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
810 LPWORD srcbits = (LPWORD)sbits;
811 WORD val;
813 width = min(srcwidth, dstwidth);
814 /* FIXME: BI_BITFIELDS not supported yet */
815 for( y = 0; y < lines; y++) {
816 for( x = 0; x < width; x++ ) {
817 val = *srcbits++;
818 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
819 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
820 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
822 dstbits = (LPBYTE)(dbits+=dstwidthb);
823 srcbits = (LPWORD)(sbits+=srcwidthb);
826 break;
828 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
830 widthb = min(srcwidthb, abs(dstwidthb));
831 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
832 memcpy(dbits, sbits, widthb);
834 break;
836 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
838 LPBYTE srcbits = (LPBYTE)sbits;
840 width = min(srcwidth, dstwidth);
841 for( y = 0; y < lines; y++) {
842 for( x = 0; x < width; x++, srcbits++ ) {
843 *dstbits++ = *srcbits++;
844 *dstbits++ = *srcbits++;
845 *dstbits++ = *srcbits++;
847 dstbits=(LPBYTE)(dbits+=dstwidthb);
848 srcbits = (LPBYTE)(sbits+=srcwidthb);
851 break;
853 default: /* ? bit bmp -> 24 bit DIB */
854 FIXME("24 bit DIB %d bit bitmap\n",
855 bmp->bitmap.bmBitsPixel);
856 break;
859 break;
861 case 32: /* 32 bpp dstDIB */
863 LPDWORD dstbits = (LPDWORD)dbits;
865 /* FIXME: BI_BITFIELDS not supported yet */
867 switch(bmp->dib->dsBm.bmBitsPixel) {
868 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
870 LPWORD srcbits = (LPWORD)sbits;
871 DWORD val;
873 width = min(srcwidth, dstwidth);
874 /* FIXME: BI_BITFIELDS not supported yet */
875 for( y = 0; y < lines; y++) {
876 for( x = 0; x < width; x++ ) {
877 val = (DWORD)*srcbits++;
878 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
879 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
880 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
882 dstbits=(LPDWORD)(dbits+=dstwidthb);
883 srcbits=(LPWORD)(sbits+=srcwidthb);
886 break;
888 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
890 LPBYTE srcbits = sbits;
892 width = min(srcwidth, dstwidth);
893 for( y = 0; y < lines; y++) {
894 for( x = 0; x < width; x++, srcbits+=3 )
895 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
896 dstbits=(LPDWORD)(dbits+=dstwidthb);
897 srcbits=(sbits+=srcwidthb);
900 break;
902 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
904 widthb = min(srcwidthb, abs(dstwidthb));
905 /* FIXME: BI_BITFIELDS not supported yet */
906 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
907 memcpy(dbits, sbits, widthb);
910 break;
912 default: /* ? bit bmp -> 32 bit DIB */
913 FIXME("32 bit DIB %d bit bitmap\n",
914 bmp->bitmap.bmBitsPixel);
915 break;
918 break;
920 default: /* ? bit DIB */
921 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
922 break;
925 /* Otherwise, get bits from the XImage */
926 else
928 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
929 else
931 if (bmp->funcs && bmp->funcs->pGetDIBits)
932 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
933 lines, bits, info, coloruse );
934 else
935 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
939 else
941 /* fill in struct members */
943 if (bpp == 0)
945 if (core_header)
947 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
948 coreheader->bcWidth = bmp->bitmap.bmWidth;
949 coreheader->bcHeight = bmp->bitmap.bmHeight;
950 coreheader->bcPlanes = 1;
951 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
953 else
955 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
956 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
957 info->bmiHeader.biPlanes = 1;
958 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
959 info->bmiHeader.biSizeImage =
960 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
961 bmp->bitmap.bmHeight,
962 bmp->bitmap.bmBitsPixel );
963 info->bmiHeader.biCompression = 0;
965 lines = abs(bmp->bitmap.bmHeight);
969 if (!core_header)
971 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
973 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
975 GDI_ReleaseObj( hdc );
976 GDI_ReleaseObj( hbitmap );
977 DeleteDC(memdc);
978 return lines;
982 /***********************************************************************
983 * CreateDIBitmap (GDI32.@)
985 * Creates a DDB (device dependent bitmap) from a DIB.
986 * The DDB will have the same color depth as the reference DC.
988 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
989 DWORD init, LPCVOID bits, const BITMAPINFO *data,
990 UINT coloruse )
992 HBITMAP handle;
993 LONG width;
994 LONG height;
995 WORD planes, bpp;
996 DWORD compr, size;
997 DC *dc;
999 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1001 if (width < 0)
1003 TRACE("Bitmap has a negative width\n");
1004 return 0;
1007 /* Top-down DIBs have a negative height */
1008 if (height < 0) height = -height;
1010 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1011 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1013 if (hdc == NULL)
1014 handle = CreateBitmap( width, height, 1, 1, NULL );
1015 else
1016 handle = CreateCompatibleBitmap( hdc, width, height );
1018 if (handle)
1020 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1022 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1024 if (!BITMAP_SetOwnerDC( handle, dc ))
1026 DeleteObject( handle );
1027 handle = 0;
1029 GDI_ReleaseObj( hdc );
1033 return handle;
1036 /***********************************************************************
1037 * CreateDIBSection (GDI.489)
1039 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1040 SEGPTR *bits16, HANDLE section, DWORD offset)
1042 LPVOID bits32;
1043 HBITMAP hbitmap;
1045 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1046 if (hbitmap)
1048 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1049 if (bmp && bmp->dib && bits32)
1051 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1052 LONG width, height;
1053 WORD planes, bpp;
1054 DWORD compr, size;
1055 INT width_bytes;
1056 WORD count, sel;
1057 int i;
1059 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1061 height = height >= 0 ? height : -height;
1062 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1064 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1066 /* calculate number of sel's needed for size with 64K steps */
1067 count = (size + 0xffff) / 0x10000;
1068 sel = AllocSelectorArray16(count);
1070 for (i = 0; i < count; i++)
1072 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1073 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1074 size -= 0x10000;
1076 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1077 if (bits16) *bits16 = bmp->segptr_bits;
1079 if (bmp) GDI_ReleaseObj( hbitmap );
1081 return HBITMAP_16(hbitmap);
1084 /***********************************************************************
1085 * DIB_CreateDIBSection
1087 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1088 VOID **bits, HANDLE section,
1089 DWORD offset, DWORD ovr_pitch)
1091 HBITMAP ret = 0;
1092 DC *dc;
1093 BOOL bDesktopDC = FALSE;
1094 DIBSECTION *dib;
1095 BITMAPOBJ *bmp;
1096 int bitmap_type;
1097 LONG width, height;
1098 WORD planes, bpp;
1099 DWORD compression, sizeImage;
1100 const DWORD *colorPtr;
1101 void *mapBits = NULL;
1103 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1104 &planes, &bpp, &compression, &sizeImage )) == -1))
1105 return 0;
1107 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1109 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, %s\n",
1110 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1112 dib->dsBm.bmType = 0;
1113 dib->dsBm.bmWidth = width;
1114 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1115 dib->dsBm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(width, bpp);
1116 dib->dsBm.bmPlanes = planes;
1117 dib->dsBm.bmBitsPixel = bpp;
1118 dib->dsBm.bmBits = NULL;
1120 if (!bitmap_type) /* core header */
1122 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1123 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1124 dib->dsBmih.biWidth = width;
1125 dib->dsBmih.biHeight = height;
1126 dib->dsBmih.biPlanes = planes;
1127 dib->dsBmih.biBitCount = bpp;
1128 dib->dsBmih.biCompression = compression;
1129 dib->dsBmih.biXPelsPerMeter = 0;
1130 dib->dsBmih.biYPelsPerMeter = 0;
1131 dib->dsBmih.biClrUsed = 0;
1132 dib->dsBmih.biClrImportant = 0;
1134 else
1136 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1137 dib->dsBmih = bmi->bmiHeader;
1138 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1141 /* only use sizeImage if it's valid and we're dealing with a compressed bitmap */
1142 if (sizeImage && (compression == BI_RLE4 || compression == BI_RLE8))
1143 dib->dsBmih.biSizeImage = sizeImage;
1144 else
1145 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1148 /* set dsBitfields values */
1149 colorPtr = (const DWORD *)((const char *)bmi + (WORD) bmi->bmiHeader.biSize);
1150 if (usage == DIB_PAL_COLORS || bpp <= 8)
1152 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1154 else switch( bpp )
1156 case 15:
1157 case 16:
1158 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0x7c00;
1159 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x03e0;
1160 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x001f;
1161 break;
1162 case 24:
1163 case 32:
1164 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0xff0000;
1165 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x00ff00;
1166 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x0000ff;
1167 break;
1170 /* get storage location for DIB bits */
1172 if (section)
1174 SYSTEM_INFO SystemInfo;
1175 DWORD mapOffset;
1176 INT mapSize;
1178 GetSystemInfo( &SystemInfo );
1179 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1180 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1181 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1182 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1184 else if (ovr_pitch && offset)
1185 dib->dsBm.bmBits = (LPVOID) offset;
1186 else
1188 offset = 0;
1189 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1190 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1192 dib->dshSection = section;
1193 dib->dsOffset = offset;
1195 if (!dib->dsBm.bmBits)
1197 HeapFree( GetProcessHeap(), 0, dib );
1198 return 0;
1201 /* If the reference hdc is null, take the desktop dc */
1202 if (hdc == 0)
1204 hdc = CreateCompatibleDC(0);
1205 bDesktopDC = TRUE;
1208 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1210 /* create Device Dependent Bitmap and add DIB pointer */
1211 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1212 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1214 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1216 bmp->dib = dib;
1217 bmp->funcs = dc->funcs;
1218 GDI_ReleaseObj( ret );
1220 if (dc->funcs->pCreateDIBSection)
1222 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1224 DeleteObject( ret );
1225 ret = 0;
1230 GDI_ReleaseObj(hdc);
1231 if (bDesktopDC) DeleteDC( hdc );
1232 if (ret && bits) *bits = dib->dsBm.bmBits;
1233 return ret;
1235 error:
1236 if (bDesktopDC) DeleteDC( hdc );
1237 if (section) UnmapViewOfFile( mapBits );
1238 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1239 HeapFree( GetProcessHeap(), 0, dib );
1240 return 0;
1243 /***********************************************************************
1244 * CreateDIBSection (GDI32.@)
1246 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1247 VOID **bits, HANDLE section,
1248 DWORD offset)
1250 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);