When creating DIBs with a color depth <= 8, always set biClrUsed field
[wine/multimedia.git] / dlls / gdi / dib.c
blob6b55d8b8c74f014b294c3401d23c4dccb4a40a90
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
46 If biCompression is BI_BITFIELDS, the color masks are at the same position
47 in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
48 the new headers have structure members for the masks.
51 * You should never access the color table using the bmiColors member,
52 because the passed structure may have one of the extended headers
53 mentioned above. Use this to calculate the location:
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
59 * More information:
60 Search for "Bitmap Structures" in MSDN
63 #include <stdarg.h>
64 #include <stdlib.h>
65 #include <string.h>
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi.h"
70 #include "wownt32.h"
71 #include "gdi_private.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
78 Some of the following helper functions are duplicated in
79 dlls/x11drv/dib.c
82 /***********************************************************************
83 * DIB_GetDIBWidthBytes
85 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
86 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
88 int DIB_GetDIBWidthBytes( int width, int depth )
90 int words;
92 switch(depth)
94 case 1: words = (width + 31) / 32; break;
95 case 4: words = (width + 7) / 8; break;
96 case 8: words = (width + 3) / 4; break;
97 case 15:
98 case 16: words = (width + 1) / 2; break;
99 case 24: words = (width * 3 + 3)/4; break;
101 default:
102 WARN("(%d): Unsupported depth\n", depth );
103 /* fall through */
104 case 32:
105 words = width;
107 return 4 * words;
110 /***********************************************************************
111 * DIB_GetDIBImageBytes
113 * Return the number of bytes used to hold the image in a DIB bitmap.
115 int DIB_GetDIBImageBytes( int width, int height, int depth )
117 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
121 /***********************************************************************
122 * DIB_BitmapInfoSize
124 * Return the size of the bitmap info structure including color table.
126 int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
128 int colors;
130 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
132 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
133 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
134 return sizeof(BITMAPCOREHEADER) + colors *
135 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
137 else /* assume BITMAPINFOHEADER */
139 colors = info->bmiHeader.biClrUsed;
140 if (colors > 256) colors = 256;
141 if (!colors && (info->bmiHeader.biBitCount <= 8))
142 colors = 1 << info->bmiHeader.biBitCount;
143 return sizeof(BITMAPINFOHEADER) + colors *
144 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
149 /***********************************************************************
150 * DIB_GetBitmapInfo
152 * Get the info from a bitmap header.
153 * Return 1 for INFOHEADER, 0 for COREHEADER,
154 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
156 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
157 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
159 if (header->biSize == sizeof(BITMAPINFOHEADER))
161 *width = header->biWidth;
162 *height = header->biHeight;
163 *planes = header->biPlanes;
164 *bpp = header->biBitCount;
165 *compr = header->biCompression;
166 *size = header->biSizeImage;
167 return 1;
169 if (header->biSize == sizeof(BITMAPCOREHEADER))
171 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
172 *width = core->bcWidth;
173 *height = core->bcHeight;
174 *planes = core->bcPlanes;
175 *bpp = core->bcBitCount;
176 *compr = 0;
177 *size = 0;
178 return 0;
180 if (header->biSize == sizeof(BITMAPV4HEADER))
182 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
183 *width = v4hdr->bV4Width;
184 *height = v4hdr->bV4Height;
185 *planes = v4hdr->bV4Planes;
186 *bpp = v4hdr->bV4BitCount;
187 *compr = v4hdr->bV4V4Compression;
188 *size = v4hdr->bV4SizeImage;
189 return 4;
191 if (header->biSize == sizeof(BITMAPV5HEADER))
193 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
194 *width = v5hdr->bV5Width;
195 *height = v5hdr->bV5Height;
196 *planes = v5hdr->bV5Planes;
197 *bpp = v5hdr->bV5BitCount;
198 *compr = v5hdr->bV5Compression;
199 *size = v5hdr->bV5SizeImage;
200 return 5;
202 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
203 return -1;
207 /***********************************************************************
208 * StretchDIBits (GDI32.@)
210 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
211 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
212 INT heightSrc, const void *bits,
213 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
215 DC *dc;
217 if (!bits || !info)
218 return 0;
220 dc = DC_GetDCUpdate( hdc );
221 if(!dc) return FALSE;
223 if(dc->funcs->pStretchDIBits)
225 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
226 heightDst, xSrc, ySrc, widthSrc,
227 heightSrc, bits, info, wUsage, dwRop);
228 GDI_ReleaseObj( hdc );
230 else /* use StretchBlt */
232 HBITMAP hBitmap, hOldBitmap;
233 HPALETTE hpal = NULL;
234 HDC hdcMem;
235 LONG height;
236 LONG width;
237 WORD planes, bpp;
238 DWORD compr, size;
240 GDI_ReleaseObj( hdc );
242 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
244 ERR("Invalid bitmap\n");
245 return 0;
248 if (width < 0)
250 ERR("Bitmap has a negative width\n");
251 return 0;
254 hdcMem = CreateCompatibleDC( hdc );
255 hBitmap = CreateCompatibleBitmap(hdc, width, height);
256 hOldBitmap = SelectObject( hdcMem, hBitmap );
257 if(wUsage == DIB_PAL_COLORS)
259 hpal = GetCurrentObject(hdc, OBJ_PAL);
260 hpal = SelectPalette(hdcMem, hpal, FALSE);
263 if (info->bmiHeader.biCompression == BI_RLE4 ||
264 info->bmiHeader.biCompression == BI_RLE8) {
266 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
267 * contain all the rectangle described in bmiHeader, but only part of it.
268 * This mean that those undescribed pixels must be left untouched.
269 * So, we first copy on a memory bitmap the current content of the
270 * destination rectangle, blit the DIB bits on top of it - hence leaving
271 * the gaps untouched -, and blitting the rectangle back.
272 * This insure that gaps are untouched on the destination rectangle
273 * Not doing so leads to trashed images (the gaps contain what was on the
274 * memory bitmap => generally black or garbage)
275 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
276 * another speed vs correctness issue. Anyway, if speed is needed, then the
277 * pStretchDIBits function shall be implemented.
278 * ericP (2000/09/09)
281 /* copy existing bitmap from destination dc */
282 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
283 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
284 dwRop );
287 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
289 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
290 left (negative biHeight) */
291 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
292 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
293 widthSrc, heightSrc, dwRop );
294 if(hpal)
295 SelectPalette(hdcMem, hpal, FALSE);
296 SelectObject( hdcMem, hOldBitmap );
297 DeleteDC( hdcMem );
298 DeleteObject( hBitmap );
300 return heightSrc;
304 /******************************************************************************
305 * SetDIBits [GDI32.@]
307 * Sets pixels in a bitmap using colors from DIB.
309 * PARAMS
310 * hdc [I] Handle to device context
311 * hbitmap [I] Handle to bitmap
312 * startscan [I] Starting scan line
313 * lines [I] Number of scan lines
314 * bits [I] Array of bitmap bits
315 * info [I] Address of structure with data
316 * coloruse [I] Type of color indexes to use
318 * RETURNS
319 * Success: Number of scan lines copied
320 * Failure: 0
322 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
323 UINT lines, LPCVOID bits, const BITMAPINFO *info,
324 UINT coloruse )
326 DC *dc;
327 BITMAPOBJ *bitmap;
328 INT result = 0;
330 if (!(dc = DC_GetDCUpdate( hdc )))
332 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
333 return 0;
336 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
338 GDI_ReleaseObj( hdc );
339 return 0;
342 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
344 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
345 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
346 bits, info, coloruse );
347 else
348 result = lines;
350 done:
351 GDI_ReleaseObj( hbitmap );
352 GDI_ReleaseObj( hdc );
353 return result;
357 /***********************************************************************
358 * SetDIBitsToDevice (GDI32.@)
360 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
361 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
362 UINT lines, LPCVOID bits, const BITMAPINFO *info,
363 UINT coloruse )
365 INT ret;
366 DC *dc;
368 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
370 if(dc->funcs->pSetDIBitsToDevice)
371 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
372 ySrc, startscan, lines, bits,
373 info, coloruse );
374 else {
375 FIXME("unimplemented on hdc %p\n", hdc);
376 ret = 0;
379 GDI_ReleaseObj( hdc );
380 return ret;
383 /***********************************************************************
384 * SetDIBColorTable (GDI32.@)
386 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
388 DC * dc;
389 UINT result = 0;
391 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
393 if (dc->funcs->pSetDIBColorTable)
394 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
396 GDI_ReleaseObj( hdc );
397 return result;
401 /***********************************************************************
402 * GetDIBColorTable (GDI32.@)
404 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
406 DC * dc;
407 UINT result = 0;
409 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
411 if (dc->funcs->pGetDIBColorTable)
412 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
414 GDI_ReleaseObj( hdc );
415 return result;
418 /* FIXME the following two structs should be combined with __sysPalTemplate in
419 objects/color.c - this should happen after de-X11-ing both of these
420 files.
421 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
422 and blue - sigh */
424 static RGBQUAD EGAColorsQuads[16] = {
425 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
426 { 0x00, 0x00, 0x00, 0x00 },
427 { 0x00, 0x00, 0x80, 0x00 },
428 { 0x00, 0x80, 0x00, 0x00 },
429 { 0x00, 0x80, 0x80, 0x00 },
430 { 0x80, 0x00, 0x00, 0x00 },
431 { 0x80, 0x00, 0x80, 0x00 },
432 { 0x80, 0x80, 0x00, 0x00 },
433 { 0x80, 0x80, 0x80, 0x00 },
434 { 0xc0, 0xc0, 0xc0, 0x00 },
435 { 0x00, 0x00, 0xff, 0x00 },
436 { 0x00, 0xff, 0x00, 0x00 },
437 { 0x00, 0xff, 0xff, 0x00 },
438 { 0xff, 0x00, 0x00, 0x00 },
439 { 0xff, 0x00, 0xff, 0x00 },
440 { 0xff, 0xff, 0x00, 0x00 },
441 { 0xff, 0xff, 0xff, 0x00 }
444 static RGBTRIPLE EGAColorsTriples[16] = {
445 /* rgbBlue, rgbGreen, rgbRed */
446 { 0x00, 0x00, 0x00 },
447 { 0x00, 0x00, 0x80 },
448 { 0x00, 0x80, 0x00 },
449 { 0x00, 0x80, 0x80 },
450 { 0x80, 0x00, 0x00 },
451 { 0x80, 0x00, 0x80 },
452 { 0x80, 0x80, 0x00 },
453 { 0x80, 0x80, 0x80 },
454 { 0xc0, 0xc0, 0xc0 },
455 { 0x00, 0x00, 0xff },
456 { 0x00, 0xff, 0x00 },
457 { 0x00, 0xff, 0xff },
458 { 0xff, 0x00, 0x00 } ,
459 { 0xff, 0x00, 0xff },
460 { 0xff, 0xff, 0x00 },
461 { 0xff, 0xff, 0xff }
464 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
465 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
466 { 0x00, 0x00, 0x00, 0x00 },
467 { 0x00, 0x00, 0x80, 0x00 },
468 { 0x00, 0x80, 0x00, 0x00 },
469 { 0x00, 0x80, 0x80, 0x00 },
470 { 0x80, 0x00, 0x00, 0x00 },
471 { 0x80, 0x00, 0x80, 0x00 },
472 { 0x80, 0x80, 0x00, 0x00 },
473 { 0xc0, 0xc0, 0xc0, 0x00 },
474 { 0xc0, 0xdc, 0xc0, 0x00 },
475 { 0xf0, 0xca, 0xa6, 0x00 },
476 { 0xf0, 0xfb, 0xff, 0x00 },
477 { 0xa4, 0xa0, 0xa0, 0x00 },
478 { 0x80, 0x80, 0x80, 0x00 },
479 { 0x00, 0x00, 0xf0, 0x00 },
480 { 0x00, 0xff, 0x00, 0x00 },
481 { 0x00, 0xff, 0xff, 0x00 },
482 { 0xff, 0x00, 0x00, 0x00 },
483 { 0xff, 0x00, 0xff, 0x00 },
484 { 0xff, 0xff, 0x00, 0x00 },
485 { 0xff, 0xff, 0xff, 0x00 }
488 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
489 /* rgbBlue, rgbGreen, rgbRed */
490 { 0x00, 0x00, 0x00 },
491 { 0x00, 0x00, 0x80 },
492 { 0x00, 0x80, 0x00 },
493 { 0x00, 0x80, 0x80 },
494 { 0x80, 0x00, 0x00 },
495 { 0x80, 0x00, 0x80 },
496 { 0x80, 0x80, 0x00 },
497 { 0xc0, 0xc0, 0xc0 },
498 { 0xc0, 0xdc, 0xc0 },
499 { 0xf0, 0xca, 0xa6 },
500 { 0xf0, 0xfb, 0xff },
501 { 0xa4, 0xa0, 0xa0 },
502 { 0x80, 0x80, 0x80 },
503 { 0x00, 0x00, 0xf0 },
504 { 0x00, 0xff, 0x00 },
505 { 0x00, 0xff, 0xff },
506 { 0xff, 0x00, 0x00 },
507 { 0xff, 0x00, 0xff },
508 { 0xff, 0xff, 0x00 },
509 { 0xff, 0xff, 0xff}
513 /******************************************************************************
514 * GetDIBits [GDI32.@]
516 * Retrieves bits of bitmap and copies to buffer.
518 * RETURNS
519 * Success: Number of scan lines copied from bitmap
520 * Failure: 0
522 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
524 INT WINAPI GetDIBits(
525 HDC hdc, /* [in] Handle to device context */
526 HBITMAP hbitmap, /* [in] Handle to bitmap */
527 UINT startscan, /* [in] First scan line to set in dest bitmap */
528 UINT lines, /* [in] Number of scan lines to copy */
529 LPVOID bits, /* [out] Address of array for bitmap bits */
530 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
531 UINT coloruse) /* [in] RGB or palette index */
533 DC * dc;
534 BITMAPOBJ * bmp;
535 int i;
536 HDC memdc;
537 int bitmap_type;
538 BOOL core_header;
539 LONG width;
540 LONG height;
541 WORD planes, bpp;
542 DWORD compr, size;
543 void* colorPtr;
544 RGBTRIPLE* rgbTriples;
545 RGBQUAD* rgbQuads;
547 if (!info) return 0;
549 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
550 if (bitmap_type == -1)
552 ERR("Invalid bitmap format\n");
553 return 0;
555 core_header = (bitmap_type == 0);
556 memdc = CreateCompatibleDC(hdc);
557 if (!(dc = DC_GetDCUpdate( hdc )))
559 DeleteDC(memdc);
560 return 0;
562 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
564 GDI_ReleaseObj( hdc );
565 DeleteDC(memdc);
566 return 0;
569 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
570 rgbTriples = (RGBTRIPLE *) colorPtr;
571 rgbQuads = (RGBQUAD *) colorPtr;
573 /* Transfer color info */
575 if (bpp <= 8 && bpp > 0)
577 if (!core_header) info->bmiHeader.biClrUsed = 0;
579 /* If the bitmap object already has a dib section at the
580 same color depth then get the color map from it */
581 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
582 if(coloruse == DIB_RGB_COLORS) {
583 HBITMAP oldbm = SelectObject(memdc, hbitmap);
584 unsigned int colors = 1 << bpp;
586 if (core_header)
588 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
589 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
591 if (buffer)
593 RGBTRIPLE* index = rgbTriples;
594 GetDIBColorTable(memdc, 0, colors, buffer);
596 for (i=0; i < colors; i++, index++)
598 index->rgbtRed = buffer[i].rgbRed;
599 index->rgbtGreen = buffer[i].rgbGreen;
600 index->rgbtBlue = buffer[i].rgbBlue;
603 HeapFree(GetProcessHeap(), 0, buffer);
606 else
608 GetDIBColorTable(memdc, 0, colors, colorPtr);
610 SelectObject(memdc, oldbm);
612 else {
613 WORD *index = colorPtr;
614 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
615 *index = i;
618 else {
619 if(bpp >= bmp->bitmap.bmBitsPixel) {
620 /* Generate the color map from the selected palette */
621 PALETTEENTRY * palEntry;
622 PALETTEOBJ * palette;
623 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
624 GDI_ReleaseObj( hdc );
625 GDI_ReleaseObj( hbitmap );
626 DeleteDC(memdc);
627 return 0;
629 palEntry = palette->logpalette.palPalEntry;
630 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
631 if (coloruse == DIB_RGB_COLORS) {
632 if (core_header)
634 rgbTriples[i].rgbtRed = palEntry->peRed;
635 rgbTriples[i].rgbtGreen = palEntry->peGreen;
636 rgbTriples[i].rgbtBlue = palEntry->peBlue;
638 else
640 rgbQuads[i].rgbRed = palEntry->peRed;
641 rgbQuads[i].rgbGreen = palEntry->peGreen;
642 rgbQuads[i].rgbBlue = palEntry->peBlue;
643 rgbQuads[i].rgbReserved = 0;
646 else ((WORD *)colorPtr)[i] = (WORD)i;
648 GDI_ReleaseObj( dc->hPalette );
649 } else {
650 switch (bpp) {
651 case 1:
652 if (core_header)
654 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
655 rgbTriples[0].rgbtBlue = 0;
656 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
657 rgbTriples[1].rgbtBlue = 0xff;
659 else
661 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
662 rgbQuads[0].rgbBlue = 0;
663 rgbQuads[0].rgbReserved = 0;
664 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
665 rgbQuads[1].rgbBlue = 0xff;
666 rgbQuads[1].rgbReserved = 0;
668 break;
670 case 4:
671 if (core_header)
672 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
673 else
674 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
676 break;
678 case 8:
680 if (core_header)
682 INT r, g, b;
683 RGBTRIPLE *color;
685 memcpy(rgbTriples, DefLogPaletteTriples,
686 10 * sizeof(RGBTRIPLE));
687 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
688 10 * sizeof(RGBTRIPLE));
689 color = rgbTriples + 10;
690 for(r = 0; r <= 5; r++) /* FIXME */
691 for(g = 0; g <= 5; g++)
692 for(b = 0; b <= 5; b++) {
693 color->rgbtRed = (r * 0xff) / 5;
694 color->rgbtGreen = (g * 0xff) / 5;
695 color->rgbtBlue = (b * 0xff) / 5;
696 color++;
699 else
701 INT r, g, b;
702 RGBQUAD *color;
704 memcpy(rgbQuads, DefLogPaletteQuads,
705 10 * sizeof(RGBQUAD));
706 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
707 10 * sizeof(RGBQUAD));
708 color = rgbQuads + 10;
709 for(r = 0; r <= 5; r++) /* FIXME */
710 for(g = 0; g <= 5; g++)
711 for(b = 0; b <= 5; b++) {
712 color->rgbRed = (r * 0xff) / 5;
713 color->rgbGreen = (g * 0xff) / 5;
714 color->rgbBlue = (b * 0xff) / 5;
715 color->rgbReserved = 0;
716 color++;
725 if (bits && lines)
727 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
728 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
730 /*FIXME: Only RGB dibs supported for now */
731 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
732 unsigned int dstwidth = width;
733 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
734 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
735 unsigned int x, y, width, widthb;
737 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
739 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
740 dstwidthb = -dstwidthb;
743 switch( bpp ) {
745 case 15:
746 case 16: /* 16 bpp dstDIB */
748 LPWORD dstbits = (LPWORD)dbits;
749 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
751 /* FIXME: BI_BITFIELDS not supported yet */
753 switch(bmp->dib->dsBm.bmBitsPixel) {
755 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
757 widthb = min(srcwidthb, abs(dstwidthb));
758 /* FIXME: BI_BITFIELDS not supported yet */
759 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
760 memcpy(dbits, sbits, widthb);
762 break;
764 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
766 LPBYTE srcbits = sbits;
768 width = min(srcwidth, dstwidth);
769 for( y = 0; y < lines; y++) {
770 for( x = 0; x < width; x++, srcbits += 3)
771 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
772 (((WORD)srcbits[1] << 2) & gmask) |
773 (((WORD)srcbits[2] << 7) & rmask);
775 dstbits = (LPWORD)(dbits+=dstwidthb);
776 srcbits = (sbits += srcwidthb);
779 break;
781 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
783 LPDWORD srcbits = (LPDWORD)sbits;
784 DWORD val;
786 width = min(srcwidth, dstwidth);
787 for( y = 0; y < lines; y++) {
788 for( x = 0; x < width; x++ ) {
789 val = *srcbits++;
790 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
791 ((val >> 9) & rmask));
793 dstbits = (LPWORD)(dbits+=dstwidthb);
794 srcbits = (LPDWORD)(sbits+=srcwidthb);
797 break;
799 default: /* ? bit bmp -> 16 bit DIB */
800 FIXME("15/16 bit DIB %d bit bitmap\n",
801 bmp->bitmap.bmBitsPixel);
802 break;
805 break;
807 case 24: /* 24 bpp dstDIB */
809 LPBYTE dstbits = dbits;
811 switch(bmp->dib->dsBm.bmBitsPixel) {
813 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
815 LPWORD srcbits = (LPWORD)sbits;
816 WORD val;
818 width = min(srcwidth, dstwidth);
819 /* FIXME: BI_BITFIELDS not supported yet */
820 for( y = 0; y < lines; y++) {
821 for( x = 0; x < width; x++ ) {
822 val = *srcbits++;
823 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
824 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
825 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
827 dstbits = (LPBYTE)(dbits+=dstwidthb);
828 srcbits = (LPWORD)(sbits+=srcwidthb);
831 break;
833 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
835 widthb = min(srcwidthb, abs(dstwidthb));
836 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
837 memcpy(dbits, sbits, widthb);
839 break;
841 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
843 LPBYTE srcbits = (LPBYTE)sbits;
845 width = min(srcwidth, dstwidth);
846 for( y = 0; y < lines; y++) {
847 for( x = 0; x < width; x++, srcbits++ ) {
848 *dstbits++ = *srcbits++;
849 *dstbits++ = *srcbits++;
850 *dstbits++ = *srcbits++;
852 dstbits=(LPBYTE)(dbits+=dstwidthb);
853 srcbits = (LPBYTE)(sbits+=srcwidthb);
856 break;
858 default: /* ? bit bmp -> 24 bit DIB */
859 FIXME("24 bit DIB %d bit bitmap\n",
860 bmp->bitmap.bmBitsPixel);
861 break;
864 break;
866 case 32: /* 32 bpp dstDIB */
868 LPDWORD dstbits = (LPDWORD)dbits;
870 /* FIXME: BI_BITFIELDS not supported yet */
872 switch(bmp->dib->dsBm.bmBitsPixel) {
873 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
875 LPWORD srcbits = (LPWORD)sbits;
876 DWORD val;
878 width = min(srcwidth, dstwidth);
879 /* FIXME: BI_BITFIELDS not supported yet */
880 for( y = 0; y < lines; y++) {
881 for( x = 0; x < width; x++ ) {
882 val = (DWORD)*srcbits++;
883 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
884 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
885 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
887 dstbits=(LPDWORD)(dbits+=dstwidthb);
888 srcbits=(LPWORD)(sbits+=srcwidthb);
891 break;
893 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
895 LPBYTE srcbits = sbits;
897 width = min(srcwidth, dstwidth);
898 for( y = 0; y < lines; y++) {
899 for( x = 0; x < width; x++, srcbits+=3 )
900 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
901 dstbits=(LPDWORD)(dbits+=dstwidthb);
902 srcbits=(sbits+=srcwidthb);
905 break;
907 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
909 widthb = min(srcwidthb, abs(dstwidthb));
910 /* FIXME: BI_BITFIELDS not supported yet */
911 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
912 memcpy(dbits, sbits, widthb);
915 break;
917 default: /* ? bit bmp -> 32 bit DIB */
918 FIXME("32 bit DIB %d bit bitmap\n",
919 bmp->bitmap.bmBitsPixel);
920 break;
923 break;
925 default: /* ? bit DIB */
926 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
927 break;
930 /* Otherwise, get bits from the XImage */
931 else
933 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
934 else
936 if (bmp->funcs && bmp->funcs->pGetDIBits)
937 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
938 lines, bits, info, coloruse );
939 else
940 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
944 else
946 /* fill in struct members */
948 if (bpp == 0)
950 if (core_header)
952 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
953 coreheader->bcWidth = bmp->bitmap.bmWidth;
954 coreheader->bcHeight = bmp->bitmap.bmHeight;
955 coreheader->bcPlanes = 1;
956 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
958 else
960 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
961 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
962 info->bmiHeader.biPlanes = 1;
963 info->bmiHeader.biSizeImage =
964 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
965 bmp->bitmap.bmHeight,
966 bmp->bitmap.bmBitsPixel );
967 switch(bmp->bitmap.bmBitsPixel)
969 case 15:
970 info->bmiHeader.biBitCount = 16;
971 info->bmiHeader.biCompression = BI_RGB;
972 break;
974 case 16:
975 info->bmiHeader.biBitCount = 16;
976 info->bmiHeader.biCompression = BI_BITFIELDS;
977 ((PDWORD)info->bmiColors)[0] = 0xf800;
978 ((PDWORD)info->bmiColors)[1] = 0x07e0;
979 ((PDWORD)info->bmiColors)[2] = 0x001f;
980 break;
982 default:
983 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
984 info->bmiHeader.biCompression = BI_RGB;
985 break;
987 info->bmiHeader.biXPelsPerMeter = 0;
988 info->bmiHeader.biYPelsPerMeter = 0;
989 info->bmiHeader.biClrUsed = 0;
990 info->bmiHeader.biClrImportant = 0;
992 /* Windows 2000 doesn't touch the additional struct members if
993 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
995 lines = abs(bmp->bitmap.bmHeight);
997 else
999 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1000 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1001 filled in. */
1002 if (!core_header)
1004 /* FIXME: biSizeImage should be calculated according to the selected
1005 compression algorithm if biCompression != BI_RGB */
1006 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
1008 lines = abs(height);
1012 if (!core_header)
1014 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
1016 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
1018 GDI_ReleaseObj( hdc );
1019 GDI_ReleaseObj( hbitmap );
1020 DeleteDC(memdc);
1021 return lines;
1025 /***********************************************************************
1026 * CreateDIBitmap (GDI32.@)
1028 * Creates a DDB (device dependent bitmap) from a DIB.
1029 * The DDB will have the same color depth as the reference DC.
1031 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1032 DWORD init, LPCVOID bits, const BITMAPINFO *data,
1033 UINT coloruse )
1035 HBITMAP handle;
1036 LONG width;
1037 LONG height;
1038 WORD planes, bpp;
1039 DWORD compr, size;
1040 DC *dc;
1042 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
1044 if (width < 0)
1046 TRACE("Bitmap has a negative width\n");
1047 return 0;
1050 /* Top-down DIBs have a negative height */
1051 if (height < 0) height = -height;
1053 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
1054 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1056 if (hdc == NULL)
1057 handle = CreateBitmap( width, height, 1, 1, NULL );
1058 else
1059 handle = CreateCompatibleBitmap( hdc, width, height );
1061 if (handle)
1063 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1065 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1067 if (!BITMAP_SetOwnerDC( handle, dc ))
1069 DeleteObject( handle );
1070 handle = 0;
1072 GDI_ReleaseObj( hdc );
1076 return handle;
1079 /***********************************************************************
1080 * CreateDIBSection (GDI.489)
1082 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1083 SEGPTR *bits16, HANDLE section, DWORD offset)
1085 LPVOID bits32;
1086 HBITMAP hbitmap;
1088 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1089 if (hbitmap)
1091 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1092 if (bmp && bmp->dib && bits32)
1094 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1095 LONG width, height;
1096 WORD planes, bpp;
1097 DWORD compr, size;
1098 INT width_bytes;
1099 WORD count, sel;
1100 int i;
1102 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
1104 height = height >= 0 ? height : -height;
1105 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1107 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
1109 /* calculate number of sel's needed for size with 64K steps */
1110 count = (size + 0xffff) / 0x10000;
1111 sel = AllocSelectorArray16(count);
1113 for (i = 0; i < count; i++)
1115 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1116 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1117 size -= 0x10000;
1119 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1120 if (bits16) *bits16 = bmp->segptr_bits;
1122 if (bmp) GDI_ReleaseObj( hbitmap );
1124 return HBITMAP_16(hbitmap);
1127 /***********************************************************************
1128 * DIB_CreateDIBSection
1130 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1131 VOID **bits, HANDLE section,
1132 DWORD offset, DWORD ovr_pitch)
1134 HBITMAP ret = 0;
1135 DC *dc;
1136 BOOL bDesktopDC = FALSE;
1137 DIBSECTION *dib;
1138 BITMAPOBJ *bmp;
1139 int bitmap_type;
1140 LONG width, height;
1141 WORD planes, bpp;
1142 DWORD compression, sizeImage;
1143 void *mapBits = NULL;
1145 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1146 &planes, &bpp, &compression, &sizeImage )) == -1))
1147 return 0;
1149 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1151 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, %s\n",
1152 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1154 dib->dsBm.bmType = 0;
1155 dib->dsBm.bmWidth = width;
1156 dib->dsBm.bmHeight = height >= 0 ? height : -height;
1157 dib->dsBm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(width, bpp);
1158 dib->dsBm.bmPlanes = planes;
1159 dib->dsBm.bmBitsPixel = bpp;
1160 dib->dsBm.bmBits = NULL;
1162 if (!bitmap_type) /* core header */
1164 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1165 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1166 dib->dsBmih.biWidth = width;
1167 dib->dsBmih.biHeight = height;
1168 dib->dsBmih.biPlanes = planes;
1169 dib->dsBmih.biBitCount = bpp;
1170 dib->dsBmih.biCompression = compression;
1171 dib->dsBmih.biXPelsPerMeter = 0;
1172 dib->dsBmih.biYPelsPerMeter = 0;
1173 dib->dsBmih.biClrUsed = 0;
1174 dib->dsBmih.biClrImportant = 0;
1176 else
1178 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1179 dib->dsBmih = bmi->bmiHeader;
1180 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1183 /* set number of entries in bmi.bmiColors table */
1184 if( bpp <= 8 )
1185 dib->dsBmih.biClrUsed = 1 << bpp;
1187 /* only use sizeImage if it's valid and we're dealing with a compressed bitmap */
1188 if (sizeImage && (compression == BI_RLE4 || compression == BI_RLE8))
1189 dib->dsBmih.biSizeImage = sizeImage;
1190 else
1191 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
1194 /* set dsBitfields values */
1195 if (usage == DIB_PAL_COLORS || bpp <= 8)
1197 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1199 else switch( bpp )
1201 case 15:
1202 case 16:
1203 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1204 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1205 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
1206 break;
1207 case 24:
1208 case 32:
1209 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1210 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1211 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
1212 break;
1215 /* get storage location for DIB bits */
1217 if (section)
1219 SYSTEM_INFO SystemInfo;
1220 DWORD mapOffset;
1221 INT mapSize;
1223 GetSystemInfo( &SystemInfo );
1224 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1225 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1226 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1227 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1229 else if (ovr_pitch && offset)
1230 dib->dsBm.bmBits = (LPVOID) offset;
1231 else
1233 offset = 0;
1234 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1235 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1237 dib->dshSection = section;
1238 dib->dsOffset = offset;
1240 if (!dib->dsBm.bmBits)
1242 HeapFree( GetProcessHeap(), 0, dib );
1243 return 0;
1246 /* If the reference hdc is null, take the desktop dc */
1247 if (hdc == 0)
1249 hdc = CreateCompatibleDC(0);
1250 bDesktopDC = TRUE;
1253 if (!(dc = DC_GetDCPtr( hdc ))) goto error;
1255 /* create Device Dependent Bitmap and add DIB pointer */
1256 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1257 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1259 if (ret && ((bmp = GDI_GetObjPtr(ret, BITMAP_MAGIC))))
1261 bmp->dib = dib;
1262 bmp->funcs = dc->funcs;
1263 GDI_ReleaseObj( ret );
1265 if (dc->funcs->pCreateDIBSection)
1267 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1269 DeleteObject( ret );
1270 ret = 0;
1275 GDI_ReleaseObj(hdc);
1276 if (bDesktopDC) DeleteDC( hdc );
1277 if (ret && bits) *bits = dib->dsBm.bmBits;
1278 return ret;
1280 error:
1281 if (bDesktopDC) DeleteDC( hdc );
1282 if (section) UnmapViewOfFile( mapBits );
1283 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1284 HeapFree( GetProcessHeap(), 0, dib );
1285 return 0;
1288 /***********************************************************************
1289 * CreateDIBSection (GDI32.@)
1291 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1292 VOID **bits, HANDLE section,
1293 DWORD offset)
1295 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);