- Extended support for BITMAPCOREINFO / BITMAPCOREHEADER structures.
[wine/wine-gecko.git] / dlls / gdi / dib.c
blob5edd5a39e2912ada32876b1e7207a1be3d9eb2fb
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 && (info->bmiHeader.biBitCount <= 8))
137 colors = 1 << info->bmiHeader.biBitCount;
138 return sizeof(BITMAPINFOHEADER) + colors *
139 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
144 /***********************************************************************
145 * DIB_GetBitmapInfo
147 * Get the info from a bitmap header.
148 * Return 1 for INFOHEADER, 0 for COREHEADER,
149 * 4 for V4HEADER, 5 for V5HEADER, -1 for error.
151 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
152 LONG *height, WORD *bpp, DWORD *compr )
154 if (header->biSize == sizeof(BITMAPINFOHEADER))
156 *width = header->biWidth;
157 *height = header->biHeight;
158 *bpp = header->biBitCount;
159 *compr = header->biCompression;
160 return 1;
162 if (header->biSize == sizeof(BITMAPCOREHEADER))
164 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
165 *width = core->bcWidth;
166 *height = core->bcHeight;
167 *bpp = core->bcBitCount;
168 *compr = 0;
169 return 0;
171 if (header->biSize == sizeof(BITMAPV4HEADER))
173 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
174 *width = v4hdr->bV4Width;
175 *height = v4hdr->bV4Height;
176 *bpp = v4hdr->bV4BitCount;
177 *compr = v4hdr->bV4V4Compression;
178 return 4;
180 if (header->biSize == sizeof(BITMAPV5HEADER))
182 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
183 *width = v5hdr->bV5Width;
184 *height = v5hdr->bV5Height;
185 *bpp = v5hdr->bV5BitCount;
186 *compr = v5hdr->bV5Compression;
187 return 5;
189 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
190 return -1;
194 /***********************************************************************
195 * StretchDIBits (GDI32.@)
197 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
198 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
199 INT heightSrc, const void *bits,
200 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
202 DC *dc;
204 if (!bits || !info)
205 return 0;
207 dc = DC_GetDCUpdate( hdc );
208 if(!dc) return FALSE;
210 if(dc->funcs->pStretchDIBits)
212 heightSrc = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
213 heightDst, xSrc, ySrc, widthSrc,
214 heightSrc, bits, info, wUsage, dwRop);
215 GDI_ReleaseObj( hdc );
217 else /* use StretchBlt */
219 HBITMAP hBitmap, hOldBitmap;
220 HPALETTE hpal = NULL;
221 HDC hdcMem;
222 LONG height;
223 LONG width;
224 WORD bpp;
225 DWORD compr;
227 if (DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr ) == -1)
229 ERR("Invalid bitmap\n");
230 return 0;
233 if (width < 0)
235 ERR("Bitmap has a negative width\n");
236 return 0;
239 GDI_ReleaseObj( hdc );
240 hdcMem = CreateCompatibleDC( hdc );
241 hBitmap = CreateCompatibleBitmap(hdc, width, height);
242 hOldBitmap = SelectObject( hdcMem, hBitmap );
243 if(wUsage == DIB_PAL_COLORS)
245 hpal = GetCurrentObject(hdc, OBJ_PAL);
246 hpal = SelectPalette(hdcMem, hpal, FALSE);
249 if (info->bmiHeader.biCompression == BI_RLE4 ||
250 info->bmiHeader.biCompression == BI_RLE8) {
252 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
253 * contain all the rectangle described in bmiHeader, but only part of it.
254 * This mean that those undescribed pixels must be left untouched.
255 * So, we first copy on a memory bitmap the current content of the
256 * destination rectangle, blit the DIB bits on top of it - hence leaving
257 * the gaps untouched -, and blitting the rectangle back.
258 * This insure that gaps are untouched on the destination rectangle
259 * Not doing so leads to trashed images (the gaps contain what was on the
260 * memory bitmap => generally black or garbage)
261 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
262 * another speed vs correctness issue. Anyway, if speed is needed, then the
263 * pStretchDIBits function shall be implemented.
264 * ericP (2000/09/09)
267 /* copy existing bitmap from destination dc */
268 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
269 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
270 dwRop );
273 SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
275 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
276 left (negative biHeight) */
277 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
278 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
279 widthSrc, heightSrc, dwRop );
280 if(hpal)
281 SelectPalette(hdcMem, hpal, FALSE);
282 SelectObject( hdcMem, hOldBitmap );
283 DeleteDC( hdcMem );
284 DeleteObject( hBitmap );
286 return heightSrc;
290 /******************************************************************************
291 * SetDIBits [GDI32.@]
293 * Sets pixels in a bitmap using colors from DIB.
295 * PARAMS
296 * hdc [I] Handle to device context
297 * hbitmap [I] Handle to bitmap
298 * startscan [I] Starting scan line
299 * lines [I] Number of scan lines
300 * bits [I] Array of bitmap bits
301 * info [I] Address of structure with data
302 * coloruse [I] Type of color indexes to use
304 * RETURNS
305 * Success: Number of scan lines copied
306 * Failure: 0
308 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
309 UINT lines, LPCVOID bits, const BITMAPINFO *info,
310 UINT coloruse )
312 DC *dc;
313 BITMAPOBJ *bitmap;
314 INT result = 0;
316 if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
318 if (!(dc = DC_GetDCUpdate( hdc )))
320 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
321 GDI_ReleaseObj( hbitmap );
322 return 0;
325 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
327 if (bitmap->funcs && bitmap->funcs->pSetDIBits)
328 result = bitmap->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
329 bits, info, coloruse );
330 else
331 result = lines;
333 done:
334 GDI_ReleaseObj( hdc );
335 GDI_ReleaseObj( hbitmap );
336 return result;
340 /***********************************************************************
341 * SetDIBitsToDevice (GDI32.@)
343 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
344 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
345 UINT lines, LPCVOID bits, const BITMAPINFO *info,
346 UINT coloruse )
348 INT ret;
349 DC *dc;
351 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
353 if(dc->funcs->pSetDIBitsToDevice)
354 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
355 ySrc, startscan, lines, bits,
356 info, coloruse );
357 else {
358 FIXME("unimplemented on hdc %p\n", hdc);
359 ret = 0;
362 GDI_ReleaseObj( hdc );
363 return ret;
366 /***********************************************************************
367 * SetDIBColorTable (GDI32.@)
369 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
371 DC * dc;
372 UINT result = 0;
374 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
376 if (dc->funcs->pSetDIBColorTable)
377 result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
379 GDI_ReleaseObj( hdc );
380 return result;
384 /***********************************************************************
385 * GetDIBColorTable (GDI32.@)
387 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
389 DC * dc;
390 UINT result = 0;
392 if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
394 if (dc->funcs->pGetDIBColorTable)
395 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
397 GDI_ReleaseObj( hdc );
398 return result;
401 /* FIXME the following two structs should be combined with __sysPalTemplate in
402 objects/color.c - this should happen after de-X11-ing both of these
403 files.
404 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
405 and blue - sigh */
407 static RGBQUAD EGAColorsQuads[16] = {
408 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
409 { 0x00, 0x00, 0x00, 0x00 },
410 { 0x00, 0x00, 0x80, 0x00 },
411 { 0x00, 0x80, 0x00, 0x00 },
412 { 0x00, 0x80, 0x80, 0x00 },
413 { 0x80, 0x00, 0x00, 0x00 },
414 { 0x80, 0x00, 0x80, 0x00 },
415 { 0x80, 0x80, 0x00, 0x00 },
416 { 0x80, 0x80, 0x80, 0x00 },
417 { 0xc0, 0xc0, 0xc0, 0x00 },
418 { 0x00, 0x00, 0xff, 0x00 },
419 { 0x00, 0xff, 0x00, 0x00 },
420 { 0x00, 0xff, 0xff, 0x00 },
421 { 0xff, 0x00, 0x00, 0x00 },
422 { 0xff, 0x00, 0xff, 0x00 },
423 { 0xff, 0xff, 0x00, 0x00 },
424 { 0xff, 0xff, 0xff, 0x00 }
427 static RGBTRIPLE EGAColorsTriples[16] = {
428 /* rgbBlue, rgbGreen, rgbRed */
429 { 0x00, 0x00, 0x00 },
430 { 0x00, 0x00, 0x80 },
431 { 0x00, 0x80, 0x00 },
432 { 0x00, 0x80, 0x80 },
433 { 0x80, 0x00, 0x00 },
434 { 0x80, 0x00, 0x80 },
435 { 0x80, 0x80, 0x00 },
436 { 0x80, 0x80, 0x80 },
437 { 0xc0, 0xc0, 0xc0 },
438 { 0x00, 0x00, 0xff },
439 { 0x00, 0xff, 0x00 },
440 { 0x00, 0xff, 0xff },
441 { 0xff, 0x00, 0x00 } ,
442 { 0xff, 0x00, 0xff },
443 { 0xff, 0xff, 0x00 },
444 { 0xff, 0xff, 0xff }
447 static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
448 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
449 { 0x00, 0x00, 0x00, 0x00 },
450 { 0x00, 0x00, 0x80, 0x00 },
451 { 0x00, 0x80, 0x00, 0x00 },
452 { 0x00, 0x80, 0x80, 0x00 },
453 { 0x80, 0x00, 0x00, 0x00 },
454 { 0x80, 0x00, 0x80, 0x00 },
455 { 0x80, 0x80, 0x00, 0x00 },
456 { 0xc0, 0xc0, 0xc0, 0x00 },
457 { 0xc0, 0xdc, 0xc0, 0x00 },
458 { 0xf0, 0xca, 0xa6, 0x00 },
459 { 0xf0, 0xfb, 0xff, 0x00 },
460 { 0xa4, 0xa0, 0xa0, 0x00 },
461 { 0x80, 0x80, 0x80, 0x00 },
462 { 0x00, 0x00, 0xf0, 0x00 },
463 { 0x00, 0xff, 0x00, 0x00 },
464 { 0x00, 0xff, 0xff, 0x00 },
465 { 0xff, 0x00, 0x00, 0x00 },
466 { 0xff, 0x00, 0xff, 0x00 },
467 { 0xff, 0xff, 0x00, 0x00 },
468 { 0xff, 0xff, 0xff, 0x00 }
471 static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
472 /* rgbBlue, rgbGreen, rgbRed */
473 { 0x00, 0x00, 0x00 },
474 { 0x00, 0x00, 0x80 },
475 { 0x00, 0x80, 0x00 },
476 { 0x00, 0x80, 0x80 },
477 { 0x80, 0x00, 0x00 },
478 { 0x80, 0x00, 0x80 },
479 { 0x80, 0x80, 0x00 },
480 { 0xc0, 0xc0, 0xc0 },
481 { 0xc0, 0xdc, 0xc0 },
482 { 0xf0, 0xca, 0xa6 },
483 { 0xf0, 0xfb, 0xff },
484 { 0xa4, 0xa0, 0xa0 },
485 { 0x80, 0x80, 0x80 },
486 { 0x00, 0x00, 0xf0 },
487 { 0x00, 0xff, 0x00 },
488 { 0x00, 0xff, 0xff },
489 { 0xff, 0x00, 0x00 },
490 { 0xff, 0x00, 0xff },
491 { 0xff, 0xff, 0x00 },
492 { 0xff, 0xff, 0xff}
496 /******************************************************************************
497 * GetDIBits [GDI32.@]
499 * Retrieves bits of bitmap and copies to buffer.
501 * RETURNS
502 * Success: Number of scan lines copied from bitmap
503 * Failure: 0
505 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_87eb.asp
507 INT WINAPI GetDIBits(
508 HDC hdc, /* [in] Handle to device context */
509 HBITMAP hbitmap, /* [in] Handle to bitmap */
510 UINT startscan, /* [in] First scan line to set in dest bitmap */
511 UINT lines, /* [in] Number of scan lines to copy */
512 LPVOID bits, /* [out] Address of array for bitmap bits */
513 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
514 UINT coloruse) /* [in] RGB or palette index */
516 DC * dc;
517 BITMAPOBJ * bmp;
518 int i;
519 HDC memdc;
520 int bitmap_type;
521 BOOL core_header;
522 LONG width;
523 LONG height;
524 WORD bpp;
525 DWORD compr;
526 void* colorPtr;
527 RGBTRIPLE* rgbTriples;
528 RGBQUAD* rgbQuads;
530 if (!info) return 0;
532 bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
533 if (bitmap_type == -1)
535 ERR("Invalid bitmap format\n");
536 return 0;
538 core_header = (bitmap_type == 0);
539 memdc = CreateCompatibleDC(hdc);
540 if (!(dc = DC_GetDCUpdate( hdc )))
542 DeleteDC(memdc);
543 return 0;
545 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
547 GDI_ReleaseObj( hdc );
548 DeleteDC(memdc);
549 return 0;
552 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
553 rgbTriples = (RGBTRIPLE *) colorPtr;
554 rgbQuads = (RGBQUAD *) colorPtr;
556 /* Transfer color info */
558 if (bpp <= 8 && bpp > 0)
560 if (!core_header) info->bmiHeader.biClrUsed = 0;
562 /* If the bitmap object already has a dib section at the
563 same color depth then get the color map from it */
564 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
565 if(coloruse == DIB_RGB_COLORS) {
566 HBITMAP oldbm = SelectObject(memdc, hbitmap);
567 unsigned int colors = 1 << bpp;
569 if (core_header)
571 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
572 RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
574 if (buffer)
576 RGBTRIPLE* index = rgbTriples;
577 GetDIBColorTable(memdc, 0, colors, buffer);
579 for (i=0; i < colors; i++, index++)
581 index->rgbtRed = buffer[i].rgbRed;
582 index->rgbtGreen = buffer[i].rgbGreen;
583 index->rgbtBlue = buffer[i].rgbBlue;
586 HeapFree(GetProcessHeap(), 0, buffer);
589 else
591 GetDIBColorTable(memdc, 0, colors, colorPtr);
593 SelectObject(memdc, oldbm);
595 else {
596 WORD *index = colorPtr;
597 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
598 *index = i;
601 else {
602 if(bpp >= bmp->bitmap.bmBitsPixel) {
603 /* Generate the color map from the selected palette */
604 PALETTEENTRY * palEntry;
605 PALETTEOBJ * palette;
606 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
607 GDI_ReleaseObj( hdc );
608 GDI_ReleaseObj( hbitmap );
609 DeleteDC(memdc);
610 return 0;
612 palEntry = palette->logpalette.palPalEntry;
613 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
614 if (coloruse == DIB_RGB_COLORS) {
615 if (core_header)
617 rgbTriples[i].rgbtRed = palEntry->peRed;
618 rgbTriples[i].rgbtGreen = palEntry->peGreen;
619 rgbTriples[i].rgbtBlue = palEntry->peBlue;
621 else
623 rgbQuads[i].rgbRed = palEntry->peRed;
624 rgbQuads[i].rgbGreen = palEntry->peGreen;
625 rgbQuads[i].rgbBlue = palEntry->peBlue;
626 rgbQuads[i].rgbReserved = 0;
629 else ((WORD *)colorPtr)[i] = (WORD)i;
631 GDI_ReleaseObj( dc->hPalette );
632 } else {
633 switch (bpp) {
634 case 1:
635 if (core_header)
637 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
638 rgbTriples[0].rgbtBlue = 0;
639 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
640 rgbTriples[1].rgbtBlue = 0xff;
642 else
644 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
645 rgbQuads[0].rgbBlue = 0;
646 rgbQuads[0].rgbReserved = 0;
647 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
648 rgbQuads[1].rgbBlue = 0xff;
649 rgbQuads[1].rgbReserved = 0;
651 break;
653 case 4:
654 if (core_header)
655 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
656 else
657 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
659 break;
661 case 8:
663 if (core_header)
665 INT r, g, b;
666 RGBTRIPLE *color;
668 memcpy(rgbTriples, DefLogPaletteTriples,
669 10 * sizeof(RGBTRIPLE));
670 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
671 10 * sizeof(RGBTRIPLE));
672 color = rgbTriples + 10;
673 for(r = 0; r <= 5; r++) /* FIXME */
674 for(g = 0; g <= 5; g++)
675 for(b = 0; b <= 5; b++) {
676 color->rgbtRed = (r * 0xff) / 5;
677 color->rgbtGreen = (g * 0xff) / 5;
678 color->rgbtBlue = (b * 0xff) / 5;
679 color++;
682 else
684 INT r, g, b;
685 RGBQUAD *color;
687 memcpy(rgbQuads, DefLogPaletteQuads,
688 10 * sizeof(RGBQUAD));
689 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
690 10 * sizeof(RGBQUAD));
691 color = rgbQuads + 10;
692 for(r = 0; r <= 5; r++) /* FIXME */
693 for(g = 0; g <= 5; g++)
694 for(b = 0; b <= 5; b++) {
695 color->rgbRed = (r * 0xff) / 5;
696 color->rgbGreen = (g * 0xff) / 5;
697 color->rgbBlue = (b * 0xff) / 5;
698 color->rgbReserved = 0;
699 color++;
708 if (bits && lines)
710 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
711 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
713 /*FIXME: Only RGB dibs supported for now */
714 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
715 unsigned int dstwidth = width;
716 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
717 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
718 unsigned int x, y, width, widthb;
720 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
722 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
723 dstwidthb = -dstwidthb;
726 switch( bpp ) {
728 case 15:
729 case 16: /* 16 bpp dstDIB */
731 LPWORD dstbits = (LPWORD)dbits;
732 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
734 /* FIXME: BI_BITFIELDS not supported yet */
736 switch(bmp->dib->dsBm.bmBitsPixel) {
738 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
740 widthb = min(srcwidthb, abs(dstwidthb));
741 /* FIXME: BI_BITFIELDS not supported yet */
742 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
743 memcpy(dbits, sbits, widthb);
745 break;
747 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
749 LPBYTE srcbits = sbits;
751 width = min(srcwidth, dstwidth);
752 for( y = 0; y < lines; y++) {
753 for( x = 0; x < width; x++, srcbits += 3)
754 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
755 (((WORD)srcbits[1] << 2) & gmask) |
756 (((WORD)srcbits[2] << 7) & rmask);
758 dstbits = (LPWORD)(dbits+=dstwidthb);
759 srcbits = (sbits += srcwidthb);
762 break;
764 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
766 LPDWORD srcbits = (LPDWORD)sbits;
767 DWORD val;
769 width = min(srcwidth, dstwidth);
770 for( y = 0; y < lines; y++) {
771 for( x = 0; x < width; x++ ) {
772 val = *srcbits++;
773 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
774 ((val >> 9) & rmask));
776 dstbits = (LPWORD)(dbits+=dstwidthb);
777 srcbits = (LPDWORD)(sbits+=srcwidthb);
780 break;
782 default: /* ? bit bmp -> 16 bit DIB */
783 FIXME("15/16 bit DIB %d bit bitmap\n",
784 bmp->bitmap.bmBitsPixel);
785 break;
788 break;
790 case 24: /* 24 bpp dstDIB */
792 LPBYTE dstbits = dbits;
794 switch(bmp->dib->dsBm.bmBitsPixel) {
796 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
798 LPWORD srcbits = (LPWORD)sbits;
799 WORD val;
801 width = min(srcwidth, dstwidth);
802 /* FIXME: BI_BITFIELDS not supported yet */
803 for( y = 0; y < lines; y++) {
804 for( x = 0; x < width; x++ ) {
805 val = *srcbits++;
806 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
807 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
808 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
810 dstbits = (LPBYTE)(dbits+=dstwidthb);
811 srcbits = (LPWORD)(sbits+=srcwidthb);
814 break;
816 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
818 widthb = min(srcwidthb, abs(dstwidthb));
819 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
820 memcpy(dbits, sbits, widthb);
822 break;
824 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
826 LPBYTE srcbits = (LPBYTE)sbits;
828 width = min(srcwidth, dstwidth);
829 for( y = 0; y < lines; y++) {
830 for( x = 0; x < width; x++, srcbits++ ) {
831 *dstbits++ = *srcbits++;
832 *dstbits++ = *srcbits++;
833 *dstbits++ = *srcbits++;
835 dstbits=(LPBYTE)(dbits+=dstwidthb);
836 srcbits = (LPBYTE)(sbits+=srcwidthb);
839 break;
841 default: /* ? bit bmp -> 24 bit DIB */
842 FIXME("24 bit DIB %d bit bitmap\n",
843 bmp->bitmap.bmBitsPixel);
844 break;
847 break;
849 case 32: /* 32 bpp dstDIB */
851 LPDWORD dstbits = (LPDWORD)dbits;
853 /* FIXME: BI_BITFIELDS not supported yet */
855 switch(bmp->dib->dsBm.bmBitsPixel) {
856 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
858 LPWORD srcbits = (LPWORD)sbits;
859 DWORD val;
861 width = min(srcwidth, dstwidth);
862 /* FIXME: BI_BITFIELDS not supported yet */
863 for( y = 0; y < lines; y++) {
864 for( x = 0; x < width; x++ ) {
865 val = (DWORD)*srcbits++;
866 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
867 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
868 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
870 dstbits=(LPDWORD)(dbits+=dstwidthb);
871 srcbits=(LPWORD)(sbits+=srcwidthb);
874 break;
876 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
878 LPBYTE srcbits = sbits;
880 width = min(srcwidth, dstwidth);
881 for( y = 0; y < lines; y++) {
882 for( x = 0; x < width; x++, srcbits+=3 )
883 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
884 dstbits=(LPDWORD)(dbits+=dstwidthb);
885 srcbits=(sbits+=srcwidthb);
888 break;
890 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
892 widthb = min(srcwidthb, abs(dstwidthb));
893 /* FIXME: BI_BITFIELDS not supported yet */
894 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
895 memcpy(dbits, sbits, widthb);
898 break;
900 default: /* ? bit bmp -> 32 bit DIB */
901 FIXME("32 bit DIB %d bit bitmap\n",
902 bmp->bitmap.bmBitsPixel);
903 break;
906 break;
908 default: /* ? bit DIB */
909 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
910 break;
913 /* Otherwise, get bits from the XImage */
914 else
916 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
917 else
919 if (bmp->funcs && bmp->funcs->pGetDIBits)
920 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
921 lines, bits, info, coloruse );
922 else
923 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
927 else
929 /* fill in struct members */
931 if (bpp == 0)
933 if (core_header)
935 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
936 coreheader->bcWidth = bmp->bitmap.bmWidth;
937 coreheader->bcHeight = bmp->bitmap.bmHeight;
938 coreheader->bcPlanes = 1;
939 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
941 else
943 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
944 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
945 info->bmiHeader.biPlanes = 1;
946 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
947 info->bmiHeader.biSizeImage =
948 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
949 bmp->bitmap.bmHeight,
950 bmp->bitmap.bmBitsPixel );
951 info->bmiHeader.biCompression = 0;
953 lines = abs(bmp->bitmap.bmHeight);
957 if (!core_header)
959 TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
961 TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
963 GDI_ReleaseObj( hdc );
964 GDI_ReleaseObj( hbitmap );
965 DeleteDC(memdc);
966 return lines;
970 /***********************************************************************
971 * CreateDIBitmap (GDI32.@)
973 * Creates a DDB (device dependent bitmap) from a DIB.
974 * The DDB will have the same color depth as the reference DC.
976 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
977 DWORD init, LPCVOID bits, const BITMAPINFO *data,
978 UINT coloruse )
980 HBITMAP handle;
981 LONG width;
982 LONG height;
983 WORD bpp;
984 DWORD compr;
985 DC *dc;
987 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
989 if (width < 0)
991 TRACE("Bitmap has a negative width\n");
992 return 0;
995 /* Top-down DIBs have a negative height */
996 if (height < 0) height = -height;
998 TRACE("hdc=%p, header=%p, init=%lu, bits=%p, data=%p, coloruse=%u (bitmap: width=%ld, height=%ld, bpp=%u, compr=%lu)\n",
999 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1001 if (hdc == NULL)
1002 handle = CreateBitmap( width, height, 1, 1, NULL );
1003 else
1004 handle = CreateCompatibleBitmap( hdc, width, height );
1006 if (handle)
1008 if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
1010 else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
1012 if (!BITMAP_SetOwnerDC( handle, dc ))
1014 DeleteObject( handle );
1015 handle = 0;
1017 GDI_ReleaseObj( hdc );
1021 return handle;
1024 /***********************************************************************
1025 * CreateDIBSection (GDI.489)
1027 HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
1028 SEGPTR *bits16, HANDLE section, DWORD offset)
1030 LPVOID bits32;
1031 HBITMAP hbitmap;
1033 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
1034 if (hbitmap)
1036 BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(hbitmap, BITMAP_MAGIC);
1037 if (bmp && bmp->dib && bits32)
1039 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1040 LONG width, height;
1041 WORD bpp;
1042 DWORD compr;
1043 BOOL core_header;
1044 INT width_bytes;
1045 INT size;
1046 WORD count, sel;
1047 int i;
1049 core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
1051 height = height >= 0 ? height : -height;
1052 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
1054 if (core_header)
1056 size = width_bytes * height;
1058 else
1060 size = (bi->biSizeImage && compr != BI_RGB) ?
1061 bi->biSizeImage : width_bytes * height;
1064 /* calculate number of sel's needed for size with 64K steps */
1065 count = (size + 0xffff) / 0x10000;
1066 sel = AllocSelectorArray16(count);
1068 for (i = 0; i < count; i++)
1070 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1071 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1072 size -= 0x10000;
1074 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1075 if (bits16) *bits16 = bmp->segptr_bits;
1077 if (bmp) GDI_ReleaseObj( hbitmap );
1079 return HBITMAP_16(hbitmap);
1082 /***********************************************************************
1083 * DIB_CreateDIBSection
1085 HBITMAP DIB_CreateDIBSection(HDC hdc, const BITMAPINFO *bmi, UINT usage,
1086 VOID **bits, HANDLE section,
1087 DWORD offset, DWORD ovr_pitch)
1089 HBITMAP hbitmap = 0;
1090 DC *dc;
1091 BOOL bDesktopDC = FALSE;
1093 /* If the reference hdc is null, take the desktop dc */
1094 if (hdc == 0)
1096 hdc = CreateCompatibleDC(0);
1097 bDesktopDC = TRUE;
1100 if ((dc = DC_GetDCPtr( hdc )))
1102 if(dc->funcs->pCreateDIBSection)
1103 hbitmap = dc->funcs->pCreateDIBSection(dc->physDev, bmi, usage, bits, section, offset, ovr_pitch);
1104 GDI_ReleaseObj(hdc);
1107 if (bDesktopDC)
1108 DeleteDC(hdc);
1110 return hbitmap;
1113 /***********************************************************************
1114 * CreateDIBSection (GDI32.@)
1116 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1117 VOID **bits, HANDLE section,
1118 DWORD offset)
1120 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);