blob: b19cb9d47b326c8963b17697ce65dd5b7a430052 [file] [log] [blame]
Alexandre Julliard401710d1993-09-04 10:09:32 +00001/*
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00002 * GDI device-independent bitmaps
Alexandre Julliard401710d1993-09-04 10:09:32 +00003 *
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00004 * Copyright 1993,1994 Alexandre Julliard
Huw D M Davies91d16081998-11-06 11:03:00 +00005 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00006 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
Jonathan Ernst360a3f92006-05-18 14:49:52 +020018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000019 */
20
Michael Kaufmann0dd29102004-11-02 05:23:49 +000021/*
22 Important information:
23
24 * Current Windows versions support two different DIB structures:
25
26 - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27 - BITMAPINFO / BITMAPINFOHEADER
28
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.
33
34
35 * The palettes are stored in different formats:
36
37 - BITMAPCOREINFO: Array of RGBTRIPLE
38 - BITMAPINFO: Array of RGBQUAD
39
40
41 * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
42
43 - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
44 - BITMAPV5HEADER: Introduced in Windows 98 / 2000
Michael Kaufmann0f2c2b82005-08-08 18:40:14 +000045
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.
Michael Kaufmann0dd29102004-11-02 05:23:49 +000049
50
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:
54
55 BITMAPINFO* info;
56 void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
57
58
59 * More information:
60 Search for "Bitmap Structures" in MSDN
61*/
62
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000063#include <stdarg.h>
Alexandre Julliard908464d2000-11-01 03:11:12 +000064#include <stdlib.h>
James Juranf4d5fef2001-01-26 20:43:40 +000065#include <string.h>
Alexandre Julliard908464d2000-11-01 03:11:12 +000066
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000067#include "windef.h"
Michael Veksler92ae2191999-05-02 11:39:09 +000068#include "winbase.h"
Michael Stefaniuc28a632a2002-11-21 21:50:04 +000069#include "wownt32.h"
Alexandre Julliard6ec42c02004-01-15 00:35:38 +000070#include "gdi_private.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000071#include "wine/debug.h"
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000072
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000073WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000074
Michael Kaufmann0dd29102004-11-02 05:23:49 +000075
76/*
77 Some of the following helper functions are duplicated in
78 dlls/x11drv/dib.c
79*/
80
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000081/***********************************************************************
82 * DIB_GetDIBWidthBytes
83 *
84 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000085 */
86int DIB_GetDIBWidthBytes( int width, int depth )
Alexandre Julliard234bc241994-12-10 13:02:28 +000087{
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000088 int words;
89
90 switch(depth)
91 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000092 case 1: words = (width + 31) / 32; break;
93 case 4: words = (width + 7) / 8; break;
94 case 8: words = (width + 3) / 4; break;
95 case 15:
96 case 16: words = (width + 1) / 2; break;
97 case 24: words = (width * 3 + 3)/4; break;
98
99 default:
Alexandre Julliard15657091999-05-23 10:25:25 +0000100 WARN("(%d): Unsupported depth\n", depth );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000101 /* fall through */
102 case 32:
103 words = width;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000104 }
105 return 4 * words;
Alexandre Julliard234bc241994-12-10 13:02:28 +0000106}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000107
Huw D M Davies608629b1999-04-18 12:07:00 +0000108/***********************************************************************
109 * DIB_GetDIBImageBytes
110 *
111 * Return the number of bytes used to hold the image in a DIB bitmap.
112 */
113int DIB_GetDIBImageBytes( int width, int height, int depth )
114{
115 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
116}
117
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000118
Alexandre Julliard401710d1993-09-04 10:09:32 +0000119/***********************************************************************
Huw Davies515b40c2008-05-02 12:35:40 +0100120 * bitmap_info_size
Alexandre Julliard401710d1993-09-04 10:09:32 +0000121 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000122 * Return the size of the bitmap info structure including color table.
Alexandre Julliard401710d1993-09-04 10:09:32 +0000123 */
Huw Davies515b40c2008-05-02 12:35:40 +0100124int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000125{
Alexandre Julliard162d95a2010-05-14 17:17:46 +0200126 unsigned int colors, size, masks = 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000127
128 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
129 {
Andrew Talbot6d070ea2006-09-14 00:58:30 +0100130 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000131 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000132 return sizeof(BITMAPCOREHEADER) + colors *
133 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
134 }
135 else /* assume BITMAPINFOHEADER */
136 {
137 colors = info->bmiHeader.biClrUsed;
Marcus Meissnera34c2342005-02-14 11:08:22 +0000138 if (colors > 256) colors = 256;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000139 if (!colors && (info->bmiHeader.biBitCount <= 8))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000140 colors = 1 << info->bmiHeader.biBitCount;
Huw Davies515b40c2008-05-02 12:35:40 +0100141 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
Alexandre Julliard162d95a2010-05-14 17:17:46 +0200142 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
143 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000144 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000145}
146
147
148/***********************************************************************
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000149 * DIB_GetBitmapInfo
150 *
151 * Get the info from a bitmap header.
Dmitry Timoshkov2a81c1a2007-06-13 19:18:55 +0900152 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000153 */
Rob Shearmanccce11d2009-02-18 20:34:00 +0000154int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
155 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000156{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000157 if (header->biSize == sizeof(BITMAPCOREHEADER))
158 {
Andrew Talbot6d070ea2006-09-14 00:58:30 +0100159 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000160 *width = core->bcWidth;
161 *height = core->bcHeight;
Alexandre Julliard95914662005-04-13 14:45:27 +0000162 *planes = core->bcPlanes;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000163 *bpp = core->bcBitCount;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000164 *compr = 0;
Alexandre Julliard95914662005-04-13 14:45:27 +0000165 *size = 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000166 return 0;
167 }
Dmitry Timoshkov2a81c1a2007-06-13 19:18:55 +0900168 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
Andreas Mohr1d8ef192001-08-03 18:11:23 +0000169 {
Dmitry Timoshkov2a81c1a2007-06-13 19:18:55 +0900170 *width = header->biWidth;
171 *height = header->biHeight;
172 *planes = header->biPlanes;
173 *bpp = header->biBitCount;
174 *compr = header->biCompression;
175 *size = header->biSizeImage;
176 return 1;
Andreas Mohr1d8ef192001-08-03 18:11:23 +0000177 }
Michael Stefaniuca0b260e2006-10-12 22:56:56 +0200178 ERR("(%d): unknown/wrong size for header\n", header->biSize );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000179 return -1;
180}
181
182
183/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000184 * StretchDIBits (GDI32.@)
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000185 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000186INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
187 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
188 INT heightSrc, const void *bits,
189 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000190{
Steve Lustbader473d6cb2002-11-25 01:10:04 +0000191 DC *dc;
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100192 INT ret;
Alexandre Julliardded30381995-07-06 17:18:27 +0000193
Steve Lustbader473d6cb2002-11-25 01:10:04 +0000194 if (!bits || !info)
195 return 0;
196
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100197 if (!(dc = get_dc_ptr( hdc ))) return 0;
Huw Davies352b8bc2003-11-12 22:42:26 +0000198
Huw D M Davies14c99d01998-10-24 10:44:05 +0000199 if(dc->funcs->pStretchDIBits)
Alexandre Julliard658cdb42001-08-15 23:33:20 +0000200 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200201 update_dc( dc );
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100202 ret = dc->funcs->pStretchDIBits(dc->physDev, xDst, yDst, widthDst,
203 heightDst, xSrc, ySrc, widthSrc,
204 heightSrc, bits, info, wUsage, dwRop);
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200205 release_dc_ptr( dc );
Alexandre Julliard658cdb42001-08-15 23:33:20 +0000206 }
207 else /* use StretchBlt */
208 {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000209 LONG height;
210 LONG width;
Alexandre Julliard95914662005-04-13 14:45:27 +0000211 WORD planes, bpp;
212 DWORD compr, size;
Rob Shearman582de7b2008-02-21 16:44:52 +0000213 HBITMAP hBitmap;
214 BOOL fastpath = FALSE;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000215
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200216 release_dc_ptr( dc );
Juan Lang31acf7f2005-07-14 10:15:42 +0000217
Alexandre Julliard95914662005-04-13 14:45:27 +0000218 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000219 {
220 ERR("Invalid bitmap\n");
221 return 0;
222 }
223
224 if (width < 0)
225 {
226 ERR("Bitmap has a negative width\n");
227 return 0;
228 }
Matthew J. Francised744e71999-10-24 17:28:23 +0000229
Rob Shearman582de7b2008-02-21 16:44:52 +0000230 hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
231
232 if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
233 widthDst == widthSrc && heightDst == heightSrc &&
234 info->bmiHeader.biCompression == BI_RGB &&
235 dwRop == SRCCOPY)
Huw Davies89b60802004-03-27 01:36:47 +0000236 {
Rob Shearman582de7b2008-02-21 16:44:52 +0000237 BITMAPOBJ *bmp;
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100238 if ((bmp = GDI_GetObjPtr( hBitmap, OBJ_BITMAP )))
Rob Shearman582de7b2008-02-21 16:44:52 +0000239 {
240 if (bmp->bitmap.bmBitsPixel == bpp &&
241 bmp->bitmap.bmWidth == widthSrc &&
242 bmp->bitmap.bmHeight == heightSrc &&
243 bmp->bitmap.bmPlanes == planes)
244 fastpath = TRUE;
245 GDI_ReleaseObj( hBitmap );
246 }
Huw Davies89b60802004-03-27 01:36:47 +0000247 }
Huw Davies352b8bc2003-11-12 22:42:26 +0000248
Rob Shearman582de7b2008-02-21 16:44:52 +0000249 if (fastpath)
250 {
251 /* fast path */
252 TRACE("using fast path\n");
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100253 ret = SetDIBits( hdc, hBitmap, 0, height, bits, info, wUsage);
Huw Davies352b8bc2003-11-12 22:42:26 +0000254 }
Rob Shearman582de7b2008-02-21 16:44:52 +0000255 else
256 {
257 /* slow path - need to use StretchBlt */
258 HBITMAP hOldBitmap;
259 HPALETTE hpal = NULL;
260 HDC hdcMem;
Vincent Béron9a624912002-05-31 23:06:46 +0000261
Rob Shearman582de7b2008-02-21 16:44:52 +0000262 hdcMem = CreateCompatibleDC( hdc );
263 hBitmap = CreateCompatibleBitmap(hdc, width, height);
264 hOldBitmap = SelectObject( hdcMem, hBitmap );
265 if(wUsage == DIB_PAL_COLORS)
266 {
267 hpal = GetCurrentObject(hdc, OBJ_PAL);
268 hpal = SelectPalette(hdcMem, hpal, FALSE);
269 }
Eric Pouech26501592000-09-10 03:13:41 +0000270
Rob Shearman582de7b2008-02-21 16:44:52 +0000271 if (info->bmiHeader.biCompression == BI_RLE4 ||
272 info->bmiHeader.biCompression == BI_RLE8) {
273
274 /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
275 * contain all the rectangle described in bmiHeader, but only part of it.
276 * This mean that those undescribed pixels must be left untouched.
277 * So, we first copy on a memory bitmap the current content of the
278 * destination rectangle, blit the DIB bits on top of it - hence leaving
279 * the gaps untouched -, and blitting the rectangle back.
280 * This insure that gaps are untouched on the destination rectangle
281 * Not doing so leads to trashed images (the gaps contain what was on the
282 * memory bitmap => generally black or garbage)
283 * Unfortunately, RLE DIBs without gaps will be slowed down. But this is
284 * another speed vs correctness issue. Anyway, if speed is needed, then the
285 * pStretchDIBits function shall be implemented.
286 * ericP (2000/09/09)
287 */
288
289 /* copy existing bitmap from destination dc */
290 StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
291 widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
292 dwRop );
293 }
294
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100295 ret = SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
Rob Shearman582de7b2008-02-21 16:44:52 +0000296
297 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
298 left (negative biHeight) */
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100299 if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
300 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
301 widthSrc, heightSrc, dwRop );
Rob Shearman582de7b2008-02-21 16:44:52 +0000302 if(hpal)
303 SelectPalette(hdcMem, hpal, FALSE);
304 SelectObject( hdcMem, hOldBitmap );
305 DeleteDC( hdcMem );
306 DeleteObject( hBitmap );
307 }
Huw D M Davies14c99d01998-10-24 10:44:05 +0000308 }
Alexandre Julliard6e387f32008-03-26 20:51:58 +0100309 return ret;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000310}
311
Alexandre Julliard54e47751999-10-13 16:16:23 +0000312
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000313/******************************************************************************
Jon Griffiths783a3952004-02-09 20:47:42 +0000314 * SetDIBits [GDI32.@]
315 *
316 * Sets pixels in a bitmap using colors from DIB.
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000317 *
318 * PARAMS
319 * hdc [I] Handle to device context
320 * hbitmap [I] Handle to bitmap
321 * startscan [I] Starting scan line
322 * lines [I] Number of scan lines
323 * bits [I] Array of bitmap bits
324 * info [I] Address of structure with data
325 * coloruse [I] Type of color indexes to use
326 *
327 * RETURNS
328 * Success: Number of scan lines copied
329 * Failure: 0
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000330 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000331INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000332 UINT lines, LPCVOID bits, const BITMAPINFO *info,
333 UINT coloruse )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000334{
Nikolay Sivov352e2ff2010-04-12 13:00:45 +0400335 DC *dc = get_dc_ptr( hdc );
336 BOOL delete_hdc = FALSE;
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000337 BITMAPOBJ *bitmap;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000338 INT result = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000339
Nikolay Sivov352e2ff2010-04-12 13:00:45 +0400340 if (coloruse == DIB_RGB_COLORS && !dc)
341 {
342 hdc = CreateCompatibleDC(0);
343 dc = get_dc_ptr( hdc );
344 delete_hdc = TRUE;
345 }
Nikolay Sivov28548842009-10-22 13:15:30 +0400346
Nikolay Sivov352e2ff2010-04-12 13:00:45 +0400347 if (!dc) return 0;
Huw Davies8e34fa62005-02-22 19:34:33 +0000348
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200349 update_dc( dc );
350
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100351 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
Huw Davies8e34fa62005-02-22 19:34:33 +0000352 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200353 release_dc_ptr( dc );
Nikolay Sivov352e2ff2010-04-12 13:00:45 +0400354 if (delete_hdc) DeleteDC(hdc);
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000355 return 0;
356 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000357
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000358 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
359
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200360 result = lines;
361 if (bitmap->funcs)
362 {
363 if (bitmap->funcs != dc->funcs)
364 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
365 else if (dc->funcs->pSetDIBits)
366 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000367 bits, info, coloruse );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200368 }
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000369
370 done:
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000371 GDI_ReleaseObj( hbitmap );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200372 release_dc_ptr( dc );
Nikolay Sivov352e2ff2010-04-12 13:00:45 +0400373 if (delete_hdc) DeleteDC(hdc);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000374 return result;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000375}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000376
Alexandre Julliard401710d1993-09-04 10:09:32 +0000377
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000378/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000379 * SetDIBitsToDevice (GDI32.@)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000380 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000381INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
382 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
383 UINT lines, LPCVOID bits, const BITMAPINFO *info,
384 UINT coloruse )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000385{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000386 INT ret;
Huw D M Davies91d16081998-11-06 11:03:00 +0000387 DC *dc;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000388
Louis Lendersd7117282007-05-07 21:03:16 +0100389 if (!bits) return 0;
390
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200391 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000392
Huw D M Davies91d16081998-11-06 11:03:00 +0000393 if(dc->funcs->pSetDIBitsToDevice)
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200394 {
395 update_dc( dc );
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000396 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
Huw D M Davies91d16081998-11-06 11:03:00 +0000397 ySrc, startscan, lines, bits,
398 info, coloruse );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200399 }
Huw D M Davies91d16081998-11-06 11:03:00 +0000400 else {
Alexandre Julliard547cdc22002-11-22 22:16:53 +0000401 FIXME("unimplemented on hdc %p\n", hdc);
Huw D M Davies91d16081998-11-06 11:03:00 +0000402 ret = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000403 }
Alexandre Julliard642d3131998-07-12 19:29:36 +0000404
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200405 release_dc_ptr( dc );
Huw D M Davies91d16081998-11-06 11:03:00 +0000406 return ret;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000407}
408
Alexandre Julliarde658d821997-11-30 17:45:40 +0000409/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000410 * SetDIBColorTable (GDI32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000411 */
Robert Shearmanb4eee492004-10-18 19:35:50 +0000412UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
Alexandre Julliarde658d821997-11-30 17:45:40 +0000413{
414 DC * dc;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000415 UINT result = 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100416 BITMAPOBJ * bitmap;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000417
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100418 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100419
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100420 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100421 {
422 /* Check if currently selected bitmap is a DIB */
423 if (bitmap->color_table)
424 {
425 if (startpos < bitmap->nb_colors)
426 {
427 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
428 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
429 result = entries;
430 }
431 }
432 GDI_ReleaseObj( dc->hBitmap );
433 }
Alexandre Julliarde658d821997-11-30 17:45:40 +0000434
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000435 if (dc->funcs->pSetDIBColorTable)
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100436 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000437
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100438 release_dc_ptr( dc );
Ove Kaavena32ddc02000-11-25 21:42:00 +0000439 return result;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000440}
441
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000442
443/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000444 * GetDIBColorTable (GDI32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000445 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000446UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
Alexandre Julliarde658d821997-11-30 17:45:40 +0000447{
448 DC * dc;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000449 UINT result = 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000450
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100451 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000452
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000453 if (dc->funcs->pGetDIBColorTable)
454 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100455 else
456 {
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100457 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100458 if (bitmap)
459 {
460 /* Check if currently selected bitmap is a DIB */
461 if (bitmap->color_table)
462 {
463 if (startpos < bitmap->nb_colors)
464 {
465 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
466 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
467 result = entries;
468 }
469 }
470 GDI_ReleaseObj( dc->hBitmap );
471 }
472 }
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100473 release_dc_ptr( dc );
Ove Kaavena32ddc02000-11-25 21:42:00 +0000474 return result;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000475}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000476
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000477/* FIXME the following two structs should be combined with __sysPalTemplate in
478 objects/color.c - this should happen after de-X11-ing both of these
479 files.
Andreas Mohrf32f9182001-04-20 18:36:05 +0000480 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000481 and blue - sigh */
482
Andrew Ziem122b8002006-05-24 07:58:57 -0600483static const RGBQUAD EGAColorsQuads[16] = {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000484/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000485 { 0x00, 0x00, 0x00, 0x00 },
486 { 0x00, 0x00, 0x80, 0x00 },
487 { 0x00, 0x80, 0x00, 0x00 },
488 { 0x00, 0x80, 0x80, 0x00 },
489 { 0x80, 0x00, 0x00, 0x00 },
490 { 0x80, 0x00, 0x80, 0x00 },
491 { 0x80, 0x80, 0x00, 0x00 },
492 { 0x80, 0x80, 0x80, 0x00 },
493 { 0xc0, 0xc0, 0xc0, 0x00 },
494 { 0x00, 0x00, 0xff, 0x00 },
495 { 0x00, 0xff, 0x00, 0x00 },
496 { 0x00, 0xff, 0xff, 0x00 },
497 { 0xff, 0x00, 0x00, 0x00 },
498 { 0xff, 0x00, 0xff, 0x00 },
499 { 0xff, 0xff, 0x00, 0x00 },
500 { 0xff, 0xff, 0xff, 0x00 }
501};
502
Andrew Ziem122b8002006-05-24 07:58:57 -0600503static const RGBTRIPLE EGAColorsTriples[16] = {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000504/* rgbBlue, rgbGreen, rgbRed */
505 { 0x00, 0x00, 0x00 },
506 { 0x00, 0x00, 0x80 },
507 { 0x00, 0x80, 0x00 },
508 { 0x00, 0x80, 0x80 },
509 { 0x80, 0x00, 0x00 },
510 { 0x80, 0x00, 0x80 },
511 { 0x80, 0x80, 0x00 },
512 { 0x80, 0x80, 0x80 },
513 { 0xc0, 0xc0, 0xc0 },
514 { 0x00, 0x00, 0xff },
515 { 0x00, 0xff, 0x00 },
516 { 0x00, 0xff, 0xff },
517 { 0xff, 0x00, 0x00 } ,
518 { 0xff, 0x00, 0xff },
519 { 0xff, 0xff, 0x00 },
520 { 0xff, 0xff, 0xff }
521};
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000522
Andrew Ziem122b8002006-05-24 07:58:57 -0600523static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000524/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000525 { 0x00, 0x00, 0x00, 0x00 },
526 { 0x00, 0x00, 0x80, 0x00 },
527 { 0x00, 0x80, 0x00, 0x00 },
528 { 0x00, 0x80, 0x80, 0x00 },
529 { 0x80, 0x00, 0x00, 0x00 },
530 { 0x80, 0x00, 0x80, 0x00 },
531 { 0x80, 0x80, 0x00, 0x00 },
532 { 0xc0, 0xc0, 0xc0, 0x00 },
533 { 0xc0, 0xdc, 0xc0, 0x00 },
534 { 0xf0, 0xca, 0xa6, 0x00 },
535 { 0xf0, 0xfb, 0xff, 0x00 },
536 { 0xa4, 0xa0, 0xa0, 0x00 },
537 { 0x80, 0x80, 0x80, 0x00 },
538 { 0x00, 0x00, 0xf0, 0x00 },
539 { 0x00, 0xff, 0x00, 0x00 },
540 { 0x00, 0xff, 0xff, 0x00 },
541 { 0xff, 0x00, 0x00, 0x00 },
542 { 0xff, 0x00, 0xff, 0x00 },
543 { 0xff, 0xff, 0x00, 0x00 },
544 { 0xff, 0xff, 0xff, 0x00 }
545};
546
Andrew Ziem122b8002006-05-24 07:58:57 -0600547static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000548/* rgbBlue, rgbGreen, rgbRed */
549 { 0x00, 0x00, 0x00 },
550 { 0x00, 0x00, 0x80 },
551 { 0x00, 0x80, 0x00 },
552 { 0x00, 0x80, 0x80 },
553 { 0x80, 0x00, 0x00 },
554 { 0x80, 0x00, 0x80 },
555 { 0x80, 0x80, 0x00 },
556 { 0xc0, 0xc0, 0xc0 },
557 { 0xc0, 0xdc, 0xc0 },
558 { 0xf0, 0xca, 0xa6 },
559 { 0xf0, 0xfb, 0xff },
560 { 0xa4, 0xa0, 0xa0 },
561 { 0x80, 0x80, 0x80 },
562 { 0x00, 0x00, 0xf0 },
563 { 0x00, 0xff, 0x00 },
564 { 0x00, 0xff, 0xff },
565 { 0xff, 0x00, 0x00 },
566 { 0xff, 0x00, 0xff },
567 { 0xff, 0xff, 0x00 },
568 { 0xff, 0xff, 0xff}
569};
570
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000571
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000572/******************************************************************************
Jon Griffiths783a3952004-02-09 20:47:42 +0000573 * GetDIBits [GDI32.@]
574 *
575 * Retrieves bits of bitmap and copies to buffer.
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000576 *
577 * RETURNS
578 * Success: Number of scan lines copied from bitmap
579 * Failure: 0
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000580 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000581INT WINAPI GetDIBits(
582 HDC hdc, /* [in] Handle to device context */
583 HBITMAP hbitmap, /* [in] Handle to bitmap */
584 UINT startscan, /* [in] First scan line to set in dest bitmap */
585 UINT lines, /* [in] Number of scan lines to copy */
Zygo Blaxell1084b2c1999-02-09 14:13:12 +0000586 LPVOID bits, /* [out] Address of array for bitmap bits */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000587 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000588 UINT coloruse) /* [in] RGB or palette index */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000589{
590 DC * dc;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000591 BITMAPOBJ * bmp;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000592 int i;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000593 int bitmap_type;
594 BOOL core_header;
595 LONG width;
596 LONG height;
Alexandre Julliard95914662005-04-13 14:45:27 +0000597 WORD planes, bpp;
598 DWORD compr, size;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000599 void* colorPtr;
600 RGBTRIPLE* rgbTriples;
601 RGBQUAD* rgbQuads;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000602
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000603 if (!info) return 0;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000604
Alexandre Julliard95914662005-04-13 14:45:27 +0000605 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000606 if (bitmap_type == -1)
607 {
608 ERR("Invalid bitmap format\n");
609 return 0;
610 }
611 core_header = (bitmap_type == 0);
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200612 if (!(dc = get_dc_ptr( hdc )))
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000613 {
Dmitry Timoshkovf31b67a2007-01-22 18:31:02 +0800614 SetLastError( ERROR_INVALID_PARAMETER );
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000615 return 0;
616 }
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200617 update_dc( dc );
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100618 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000619 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200620 release_dc_ptr( dc );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000621 return 0;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000622 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000623
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000624 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
Michael Stefaniuc667a1ed2009-01-26 11:01:12 +0100625 rgbTriples = colorPtr;
626 rgbQuads = colorPtr;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000627
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000628 /* Transfer color info */
629
Alexandre Julliard99892d62008-04-18 12:08:12 +0200630 switch (bpp)
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000631 {
Alexandre Julliard99892d62008-04-18 12:08:12 +0200632 case 0: /* query bitmap info only */
633 if (core_header)
634 {
635 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
636 coreheader->bcWidth = bmp->bitmap.bmWidth;
637 coreheader->bcHeight = bmp->bitmap.bmHeight;
638 coreheader->bcPlanes = 1;
639 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
640 }
641 else
642 {
643 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
644 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
645 info->bmiHeader.biPlanes = 1;
646 info->bmiHeader.biSizeImage =
647 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
648 bmp->bitmap.bmHeight,
649 bmp->bitmap.bmBitsPixel );
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200650 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200651 switch(bmp->bitmap.bmBitsPixel)
652 {
653 case 15:
654 info->bmiHeader.biBitCount = 16;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200655 break;
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200656 case 24:
657 info->bmiHeader.biBitCount = 32;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200658 break;
659 default:
660 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200661 break;
662 }
663 info->bmiHeader.biXPelsPerMeter = 0;
664 info->bmiHeader.biYPelsPerMeter = 0;
665 info->bmiHeader.biClrUsed = 0;
666 info->bmiHeader.biClrImportant = 0;
667
668 /* Windows 2000 doesn't touch the additional struct members if
669 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
670 }
671 lines = abs(bmp->bitmap.bmHeight);
672 goto done;
673
674 case 1:
675 case 4:
676 case 8:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000677 if (!core_header) info->bmiHeader.biClrUsed = 0;
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000678
Dave Belanger4db092c2003-10-11 05:23:45 +0000679 /* If the bitmap object already has a dib section at the
680 same color depth then get the color map from it */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000681 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000682 if(coloruse == DIB_RGB_COLORS) {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100683 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000684
685 if (core_header)
686 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100687 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
688 RGBTRIPLE* index = rgbTriples;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000689
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100690 for (i=0; i < colors; i++, index++)
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000691 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100692 index->rgbtRed = bmp->color_table[i].rgbRed;
693 index->rgbtGreen = bmp->color_table[i].rgbGreen;
694 index->rgbtBlue = bmp->color_table[i].rgbBlue;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000695 }
696 }
697 else
698 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100699 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
700 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000701 }
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000702 }
Huw Davies16145172004-03-29 21:39:04 +0000703 else {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000704 WORD *index = colorPtr;
Huw Davies16145172004-03-29 21:39:04 +0000705 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
706 *index = i;
707 }
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000708 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000709 else {
Michael Karcher53339232008-06-08 01:44:10 +0200710 if (coloruse == DIB_PAL_COLORS) {
711 for (i = 0; i < (1 << bpp); i++)
712 ((WORD *)colorPtr)[i] = (WORD)i;
713 }
Michael Karcherfd8746b2008-06-29 13:30:01 +0200714 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
715 /* For color DDBs in native depth (mono DDBs always have
716 a black/white palette):
717 Generate the color map from the selected palette */
Alexandre Julliardc60757b2006-11-17 14:34:20 +0100718 PALETTEENTRY palEntry[256];
719
720 memset( palEntry, 0, sizeof(palEntry) );
721 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
722 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200723 release_dc_ptr( dc );
Dave Belanger4db092c2003-10-11 05:23:45 +0000724 GDI_ReleaseObj( hbitmap );
725 return 0;
726 }
Alexandre Julliardc60757b2006-11-17 14:34:20 +0100727 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
Michael Karcher53339232008-06-08 01:44:10 +0200728 if (core_header)
729 {
730 rgbTriples[i].rgbtRed = palEntry[i].peRed;
731 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
732 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
Dave Belanger4db092c2003-10-11 05:23:45 +0000733 }
Michael Karcher53339232008-06-08 01:44:10 +0200734 else
735 {
736 rgbQuads[i].rgbRed = palEntry[i].peRed;
737 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
738 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
739 rgbQuads[i].rgbReserved = 0;
740 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000741 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000742 } else {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000743 switch (bpp) {
Dave Belanger4db092c2003-10-11 05:23:45 +0000744 case 1:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000745 if (core_header)
746 {
747 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
748 rgbTriples[0].rgbtBlue = 0;
749 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
750 rgbTriples[1].rgbtBlue = 0xff;
751 }
752 else
753 {
754 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
755 rgbQuads[0].rgbBlue = 0;
756 rgbQuads[0].rgbReserved = 0;
757 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
758 rgbQuads[1].rgbBlue = 0xff;
759 rgbQuads[1].rgbReserved = 0;
760 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000761 break;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000762
Dave Belanger4db092c2003-10-11 05:23:45 +0000763 case 4:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000764 if (core_header)
765 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
766 else
767 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
768
Dave Belanger4db092c2003-10-11 05:23:45 +0000769 break;
770
771 case 8:
772 {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000773 if (core_header)
774 {
775 INT r, g, b;
776 RGBTRIPLE *color;
Dave Belanger4db092c2003-10-11 05:23:45 +0000777
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000778 memcpy(rgbTriples, DefLogPaletteTriples,
779 10 * sizeof(RGBTRIPLE));
780 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
781 10 * sizeof(RGBTRIPLE));
782 color = rgbTriples + 10;
783 for(r = 0; r <= 5; r++) /* FIXME */
784 for(g = 0; g <= 5; g++)
785 for(b = 0; b <= 5; b++) {
786 color->rgbtRed = (r * 0xff) / 5;
787 color->rgbtGreen = (g * 0xff) / 5;
788 color->rgbtBlue = (b * 0xff) / 5;
789 color++;
790 }
791 }
792 else
793 {
794 INT r, g, b;
795 RGBQUAD *color;
796
797 memcpy(rgbQuads, DefLogPaletteQuads,
798 10 * sizeof(RGBQUAD));
799 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
800 10 * sizeof(RGBQUAD));
801 color = rgbQuads + 10;
802 for(r = 0; r <= 5; r++) /* FIXME */
803 for(g = 0; g <= 5; g++)
804 for(b = 0; b <= 5; b++) {
805 color->rgbRed = (r * 0xff) / 5;
806 color->rgbGreen = (g * 0xff) / 5;
807 color->rgbBlue = (b * 0xff) / 5;
808 color->rgbReserved = 0;
809 color++;
810 }
811 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000812 }
813 }
814 }
815 }
Alexandre Julliard99892d62008-04-18 12:08:12 +0200816 break;
817
818 case 15:
819 if (info->bmiHeader.biCompression == BI_BITFIELDS)
820 {
821 ((PDWORD)info->bmiColors)[0] = 0x7c00;
822 ((PDWORD)info->bmiColors)[1] = 0x03e0;
823 ((PDWORD)info->bmiColors)[2] = 0x001f;
824 }
825 break;
826
827 case 16:
828 if (info->bmiHeader.biCompression == BI_BITFIELDS)
829 {
830 ((PDWORD)info->bmiColors)[0] = 0xf800;
831 ((PDWORD)info->bmiColors)[1] = 0x07e0;
832 ((PDWORD)info->bmiColors)[2] = 0x001f;
833 }
834 break;
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200835
836 case 24:
837 case 32:
838 if (info->bmiHeader.biCompression == BI_BITFIELDS)
839 {
840 ((PDWORD)info->bmiColors)[0] = 0xff0000;
841 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
842 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
843 }
844 break;
Dave Belanger4db092c2003-10-11 05:23:45 +0000845 }
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000846
Kai Morich9e9fc1b1999-09-13 15:13:24 +0000847 if (bits && lines)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000848 {
Andreas Mohrf32f9182001-04-20 18:36:05 +0000849 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000850 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
Karl Lessard41875791999-09-03 16:49:17 +0000851 {
852 /*FIXME: Only RGB dibs supported for now */
Joerg Mayer4d756402001-01-10 22:45:33 +0000853 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000854 unsigned int dstwidth = width;
855 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
Patrik Stridvall0ee98cc2000-02-26 13:17:55 +0000856 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
Huw Daviesdd8922f2004-08-12 20:02:39 +0000857 unsigned int x, y, width, widthb;
Karl Lessard41875791999-09-03 16:49:17 +0000858
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000859 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
Karl Lessard41875791999-09-03 16:49:17 +0000860 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000861 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
Karl Lessard41875791999-09-03 16:49:17 +0000862 dstwidthb = -dstwidthb;
863 }
864
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000865 switch( bpp ) {
Karl Lessard41875791999-09-03 16:49:17 +0000866
Karl Lessarddee464c1999-09-14 11:51:01 +0000867 case 15:
Karl Lessard41875791999-09-03 16:49:17 +0000868 case 16: /* 16 bpp dstDIB */
869 {
870 LPWORD dstbits = (LPWORD)dbits;
871 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
872
873 /* FIXME: BI_BITFIELDS not supported yet */
874
875 switch(bmp->dib->dsBm.bmBitsPixel) {
876
877 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
878 {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000879 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +0000880 /* FIXME: BI_BITFIELDS not supported yet */
881 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
Huw Daviesdd8922f2004-08-12 20:02:39 +0000882 memcpy(dbits, sbits, widthb);
Karl Lessard41875791999-09-03 16:49:17 +0000883 }
884 break;
885
886 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
887 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000888 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000889
Huw Daviesdd8922f2004-08-12 20:02:39 +0000890 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000891 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000892 for( x = 0; x < width; x++, srcbits += 3)
Marcus Meissner183eae92001-06-14 19:22:55 +0000893 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
894 (((WORD)srcbits[1] << 2) & gmask) |
895 (((WORD)srcbits[2] << 7) & rmask);
896
Karl Lessard41875791999-09-03 16:49:17 +0000897 dstbits = (LPWORD)(dbits+=dstwidthb);
Huw D M Davies1bb98601999-09-19 12:04:17 +0000898 srcbits = (sbits += srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000899 }
900 }
901 break;
902
903 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
904 {
905 LPDWORD srcbits = (LPDWORD)sbits;
906 DWORD val;
907
Huw Daviesdd8922f2004-08-12 20:02:39 +0000908 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000909 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000910 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000911 val = *srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000912 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
913 ((val >> 9) & rmask));
Karl Lessard41875791999-09-03 16:49:17 +0000914 }
Huw D M Davies1bb98601999-09-19 12:04:17 +0000915 dstbits = (LPWORD)(dbits+=dstwidthb);
916 srcbits = (LPDWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000917 }
918 }
919 break;
920
921 default: /* ? bit bmp -> 16 bit DIB */
922 FIXME("15/16 bit DIB %d bit bitmap\n",
923 bmp->bitmap.bmBitsPixel);
924 break;
925 }
926 }
927 break;
928
929 case 24: /* 24 bpp dstDIB */
930 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000931 LPBYTE dstbits = dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000932
933 switch(bmp->dib->dsBm.bmBitsPixel) {
934
935 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
936 {
937 LPWORD srcbits = (LPWORD)sbits;
938 WORD val;
939
Huw Daviesdd8922f2004-08-12 20:02:39 +0000940 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000941 /* FIXME: BI_BITFIELDS not supported yet */
942 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000943 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000944 val = *srcbits++;
Karl Lessard41875791999-09-03 16:49:17 +0000945 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000946 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
947 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
Karl Lessard41875791999-09-03 16:49:17 +0000948 }
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000949 dstbits = dbits+=dstwidthb;
Karl Lessard41875791999-09-03 16:49:17 +0000950 srcbits = (LPWORD)(sbits+=srcwidthb);
951 }
952 }
953 break;
954
955 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
956 {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000957 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +0000958 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
Huw Daviesdd8922f2004-08-12 20:02:39 +0000959 memcpy(dbits, sbits, widthb);
Karl Lessard41875791999-09-03 16:49:17 +0000960 }
961 break;
962
963 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
964 {
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000965 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000966
Huw Daviesdd8922f2004-08-12 20:02:39 +0000967 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000968 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000969 for( x = 0; x < width; x++, srcbits++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000970 *dstbits++ = *srcbits++;
971 *dstbits++ = *srcbits++;
972 *dstbits++ = *srcbits++;
973 }
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000974 dstbits = dbits+=dstwidthb;
975 srcbits = sbits+=srcwidthb;
Karl Lessard41875791999-09-03 16:49:17 +0000976 }
977 }
978 break;
979
980 default: /* ? bit bmp -> 24 bit DIB */
981 FIXME("24 bit DIB %d bit bitmap\n",
982 bmp->bitmap.bmBitsPixel);
983 break;
984 }
985 }
986 break;
987
988 case 32: /* 32 bpp dstDIB */
989 {
990 LPDWORD dstbits = (LPDWORD)dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000991
992 /* FIXME: BI_BITFIELDS not supported yet */
993
994 switch(bmp->dib->dsBm.bmBitsPixel) {
995 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
996 {
997 LPWORD srcbits = (LPWORD)sbits;
998 DWORD val;
999
Huw Daviesdd8922f2004-08-12 20:02:39 +00001000 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +00001001 /* FIXME: BI_BITFIELDS not supported yet */
1002 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +00001003 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +00001004 val = (DWORD)*srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +00001005 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
Karl Lessard41875791999-09-03 16:49:17 +00001006 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
Karl Lessardc73a1fd1999-09-19 14:15:41 +00001007 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
Karl Lessard41875791999-09-03 16:49:17 +00001008 }
Huw D M Davies1bb98601999-09-19 12:04:17 +00001009 dstbits=(LPDWORD)(dbits+=dstwidthb);
1010 srcbits=(LPWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +00001011 }
1012 }
1013 break;
1014
1015 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1016 {
Huw D M Davies1bb98601999-09-19 12:04:17 +00001017 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +00001018
Huw Daviesdd8922f2004-08-12 20:02:39 +00001019 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +00001020 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +00001021 for( x = 0; x < width; x++, srcbits+=3 )
Huw Daviese32932e2005-12-08 13:53:07 +01001022 *dstbits++ = srcbits[0] |
1023 (srcbits[1] << 8) |
1024 (srcbits[2] << 16);
Huw D M Davies1bb98601999-09-19 12:04:17 +00001025 dstbits=(LPDWORD)(dbits+=dstwidthb);
Karl Lessard41875791999-09-03 16:49:17 +00001026 srcbits=(sbits+=srcwidthb);
1027 }
1028 }
1029 break;
1030
Huw Daviesdd8922f2004-08-12 20:02:39 +00001031 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
Karl Lessard41875791999-09-03 16:49:17 +00001032 {
Huw Daviesdd8922f2004-08-12 20:02:39 +00001033 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +00001034 /* FIXME: BI_BITFIELDS not supported yet */
Huw Daviesdd8922f2004-08-12 20:02:39 +00001035 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1036 memcpy(dbits, sbits, widthb);
1037 }
Karl Lessard41875791999-09-03 16:49:17 +00001038 }
1039 break;
1040
Dave Belanger4db092c2003-10-11 05:23:45 +00001041 default: /* ? bit bmp -> 32 bit DIB */
1042 FIXME("32 bit DIB %d bit bitmap\n",
Karl Lessard41875791999-09-03 16:49:17 +00001043 bmp->bitmap.bmBitsPixel);
1044 break;
1045 }
1046 }
1047 break;
1048
1049 default: /* ? bit DIB */
1050 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1051 break;
1052 }
1053 }
1054 /* Otherwise, get bits from the XImage */
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001055 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001056 {
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001057 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1058 else
1059 {
1060 if (bmp->funcs && bmp->funcs->pGetDIBits)
1061 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1062 lines, bits, info, coloruse );
1063 else
1064 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1065 }
1066 }
Alexandre Julliard401710d1993-09-04 10:09:32 +00001067 }
Alexandre Julliard99892d62008-04-18 12:08:12 +02001068 else lines = abs(height);
Huw D M Daviescc3e5d71999-03-25 10:48:01 +00001069
Alexandre Julliard99892d62008-04-18 12:08:12 +02001070 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1071 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1072 filled in. */
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001073 if (!core_header)
1074 {
Alexandre Julliard99892d62008-04-18 12:08:12 +02001075 /* FIXME: biSizeImage should be calculated according to the selected
1076 compression algorithm if biCompression != BI_RGB */
1077 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001078 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001079 }
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001080 TRACE("biWidth = %d, biHeight = %d\n", width, height);
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001081
Alexandre Julliard99892d62008-04-18 12:08:12 +02001082done:
Alexandre Julliardbaa8d222007-09-17 16:48:56 +02001083 release_dc_ptr( dc );
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001084 GDI_ReleaseObj( hbitmap );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001085 return lines;
1086}
1087
1088
1089/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00001090 * CreateDIBitmap (GDI32.@)
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001091 *
1092 * Creates a DDB (device dependent bitmap) from a DIB.
1093 * The DDB will have the same color depth as the reference DC.
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001094 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001095HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001096 DWORD init, LPCVOID bits, const BITMAPINFO *data,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001097 UINT coloruse )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001098{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001099 HBITMAP handle;
Michael Kaufmann970b2212004-09-20 21:45:00 +00001100 LONG width;
1101 LONG height;
Alexandre Julliard95914662005-04-13 14:45:27 +00001102 WORD planes, bpp;
1103 DWORD compr, size;
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001104 DC *dc;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001105
Nikolay Sivov0f9bc1d2009-05-03 12:42:00 +04001106 if (!header) return 0;
1107
Alexandre Julliard95914662005-04-13 14:45:27 +00001108 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
Michael Kaufmann970b2212004-09-20 21:45:00 +00001109
1110 if (width < 0)
1111 {
1112 TRACE("Bitmap has a negative width\n");
1113 return 0;
1114 }
1115
1116 /* Top-down DIBs have a negative height */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001117 if (height < 0) height = -height;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001118
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001119 TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
Michael Kaufmann970b2212004-09-20 21:45:00 +00001120 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1121
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001122 if (hdc == NULL)
1123 handle = CreateBitmap( width, height, 1, 1, NULL );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001124 else
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001125 handle = CreateCompatibleBitmap( hdc, width, height );
Alexandre Julliard946a4442000-07-30 13:50:27 +00001126
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001127 if (handle)
1128 {
Huw Davies37423892009-06-18 15:31:18 +01001129 if (init & CBM_INIT)
Lei Zhangce552d42008-07-18 15:28:44 -07001130 {
1131 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1132 {
1133 DeleteObject( handle );
1134 handle = 0;
1135 }
1136 }
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001137
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001138 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001139 {
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001140 if (!BITMAP_SetOwnerDC( handle, dc ))
1141 {
1142 DeleteObject( handle );
1143 handle = 0;
1144 }
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001145 release_dc_ptr( dc );
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001146 }
1147 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001148
Alexandre Julliard401710d1993-09-04 10:09:32 +00001149 return handle;
1150}
Alexandre Julliard77b99181997-09-14 17:17:23 +00001151
Francois Gouget44b52b12008-01-16 12:20:50 +01001152/* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001153static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1154{
1155 RGBQUAD *colorTable;
Andrew Talbot44be6c72008-10-02 22:18:38 +01001156 unsigned int colors, i;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001157 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1158
1159 if (core_info)
1160 {
1161 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1162 }
1163 else
1164 {
1165 colors = info->bmiHeader.biClrUsed;
1166 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1167 }
1168
1169 if (colors > 256) {
1170 ERR("called with >256 colors!\n");
1171 return;
1172 }
1173
1174 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1175
1176 if(coloruse == DIB_RGB_COLORS)
1177 {
1178 if (core_info)
1179 {
1180 /* Convert RGBTRIPLEs to RGBQUADs */
1181 for (i=0; i < colors; i++)
1182 {
1183 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1184 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1185 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1186 colorTable[i].rgbReserved = 0;
1187 }
1188 }
1189 else
1190 {
1191 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1192 }
1193 }
1194 else
1195 {
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001196 PALETTEENTRY entries[256];
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001197 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001198 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001199
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001200 for (i = 0; i < colors; i++, index++)
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001201 {
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001202 PALETTEENTRY *entry = &entries[*index % count];
1203 colorTable[i].rgbRed = entry->peRed;
1204 colorTable[i].rgbGreen = entry->peGreen;
1205 colorTable[i].rgbBlue = entry->peBlue;
1206 colorTable[i].rgbReserved = 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001207 }
1208 }
1209 bmp->color_table = colorTable;
1210 bmp->nb_colors = colors;
1211}
1212
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001213/***********************************************************************
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001214 * CreateDIBSection (GDI32.@)
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001215 */
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001216HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1217 VOID **bits, HANDLE section, DWORD offset)
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001218{
Alexandre Julliard95914662005-04-13 14:45:27 +00001219 HBITMAP ret = 0;
Stephane Lussier23259ce2000-07-11 22:04:44 +00001220 DC *dc;
1221 BOOL bDesktopDC = FALSE;
Alexandre Julliard95914662005-04-13 14:45:27 +00001222 DIBSECTION *dib;
1223 BITMAPOBJ *bmp;
1224 int bitmap_type;
1225 LONG width, height;
1226 WORD planes, bpp;
1227 DWORD compression, sizeImage;
Alexandre Julliard95914662005-04-13 14:45:27 +00001228 void *mapBits = NULL;
1229
Nikolay Sivov14413112008-05-10 11:14:29 +04001230 if(!bmi){
1231 if(bits) *bits = NULL;
1232 return NULL;
1233 }
1234
Alexandre Julliard95914662005-04-13 14:45:27 +00001235 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1236 &planes, &bpp, &compression, &sizeImage )) == -1))
1237 return 0;
1238
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001239 if (compression != BI_RGB && compression != BI_BITFIELDS)
1240 {
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001241 TRACE("can't create a compressed (%u) dibsection\n", compression);
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001242 return 0;
1243 }
1244
Alexandre Julliard95914662005-04-13 14:45:27 +00001245 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1246
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001247 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
Alexandre Julliard95914662005-04-13 14:45:27 +00001248 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1249
1250 dib->dsBm.bmType = 0;
1251 dib->dsBm.bmWidth = width;
1252 dib->dsBm.bmHeight = height >= 0 ? height : -height;
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001253 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
Alexandre Julliard95914662005-04-13 14:45:27 +00001254 dib->dsBm.bmPlanes = planes;
1255 dib->dsBm.bmBitsPixel = bpp;
1256 dib->dsBm.bmBits = NULL;
1257
1258 if (!bitmap_type) /* core header */
1259 {
1260 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1261 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1262 dib->dsBmih.biWidth = width;
1263 dib->dsBmih.biHeight = height;
1264 dib->dsBmih.biPlanes = planes;
1265 dib->dsBmih.biBitCount = bpp;
1266 dib->dsBmih.biCompression = compression;
1267 dib->dsBmih.biXPelsPerMeter = 0;
1268 dib->dsBmih.biYPelsPerMeter = 0;
1269 dib->dsBmih.biClrUsed = 0;
1270 dib->dsBmih.biClrImportant = 0;
1271 }
1272 else
1273 {
1274 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1275 dib->dsBmih = bmi->bmiHeader;
1276 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1277 }
1278
Peter Beutnerc9e02e12005-11-14 15:10:23 +00001279 /* set number of entries in bmi.bmiColors table */
1280 if( bpp <= 8 )
1281 dib->dsBmih.biClrUsed = 1 << bpp;
1282
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001283 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
Alexandre Julliard95914662005-04-13 14:45:27 +00001284
1285 /* set dsBitfields values */
Alexandre Julliard95914662005-04-13 14:45:27 +00001286 if (usage == DIB_PAL_COLORS || bpp <= 8)
1287 {
1288 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1289 }
1290 else switch( bpp )
1291 {
1292 case 15:
1293 case 16:
Michael Kaufmann0f2c2b82005-08-08 18:40:14 +00001294 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1295 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1296 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
Alexandre Julliard95914662005-04-13 14:45:27 +00001297 break;
1298 case 24:
1299 case 32:
Michael Kaufmann0f2c2b82005-08-08 18:40:14 +00001300 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1301 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1302 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
Alexandre Julliard95914662005-04-13 14:45:27 +00001303 break;
1304 }
1305
1306 /* get storage location for DIB bits */
1307
1308 if (section)
1309 {
1310 SYSTEM_INFO SystemInfo;
1311 DWORD mapOffset;
1312 INT mapSize;
1313
1314 GetSystemInfo( &SystemInfo );
1315 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1316 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1317 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1318 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1319 }
Alexandre Julliard95914662005-04-13 14:45:27 +00001320 else
1321 {
1322 offset = 0;
1323 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1324 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1325 }
1326 dib->dshSection = section;
1327 dib->dsOffset = offset;
1328
1329 if (!dib->dsBm.bmBits)
1330 {
1331 HeapFree( GetProcessHeap(), 0, dib );
1332 return 0;
1333 }
Stephane Lussier23259ce2000-07-11 22:04:44 +00001334
1335 /* If the reference hdc is null, take the desktop dc */
1336 if (hdc == 0)
1337 {
1338 hdc = CreateCompatibleDC(0);
1339 bDesktopDC = TRUE;
1340 }
1341
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001342 if (!(dc = get_dc_ptr( hdc ))) goto error;
Alexandre Julliard95914662005-04-13 14:45:27 +00001343
1344 /* create Device Dependent Bitmap and add DIB pointer */
1345 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1346 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1347
Alexandre Julliard5811a2c2009-01-28 16:20:56 +01001348 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001349 {
Alexandre Julliard95914662005-04-13 14:45:27 +00001350 bmp->dib = dib;
1351 bmp->funcs = dc->funcs;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001352 /* create local copy of DIB palette */
1353 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
Alexandre Julliard95914662005-04-13 14:45:27 +00001354 GDI_ReleaseObj( ret );
1355
1356 if (dc->funcs->pCreateDIBSection)
1357 {
1358 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1359 {
1360 DeleteObject( ret );
1361 ret = 0;
1362 }
1363 }
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001364 }
Ulrich Weigand4f85bad1999-02-09 15:30:22 +00001365
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001366 release_dc_ptr( dc );
Alexandre Julliard95914662005-04-13 14:45:27 +00001367 if (bDesktopDC) DeleteDC( hdc );
1368 if (ret && bits) *bits = dib->dsBm.bmBits;
1369 return ret;
Stephane Lussier23259ce2000-07-11 22:04:44 +00001370
Alexandre Julliard95914662005-04-13 14:45:27 +00001371error:
1372 if (bDesktopDC) DeleteDC( hdc );
1373 if (section) UnmapViewOfFile( mapBits );
1374 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1375 HeapFree( GetProcessHeap(), 0, dib );
1376 return 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001377}