blob: 9fcb7c58e9a562282e2d629dd8c1403ee0cce59d [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{
Huw Davies515b40c2008-05-02 12:35:40 +0100126 int colors, 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;
142 return sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) + colors *
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000143 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
144 }
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 */
Michael Kaufmann970b2212004-09-20 21:45:00 +0000154static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
Alexandre Julliard95914662005-04-13 14:45:27 +0000155 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{
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000335 DC *dc;
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000336 BITMAPOBJ *bitmap;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000337 INT result = 0;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000338
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200339 if (!(dc = get_dc_ptr( hdc )))
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000340 {
341 if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" );
Huw Davies8e34fa62005-02-22 19:34:33 +0000342 return 0;
343 }
344
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200345 update_dc( dc );
346
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100347 if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
Huw Davies8e34fa62005-02-22 19:34:33 +0000348 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200349 release_dc_ptr( dc );
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000350 return 0;
351 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000352
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000353 if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done;
354
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200355 result = lines;
356 if (bitmap->funcs)
357 {
358 if (bitmap->funcs != dc->funcs)
359 ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc );
360 else if (dc->funcs->pSetDIBits)
361 result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines,
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000362 bits, info, coloruse );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200363 }
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000364
365 done:
Alexandre Julliardd8a92442002-05-31 18:43:22 +0000366 GDI_ReleaseObj( hbitmap );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200367 release_dc_ptr( dc );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000368 return result;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000369}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000370
Alexandre Julliard401710d1993-09-04 10:09:32 +0000371
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000372/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000373 * SetDIBitsToDevice (GDI32.@)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000374 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000375INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
376 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
377 UINT lines, LPCVOID bits, const BITMAPINFO *info,
378 UINT coloruse )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000379{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000380 INT ret;
Huw D M Davies91d16081998-11-06 11:03:00 +0000381 DC *dc;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000382
Louis Lendersd7117282007-05-07 21:03:16 +0100383 if (!bits) return 0;
384
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200385 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000386
Huw D M Davies91d16081998-11-06 11:03:00 +0000387 if(dc->funcs->pSetDIBitsToDevice)
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200388 {
389 update_dc( dc );
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000390 ret = dc->funcs->pSetDIBitsToDevice( dc->physDev, xDest, yDest, cx, cy, xSrc,
Huw D M Davies91d16081998-11-06 11:03:00 +0000391 ySrc, startscan, lines, bits,
392 info, coloruse );
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200393 }
Huw D M Davies91d16081998-11-06 11:03:00 +0000394 else {
Alexandre Julliard547cdc22002-11-22 22:16:53 +0000395 FIXME("unimplemented on hdc %p\n", hdc);
Huw D M Davies91d16081998-11-06 11:03:00 +0000396 ret = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000397 }
Alexandre Julliard642d3131998-07-12 19:29:36 +0000398
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200399 release_dc_ptr( dc );
Huw D M Davies91d16081998-11-06 11:03:00 +0000400 return ret;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000401}
402
Alexandre Julliarde658d821997-11-30 17:45:40 +0000403/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000404 * SetDIBColorTable (GDI32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000405 */
Robert Shearmanb4eee492004-10-18 19:35:50 +0000406UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
Alexandre Julliarde658d821997-11-30 17:45:40 +0000407{
408 DC * dc;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000409 UINT result = 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100410 BITMAPOBJ * bitmap;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000411
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100412 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100413
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100414 if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100415 {
416 /* Check if currently selected bitmap is a DIB */
417 if (bitmap->color_table)
418 {
419 if (startpos < bitmap->nb_colors)
420 {
421 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
422 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
423 result = entries;
424 }
425 }
426 GDI_ReleaseObj( dc->hBitmap );
427 }
Alexandre Julliarde658d821997-11-30 17:45:40 +0000428
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000429 if (dc->funcs->pSetDIBColorTable)
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100430 dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000431
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100432 release_dc_ptr( dc );
Ove Kaavena32ddc02000-11-25 21:42:00 +0000433 return result;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000434}
435
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000436
437/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000438 * GetDIBColorTable (GDI32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000439 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000440UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
Alexandre Julliarde658d821997-11-30 17:45:40 +0000441{
442 DC * dc;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000443 UINT result = 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000444
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100445 if (!(dc = get_dc_ptr( hdc ))) return 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000446
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000447 if (dc->funcs->pGetDIBColorTable)
448 result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100449 else
450 {
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100451 BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP );
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100452 if (bitmap)
453 {
454 /* Check if currently selected bitmap is a DIB */
455 if (bitmap->color_table)
456 {
457 if (startpos < bitmap->nb_colors)
458 {
459 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
460 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
461 result = entries;
462 }
463 }
464 GDI_ReleaseObj( dc->hBitmap );
465 }
466 }
Alexandre Julliard67a9edb2008-02-05 17:35:40 +0100467 release_dc_ptr( dc );
Ove Kaavena32ddc02000-11-25 21:42:00 +0000468 return result;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000469}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000470
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000471/* FIXME the following two structs should be combined with __sysPalTemplate in
472 objects/color.c - this should happen after de-X11-ing both of these
473 files.
Andreas Mohrf32f9182001-04-20 18:36:05 +0000474 NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000475 and blue - sigh */
476
Andrew Ziem122b8002006-05-24 07:58:57 -0600477static const RGBQUAD EGAColorsQuads[16] = {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000478/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000479 { 0x00, 0x00, 0x00, 0x00 },
480 { 0x00, 0x00, 0x80, 0x00 },
481 { 0x00, 0x80, 0x00, 0x00 },
482 { 0x00, 0x80, 0x80, 0x00 },
483 { 0x80, 0x00, 0x00, 0x00 },
484 { 0x80, 0x00, 0x80, 0x00 },
485 { 0x80, 0x80, 0x00, 0x00 },
486 { 0x80, 0x80, 0x80, 0x00 },
487 { 0xc0, 0xc0, 0xc0, 0x00 },
488 { 0x00, 0x00, 0xff, 0x00 },
489 { 0x00, 0xff, 0x00, 0x00 },
490 { 0x00, 0xff, 0xff, 0x00 },
491 { 0xff, 0x00, 0x00, 0x00 },
492 { 0xff, 0x00, 0xff, 0x00 },
493 { 0xff, 0xff, 0x00, 0x00 },
494 { 0xff, 0xff, 0xff, 0x00 }
495};
496
Andrew Ziem122b8002006-05-24 07:58:57 -0600497static const RGBTRIPLE EGAColorsTriples[16] = {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000498/* rgbBlue, rgbGreen, rgbRed */
499 { 0x00, 0x00, 0x00 },
500 { 0x00, 0x00, 0x80 },
501 { 0x00, 0x80, 0x00 },
502 { 0x00, 0x80, 0x80 },
503 { 0x80, 0x00, 0x00 },
504 { 0x80, 0x00, 0x80 },
505 { 0x80, 0x80, 0x00 },
506 { 0x80, 0x80, 0x80 },
507 { 0xc0, 0xc0, 0xc0 },
508 { 0x00, 0x00, 0xff },
509 { 0x00, 0xff, 0x00 },
510 { 0x00, 0xff, 0xff },
511 { 0xff, 0x00, 0x00 } ,
512 { 0xff, 0x00, 0xff },
513 { 0xff, 0xff, 0x00 },
514 { 0xff, 0xff, 0xff }
515};
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000516
Andrew Ziem122b8002006-05-24 07:58:57 -0600517static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000518/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000519 { 0x00, 0x00, 0x00, 0x00 },
520 { 0x00, 0x00, 0x80, 0x00 },
521 { 0x00, 0x80, 0x00, 0x00 },
522 { 0x00, 0x80, 0x80, 0x00 },
523 { 0x80, 0x00, 0x00, 0x00 },
524 { 0x80, 0x00, 0x80, 0x00 },
525 { 0x80, 0x80, 0x00, 0x00 },
526 { 0xc0, 0xc0, 0xc0, 0x00 },
527 { 0xc0, 0xdc, 0xc0, 0x00 },
528 { 0xf0, 0xca, 0xa6, 0x00 },
529 { 0xf0, 0xfb, 0xff, 0x00 },
530 { 0xa4, 0xa0, 0xa0, 0x00 },
531 { 0x80, 0x80, 0x80, 0x00 },
532 { 0x00, 0x00, 0xf0, 0x00 },
533 { 0x00, 0xff, 0x00, 0x00 },
534 { 0x00, 0xff, 0xff, 0x00 },
535 { 0xff, 0x00, 0x00, 0x00 },
536 { 0xff, 0x00, 0xff, 0x00 },
537 { 0xff, 0xff, 0x00, 0x00 },
538 { 0xff, 0xff, 0xff, 0x00 }
539};
540
Andrew Ziem122b8002006-05-24 07:58:57 -0600541static const RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000542/* rgbBlue, rgbGreen, rgbRed */
543 { 0x00, 0x00, 0x00 },
544 { 0x00, 0x00, 0x80 },
545 { 0x00, 0x80, 0x00 },
546 { 0x00, 0x80, 0x80 },
547 { 0x80, 0x00, 0x00 },
548 { 0x80, 0x00, 0x80 },
549 { 0x80, 0x80, 0x00 },
550 { 0xc0, 0xc0, 0xc0 },
551 { 0xc0, 0xdc, 0xc0 },
552 { 0xf0, 0xca, 0xa6 },
553 { 0xf0, 0xfb, 0xff },
554 { 0xa4, 0xa0, 0xa0 },
555 { 0x80, 0x80, 0x80 },
556 { 0x00, 0x00, 0xf0 },
557 { 0x00, 0xff, 0x00 },
558 { 0x00, 0xff, 0xff },
559 { 0xff, 0x00, 0x00 },
560 { 0xff, 0x00, 0xff },
561 { 0xff, 0xff, 0x00 },
562 { 0xff, 0xff, 0xff}
563};
564
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000565
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000566/******************************************************************************
Jon Griffiths783a3952004-02-09 20:47:42 +0000567 * GetDIBits [GDI32.@]
568 *
569 * Retrieves bits of bitmap and copies to buffer.
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000570 *
571 * RETURNS
572 * Success: Number of scan lines copied from bitmap
573 * Failure: 0
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000574 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000575INT WINAPI GetDIBits(
576 HDC hdc, /* [in] Handle to device context */
577 HBITMAP hbitmap, /* [in] Handle to bitmap */
578 UINT startscan, /* [in] First scan line to set in dest bitmap */
579 UINT lines, /* [in] Number of scan lines to copy */
Zygo Blaxell1084b2c1999-02-09 14:13:12 +0000580 LPVOID bits, /* [out] Address of array for bitmap bits */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000581 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000582 UINT coloruse) /* [in] RGB or palette index */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000583{
584 DC * dc;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000585 BITMAPOBJ * bmp;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000586 int i;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000587 int bitmap_type;
588 BOOL core_header;
589 LONG width;
590 LONG height;
Alexandre Julliard95914662005-04-13 14:45:27 +0000591 WORD planes, bpp;
592 DWORD compr, size;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000593 void* colorPtr;
594 RGBTRIPLE* rgbTriples;
595 RGBQUAD* rgbQuads;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000596
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000597 if (!info) return 0;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000598
Alexandre Julliard95914662005-04-13 14:45:27 +0000599 bitmap_type = DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &planes, &bpp, &compr, &size);
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000600 if (bitmap_type == -1)
601 {
602 ERR("Invalid bitmap format\n");
603 return 0;
604 }
605 core_header = (bitmap_type == 0);
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200606 if (!(dc = get_dc_ptr( hdc )))
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000607 {
Dmitry Timoshkovf31b67a2007-01-22 18:31:02 +0800608 SetLastError( ERROR_INVALID_PARAMETER );
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000609 return 0;
610 }
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200611 update_dc( dc );
Alexandre Julliard5811a2c2009-01-28 16:20:56 +0100612 if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000613 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200614 release_dc_ptr( dc );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000615 return 0;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000616 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000617
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000618 colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
Michael Stefaniuc667a1ed2009-01-26 11:01:12 +0100619 rgbTriples = colorPtr;
620 rgbQuads = colorPtr;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000621
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000622 /* Transfer color info */
623
Alexandre Julliard99892d62008-04-18 12:08:12 +0200624 switch (bpp)
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000625 {
Alexandre Julliard99892d62008-04-18 12:08:12 +0200626 case 0: /* query bitmap info only */
627 if (core_header)
628 {
629 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
630 coreheader->bcWidth = bmp->bitmap.bmWidth;
631 coreheader->bcHeight = bmp->bitmap.bmHeight;
632 coreheader->bcPlanes = 1;
633 coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
634 }
635 else
636 {
637 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
638 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
639 info->bmiHeader.biPlanes = 1;
640 info->bmiHeader.biSizeImage =
641 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
642 bmp->bitmap.bmHeight,
643 bmp->bitmap.bmBitsPixel );
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200644 info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200645 switch(bmp->bitmap.bmBitsPixel)
646 {
647 case 15:
648 info->bmiHeader.biBitCount = 16;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200649 break;
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200650 case 24:
651 info->bmiHeader.biBitCount = 32;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200652 break;
653 default:
654 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
Alexandre Julliard99892d62008-04-18 12:08:12 +0200655 break;
656 }
657 info->bmiHeader.biXPelsPerMeter = 0;
658 info->bmiHeader.biYPelsPerMeter = 0;
659 info->bmiHeader.biClrUsed = 0;
660 info->bmiHeader.biClrImportant = 0;
661
662 /* Windows 2000 doesn't touch the additional struct members if
663 it's a BITMAPV4HEADER or a BITMAPV5HEADER */
664 }
665 lines = abs(bmp->bitmap.bmHeight);
666 goto done;
667
668 case 1:
669 case 4:
670 case 8:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000671 if (!core_header) info->bmiHeader.biClrUsed = 0;
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000672
Dave Belanger4db092c2003-10-11 05:23:45 +0000673 /* If the bitmap object already has a dib section at the
674 same color depth then get the color map from it */
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000675 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000676 if(coloruse == DIB_RGB_COLORS) {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100677 unsigned int colors = min( bmp->nb_colors, 1 << bpp );
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000678
679 if (core_header)
680 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100681 /* Convert the color table (RGBQUAD to RGBTRIPLE) */
682 RGBTRIPLE* index = rgbTriples;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000683
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100684 for (i=0; i < colors; i++, index++)
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000685 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100686 index->rgbtRed = bmp->color_table[i].rgbRed;
687 index->rgbtGreen = bmp->color_table[i].rgbGreen;
688 index->rgbtBlue = bmp->color_table[i].rgbBlue;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000689 }
690 }
691 else
692 {
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +0100693 if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
694 memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000695 }
Huw Daviesfddf5ce2004-03-30 20:38:45 +0000696 }
Huw Davies16145172004-03-29 21:39:04 +0000697 else {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000698 WORD *index = colorPtr;
Huw Davies16145172004-03-29 21:39:04 +0000699 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
700 *index = i;
701 }
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000702 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000703 else {
Michael Karcher53339232008-06-08 01:44:10 +0200704 if (coloruse == DIB_PAL_COLORS) {
705 for (i = 0; i < (1 << bpp); i++)
706 ((WORD *)colorPtr)[i] = (WORD)i;
707 }
Michael Karcherfd8746b2008-06-29 13:30:01 +0200708 else if(bpp > 1 && bpp == bmp->bitmap.bmBitsPixel) {
709 /* For color DDBs in native depth (mono DDBs always have
710 a black/white palette):
711 Generate the color map from the selected palette */
Alexandre Julliardc60757b2006-11-17 14:34:20 +0100712 PALETTEENTRY palEntry[256];
713
714 memset( palEntry, 0, sizeof(palEntry) );
715 if (!GetPaletteEntries( dc->hPalette, 0, 1 << bmp->bitmap.bmBitsPixel, palEntry ))
716 {
Alexandre Julliardbaa8d222007-09-17 16:48:56 +0200717 release_dc_ptr( dc );
Dave Belanger4db092c2003-10-11 05:23:45 +0000718 GDI_ReleaseObj( hbitmap );
719 return 0;
720 }
Alexandre Julliardc60757b2006-11-17 14:34:20 +0100721 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++) {
Michael Karcher53339232008-06-08 01:44:10 +0200722 if (core_header)
723 {
724 rgbTriples[i].rgbtRed = palEntry[i].peRed;
725 rgbTriples[i].rgbtGreen = palEntry[i].peGreen;
726 rgbTriples[i].rgbtBlue = palEntry[i].peBlue;
Dave Belanger4db092c2003-10-11 05:23:45 +0000727 }
Michael Karcher53339232008-06-08 01:44:10 +0200728 else
729 {
730 rgbQuads[i].rgbRed = palEntry[i].peRed;
731 rgbQuads[i].rgbGreen = palEntry[i].peGreen;
732 rgbQuads[i].rgbBlue = palEntry[i].peBlue;
733 rgbQuads[i].rgbReserved = 0;
734 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000735 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000736 } else {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000737 switch (bpp) {
Dave Belanger4db092c2003-10-11 05:23:45 +0000738 case 1:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000739 if (core_header)
740 {
741 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
742 rgbTriples[0].rgbtBlue = 0;
743 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
744 rgbTriples[1].rgbtBlue = 0xff;
745 }
746 else
747 {
748 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
749 rgbQuads[0].rgbBlue = 0;
750 rgbQuads[0].rgbReserved = 0;
751 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
752 rgbQuads[1].rgbBlue = 0xff;
753 rgbQuads[1].rgbReserved = 0;
754 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000755 break;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000756
Dave Belanger4db092c2003-10-11 05:23:45 +0000757 case 4:
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000758 if (core_header)
759 memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
760 else
761 memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
762
Dave Belanger4db092c2003-10-11 05:23:45 +0000763 break;
764
765 case 8:
766 {
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000767 if (core_header)
768 {
769 INT r, g, b;
770 RGBTRIPLE *color;
Dave Belanger4db092c2003-10-11 05:23:45 +0000771
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000772 memcpy(rgbTriples, DefLogPaletteTriples,
773 10 * sizeof(RGBTRIPLE));
774 memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
775 10 * sizeof(RGBTRIPLE));
776 color = rgbTriples + 10;
777 for(r = 0; r <= 5; r++) /* FIXME */
778 for(g = 0; g <= 5; g++)
779 for(b = 0; b <= 5; b++) {
780 color->rgbtRed = (r * 0xff) / 5;
781 color->rgbtGreen = (g * 0xff) / 5;
782 color->rgbtBlue = (b * 0xff) / 5;
783 color++;
784 }
785 }
786 else
787 {
788 INT r, g, b;
789 RGBQUAD *color;
790
791 memcpy(rgbQuads, DefLogPaletteQuads,
792 10 * sizeof(RGBQUAD));
793 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
794 10 * sizeof(RGBQUAD));
795 color = rgbQuads + 10;
796 for(r = 0; r <= 5; r++) /* FIXME */
797 for(g = 0; g <= 5; g++)
798 for(b = 0; b <= 5; b++) {
799 color->rgbRed = (r * 0xff) / 5;
800 color->rgbGreen = (g * 0xff) / 5;
801 color->rgbBlue = (b * 0xff) / 5;
802 color->rgbReserved = 0;
803 color++;
804 }
805 }
Dave Belanger4db092c2003-10-11 05:23:45 +0000806 }
807 }
808 }
809 }
Alexandre Julliard99892d62008-04-18 12:08:12 +0200810 break;
811
812 case 15:
813 if (info->bmiHeader.biCompression == BI_BITFIELDS)
814 {
815 ((PDWORD)info->bmiColors)[0] = 0x7c00;
816 ((PDWORD)info->bmiColors)[1] = 0x03e0;
817 ((PDWORD)info->bmiColors)[2] = 0x001f;
818 }
819 break;
820
821 case 16:
822 if (info->bmiHeader.biCompression == BI_BITFIELDS)
823 {
824 ((PDWORD)info->bmiColors)[0] = 0xf800;
825 ((PDWORD)info->bmiColors)[1] = 0x07e0;
826 ((PDWORD)info->bmiColors)[2] = 0x001f;
827 }
828 break;
Alexandre Julliardbaceb8d2008-04-21 11:57:30 +0200829
830 case 24:
831 case 32:
832 if (info->bmiHeader.biCompression == BI_BITFIELDS)
833 {
834 ((PDWORD)info->bmiColors)[0] = 0xff0000;
835 ((PDWORD)info->bmiColors)[1] = 0x00ff00;
836 ((PDWORD)info->bmiColors)[2] = 0x0000ff;
837 }
838 break;
Dave Belanger4db092c2003-10-11 05:23:45 +0000839 }
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000840
Kai Morich9e9fc1b1999-09-13 15:13:24 +0000841 if (bits && lines)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000842 {
Andreas Mohrf32f9182001-04-20 18:36:05 +0000843 /* 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 +0000844 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
Karl Lessard41875791999-09-03 16:49:17 +0000845 {
846 /*FIXME: Only RGB dibs supported for now */
Joerg Mayer4d756402001-01-10 22:45:33 +0000847 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000848 unsigned int dstwidth = width;
849 int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
Patrik Stridvall0ee98cc2000-02-26 13:17:55 +0000850 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
Huw Daviesdd8922f2004-08-12 20:02:39 +0000851 unsigned int x, y, width, widthb;
Karl Lessard41875791999-09-03 16:49:17 +0000852
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000853 if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
Karl Lessard41875791999-09-03 16:49:17 +0000854 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000855 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
Karl Lessard41875791999-09-03 16:49:17 +0000856 dstwidthb = -dstwidthb;
857 }
858
Michael Kaufmann0dd29102004-11-02 05:23:49 +0000859 switch( bpp ) {
Karl Lessard41875791999-09-03 16:49:17 +0000860
Karl Lessarddee464c1999-09-14 11:51:01 +0000861 case 15:
Karl Lessard41875791999-09-03 16:49:17 +0000862 case 16: /* 16 bpp dstDIB */
863 {
864 LPWORD dstbits = (LPWORD)dbits;
865 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
866
867 /* FIXME: BI_BITFIELDS not supported yet */
868
869 switch(bmp->dib->dsBm.bmBitsPixel) {
870
871 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
872 {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000873 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +0000874 /* FIXME: BI_BITFIELDS not supported yet */
875 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
Huw Daviesdd8922f2004-08-12 20:02:39 +0000876 memcpy(dbits, sbits, widthb);
Karl Lessard41875791999-09-03 16:49:17 +0000877 }
878 break;
879
880 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
881 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000882 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000883
Huw Daviesdd8922f2004-08-12 20:02:39 +0000884 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000885 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000886 for( x = 0; x < width; x++, srcbits += 3)
Marcus Meissner183eae92001-06-14 19:22:55 +0000887 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
888 (((WORD)srcbits[1] << 2) & gmask) |
889 (((WORD)srcbits[2] << 7) & rmask);
890
Karl Lessard41875791999-09-03 16:49:17 +0000891 dstbits = (LPWORD)(dbits+=dstwidthb);
Huw D M Davies1bb98601999-09-19 12:04:17 +0000892 srcbits = (sbits += srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000893 }
894 }
895 break;
896
897 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
898 {
899 LPDWORD srcbits = (LPDWORD)sbits;
900 DWORD val;
901
Huw Daviesdd8922f2004-08-12 20:02:39 +0000902 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000903 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000904 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000905 val = *srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000906 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
907 ((val >> 9) & rmask));
Karl Lessard41875791999-09-03 16:49:17 +0000908 }
Huw D M Davies1bb98601999-09-19 12:04:17 +0000909 dstbits = (LPWORD)(dbits+=dstwidthb);
910 srcbits = (LPDWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000911 }
912 }
913 break;
914
915 default: /* ? bit bmp -> 16 bit DIB */
916 FIXME("15/16 bit DIB %d bit bitmap\n",
917 bmp->bitmap.bmBitsPixel);
918 break;
919 }
920 }
921 break;
922
923 case 24: /* 24 bpp dstDIB */
924 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000925 LPBYTE dstbits = dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000926
927 switch(bmp->dib->dsBm.bmBitsPixel) {
928
929 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
930 {
931 LPWORD srcbits = (LPWORD)sbits;
932 WORD val;
933
Huw Daviesdd8922f2004-08-12 20:02:39 +0000934 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000935 /* FIXME: BI_BITFIELDS not supported yet */
936 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000937 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000938 val = *srcbits++;
Karl Lessard41875791999-09-03 16:49:17 +0000939 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000940 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
941 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
Karl Lessard41875791999-09-03 16:49:17 +0000942 }
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000943 dstbits = dbits+=dstwidthb;
Karl Lessard41875791999-09-03 16:49:17 +0000944 srcbits = (LPWORD)(sbits+=srcwidthb);
945 }
946 }
947 break;
948
949 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
950 {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000951 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +0000952 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
Huw Daviesdd8922f2004-08-12 20:02:39 +0000953 memcpy(dbits, sbits, widthb);
Karl Lessard41875791999-09-03 16:49:17 +0000954 }
955 break;
956
957 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
958 {
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000959 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000960
Huw Daviesdd8922f2004-08-12 20:02:39 +0000961 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000962 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000963 for( x = 0; x < width; x++, srcbits++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000964 *dstbits++ = *srcbits++;
965 *dstbits++ = *srcbits++;
966 *dstbits++ = *srcbits++;
967 }
Andrew Talbotd0d4c742008-01-05 16:44:09 +0000968 dstbits = dbits+=dstwidthb;
969 srcbits = sbits+=srcwidthb;
Karl Lessard41875791999-09-03 16:49:17 +0000970 }
971 }
972 break;
973
974 default: /* ? bit bmp -> 24 bit DIB */
975 FIXME("24 bit DIB %d bit bitmap\n",
976 bmp->bitmap.bmBitsPixel);
977 break;
978 }
979 }
980 break;
981
982 case 32: /* 32 bpp dstDIB */
983 {
984 LPDWORD dstbits = (LPDWORD)dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000985
986 /* FIXME: BI_BITFIELDS not supported yet */
987
988 switch(bmp->dib->dsBm.bmBitsPixel) {
989 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
990 {
991 LPWORD srcbits = (LPWORD)sbits;
992 DWORD val;
993
Huw Daviesdd8922f2004-08-12 20:02:39 +0000994 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +0000995 /* FIXME: BI_BITFIELDS not supported yet */
996 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +0000997 for( x = 0; x < width; x++ ) {
Karl Lessard41875791999-09-03 16:49:17 +0000998 val = (DWORD)*srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000999 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
Karl Lessard41875791999-09-03 16:49:17 +00001000 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
Karl Lessardc73a1fd1999-09-19 14:15:41 +00001001 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
Karl Lessard41875791999-09-03 16:49:17 +00001002 }
Huw D M Davies1bb98601999-09-19 12:04:17 +00001003 dstbits=(LPDWORD)(dbits+=dstwidthb);
1004 srcbits=(LPWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +00001005 }
1006 }
1007 break;
1008
1009 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
1010 {
Huw D M Davies1bb98601999-09-19 12:04:17 +00001011 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +00001012
Huw Daviesdd8922f2004-08-12 20:02:39 +00001013 width = min(srcwidth, dstwidth);
Karl Lessard41875791999-09-03 16:49:17 +00001014 for( y = 0; y < lines; y++) {
Huw Daviesdd8922f2004-08-12 20:02:39 +00001015 for( x = 0; x < width; x++, srcbits+=3 )
Huw Daviese32932e2005-12-08 13:53:07 +01001016 *dstbits++ = srcbits[0] |
1017 (srcbits[1] << 8) |
1018 (srcbits[2] << 16);
Huw D M Davies1bb98601999-09-19 12:04:17 +00001019 dstbits=(LPDWORD)(dbits+=dstwidthb);
Karl Lessard41875791999-09-03 16:49:17 +00001020 srcbits=(sbits+=srcwidthb);
1021 }
1022 }
1023 break;
1024
Huw Daviesdd8922f2004-08-12 20:02:39 +00001025 case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */
Karl Lessard41875791999-09-03 16:49:17 +00001026 {
Huw Daviesdd8922f2004-08-12 20:02:39 +00001027 widthb = min(srcwidthb, abs(dstwidthb));
Karl Lessard41875791999-09-03 16:49:17 +00001028 /* FIXME: BI_BITFIELDS not supported yet */
Huw Daviesdd8922f2004-08-12 20:02:39 +00001029 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) {
1030 memcpy(dbits, sbits, widthb);
1031 }
Karl Lessard41875791999-09-03 16:49:17 +00001032 }
1033 break;
1034
Dave Belanger4db092c2003-10-11 05:23:45 +00001035 default: /* ? bit bmp -> 32 bit DIB */
1036 FIXME("32 bit DIB %d bit bitmap\n",
Karl Lessard41875791999-09-03 16:49:17 +00001037 bmp->bitmap.bmBitsPixel);
1038 break;
1039 }
1040 }
1041 break;
1042
1043 default: /* ? bit DIB */
1044 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
1045 break;
1046 }
1047 }
1048 /* Otherwise, get bits from the XImage */
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001049 else
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001050 {
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001051 if (!bmp->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) lines = 0;
1052 else
1053 {
1054 if (bmp->funcs && bmp->funcs->pGetDIBits)
1055 lines = bmp->funcs->pGetDIBits( dc->physDev, hbitmap, startscan,
1056 lines, bits, info, coloruse );
1057 else
1058 lines = 0; /* FIXME: should copy from bmp->bitmap.bmBits */
1059 }
1060 }
Alexandre Julliard401710d1993-09-04 10:09:32 +00001061 }
Alexandre Julliard99892d62008-04-18 12:08:12 +02001062 else lines = abs(height);
Huw D M Daviescc3e5d71999-03-25 10:48:01 +00001063
Alexandre Julliard99892d62008-04-18 12:08:12 +02001064 /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
1065 if bits == NULL and bpp != 0, only biSizeImage and the color table are
1066 filled in. */
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001067 if (!core_header)
1068 {
Alexandre Julliard99892d62008-04-18 12:08:12 +02001069 /* FIXME: biSizeImage should be calculated according to the selected
1070 compression algorithm if biCompression != BI_RGB */
1071 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001072 TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001073 }
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001074 TRACE("biWidth = %d, biHeight = %d\n", width, height);
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001075
Alexandre Julliard99892d62008-04-18 12:08:12 +02001076done:
Alexandre Julliardbaa8d222007-09-17 16:48:56 +02001077 release_dc_ptr( dc );
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001078 GDI_ReleaseObj( hbitmap );
Alexandre Julliard401710d1993-09-04 10:09:32 +00001079 return lines;
1080}
1081
1082
1083/***********************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00001084 * CreateDIBitmap (GDI32.@)
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001085 *
1086 * Creates a DDB (device dependent bitmap) from a DIB.
1087 * The DDB will have the same color depth as the reference DC.
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001088 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001089HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001090 DWORD init, LPCVOID bits, const BITMAPINFO *data,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001091 UINT coloruse )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001092{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001093 HBITMAP handle;
Michael Kaufmann970b2212004-09-20 21:45:00 +00001094 LONG width;
1095 LONG height;
Alexandre Julliard95914662005-04-13 14:45:27 +00001096 WORD planes, bpp;
1097 DWORD compr, size;
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001098 DC *dc;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001099
Alexandre Julliard95914662005-04-13 14:45:27 +00001100 if (DIB_GetBitmapInfo( header, &width, &height, &planes, &bpp, &compr, &size ) == -1) return 0;
Michael Kaufmann970b2212004-09-20 21:45:00 +00001101
1102 if (width < 0)
1103 {
1104 TRACE("Bitmap has a negative width\n");
1105 return 0;
1106 }
1107
1108 /* Top-down DIBs have a negative height */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001109 if (height < 0) height = -height;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001110
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001111 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 +00001112 hdc, header, init, bits, data, coloruse, width, height, bpp, compr);
1113
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001114 if (hdc == NULL)
1115 handle = CreateBitmap( width, height, 1, 1, NULL );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001116 else
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001117 handle = CreateCompatibleBitmap( hdc, width, height );
Alexandre Julliard946a4442000-07-30 13:50:27 +00001118
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001119 if (handle)
1120 {
Lei Zhangce552d42008-07-18 15:28:44 -07001121 if (init == CBM_INIT)
1122 {
1123 if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1124 {
1125 DeleteObject( handle );
1126 handle = 0;
1127 }
1128 }
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001129
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001130 else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) )
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001131 {
Alexandre Julliardcdcdbe52004-09-13 19:37:03 +00001132 if (!BITMAP_SetOwnerDC( handle, dc ))
1133 {
1134 DeleteObject( handle );
1135 handle = 0;
1136 }
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001137 release_dc_ptr( dc );
Alexandre Julliardd8a92442002-05-31 18:43:22 +00001138 }
1139 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001140
Alexandre Julliard401710d1993-09-04 10:09:32 +00001141 return handle;
1142}
Alexandre Julliard77b99181997-09-14 17:17:23 +00001143
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001144/***********************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +00001145 * CreateDIBSection (GDI.489)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001146 */
Dmitry Timoshkov21fc3c82004-03-12 19:46:12 +00001147HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 usage,
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001148 SEGPTR *bits16, HANDLE section, DWORD offset)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001149{
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001150 LPVOID bits32;
1151 HBITMAP hbitmap;
Stephane Lussier23259ce2000-07-11 22:04:44 +00001152
Michael Stefaniuc28a632a2002-11-21 21:50:04 +00001153 hbitmap = CreateDIBSection( HDC_32(hdc), bmi, usage, &bits32, section, offset );
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001154 if (hbitmap)
Stephane Lussier23259ce2000-07-11 22:04:44 +00001155 {
Alexandre Julliard5811a2c2009-01-28 16:20:56 +01001156 BITMAPOBJ *bmp = GDI_GetObjPtr(hbitmap, OBJ_BITMAP);
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001157 if (bmp && bmp->dib && bits32)
1158 {
Dmitry Timoshkov21fc3c82004-03-12 19:46:12 +00001159 const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001160 LONG width, height;
Alexandre Julliard95914662005-04-13 14:45:27 +00001161 WORD planes, bpp;
1162 DWORD compr, size;
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001163 INT width_bytes;
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001164 WORD count, sel;
1165 int i;
1166
Alexandre Julliard95914662005-04-13 14:45:27 +00001167 DIB_GetBitmapInfo(bi, &width, &height, &planes, &bpp, &compr, &size);
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001168
1169 height = height >= 0 ? height : -height;
1170 width_bytes = DIB_GetDIBWidthBytes(width, bpp);
Alexandre Julliard95914662005-04-13 14:45:27 +00001171
1172 if (!size || (compr != BI_RLE4 && compr != BI_RLE8)) size = width_bytes * height;
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001173
Andreas Mohr757e7cb2002-05-08 00:20:40 +00001174 /* calculate number of sel's needed for size with 64K steps */
Michael Kaufmann0dd29102004-11-02 05:23:49 +00001175 count = (size + 0xffff) / 0x10000;
1176 sel = AllocSelectorArray16(count);
Andreas Mohr757e7cb2002-05-08 00:20:40 +00001177
1178 for (i = 0; i < count; i++)
1179 {
1180 SetSelectorBase(sel + (i << __AHSHIFT), (DWORD)bits32 + i * 0x10000);
1181 SetSelectorLimit16(sel + (i << __AHSHIFT), size - 1); /* yep, limit is correct */
1182 size -= 0x10000;
1183 }
Alexandre Julliard6bbc7452001-07-22 23:13:08 +00001184 bmp->segptr_bits = MAKESEGPTR( sel, 0 );
1185 if (bits16) *bits16 = bmp->segptr_bits;
1186 }
1187 if (bmp) GDI_ReleaseObj( hbitmap );
Stephane Lussier23259ce2000-07-11 22:04:44 +00001188 }
Michael Stefaniuc28a632a2002-11-21 21:50:04 +00001189 return HBITMAP_16(hbitmap);
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001190}
1191
Francois Gouget44b52b12008-01-16 12:20:50 +01001192/* Copy/synthesize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001193static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1194{
1195 RGBQUAD *colorTable;
Andrew Talbot44be6c72008-10-02 22:18:38 +01001196 unsigned int colors, i;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001197 BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
1198
1199 if (core_info)
1200 {
1201 colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
1202 }
1203 else
1204 {
1205 colors = info->bmiHeader.biClrUsed;
1206 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
1207 }
1208
1209 if (colors > 256) {
1210 ERR("called with >256 colors!\n");
1211 return;
1212 }
1213
1214 if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1215
1216 if(coloruse == DIB_RGB_COLORS)
1217 {
1218 if (core_info)
1219 {
1220 /* Convert RGBTRIPLEs to RGBQUADs */
1221 for (i=0; i < colors; i++)
1222 {
1223 colorTable[i].rgbRed = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
1224 colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
1225 colorTable[i].rgbBlue = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
1226 colorTable[i].rgbReserved = 0;
1227 }
1228 }
1229 else
1230 {
1231 memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
1232 }
1233 }
1234 else
1235 {
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001236 PALETTEENTRY entries[256];
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001237 const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001238 UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001239
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001240 for (i = 0; i < colors; i++, index++)
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001241 {
Alexandre Julliardc60757b2006-11-17 14:34:20 +01001242 PALETTEENTRY *entry = &entries[*index % count];
1243 colorTable[i].rgbRed = entry->peRed;
1244 colorTable[i].rgbGreen = entry->peGreen;
1245 colorTable[i].rgbBlue = entry->peBlue;
1246 colorTable[i].rgbReserved = 0;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001247 }
1248 }
1249 bmp->color_table = colorTable;
1250 bmp->nb_colors = colors;
1251}
1252
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001253/***********************************************************************
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001254 * CreateDIBSection (GDI32.@)
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001255 */
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001256HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1257 VOID **bits, HANDLE section, DWORD offset)
Ove Kaaven8b9f3382000-04-29 16:47:07 +00001258{
Alexandre Julliard95914662005-04-13 14:45:27 +00001259 HBITMAP ret = 0;
Stephane Lussier23259ce2000-07-11 22:04:44 +00001260 DC *dc;
1261 BOOL bDesktopDC = FALSE;
Alexandre Julliard95914662005-04-13 14:45:27 +00001262 DIBSECTION *dib;
1263 BITMAPOBJ *bmp;
1264 int bitmap_type;
1265 LONG width, height;
1266 WORD planes, bpp;
1267 DWORD compression, sizeImage;
Alexandre Julliard95914662005-04-13 14:45:27 +00001268 void *mapBits = NULL;
1269
Nikolay Sivov14413112008-05-10 11:14:29 +04001270 if(!bmi){
1271 if(bits) *bits = NULL;
1272 return NULL;
1273 }
1274
Alexandre Julliard95914662005-04-13 14:45:27 +00001275 if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
1276 &planes, &bpp, &compression, &sizeImage )) == -1))
1277 return 0;
1278
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001279 if (compression != BI_RGB && compression != BI_BITFIELDS)
1280 {
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001281 TRACE("can't create a compressed (%u) dibsection\n", compression);
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001282 return 0;
1283 }
1284
Alexandre Julliard95914662005-04-13 14:45:27 +00001285 if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1286
Michael Stefaniuca0b260e2006-10-12 22:56:56 +02001287 TRACE("format (%d,%d), planes %d, bpp %d, size %d, %s\n",
Alexandre Julliard95914662005-04-13 14:45:27 +00001288 width, height, planes, bpp, sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1289
1290 dib->dsBm.bmType = 0;
1291 dib->dsBm.bmWidth = width;
1292 dib->dsBm.bmHeight = height >= 0 ? height : -height;
Alexandre Julliard1a2417d2006-06-19 11:25:42 +02001293 dib->dsBm.bmWidthBytes = DIB_GetDIBWidthBytes(width, bpp);
Alexandre Julliard95914662005-04-13 14:45:27 +00001294 dib->dsBm.bmPlanes = planes;
1295 dib->dsBm.bmBitsPixel = bpp;
1296 dib->dsBm.bmBits = NULL;
1297
1298 if (!bitmap_type) /* core header */
1299 {
1300 /* convert the BITMAPCOREHEADER to a BITMAPINFOHEADER */
1301 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1302 dib->dsBmih.biWidth = width;
1303 dib->dsBmih.biHeight = height;
1304 dib->dsBmih.biPlanes = planes;
1305 dib->dsBmih.biBitCount = bpp;
1306 dib->dsBmih.biCompression = compression;
1307 dib->dsBmih.biXPelsPerMeter = 0;
1308 dib->dsBmih.biYPelsPerMeter = 0;
1309 dib->dsBmih.biClrUsed = 0;
1310 dib->dsBmih.biClrImportant = 0;
1311 }
1312 else
1313 {
1314 /* truncate extended bitmap headers (BITMAPV4HEADER etc.) */
1315 dib->dsBmih = bmi->bmiHeader;
1316 dib->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
1317 }
1318
Peter Beutnerc9e02e12005-11-14 15:10:23 +00001319 /* set number of entries in bmi.bmiColors table */
1320 if( bpp <= 8 )
1321 dib->dsBmih.biClrUsed = 1 << bpp;
1322
Ulrich Czekalla4f5cbfb2006-01-03 12:09:03 +01001323 dib->dsBmih.biSizeImage = dib->dsBm.bmWidthBytes * dib->dsBm.bmHeight;
Alexandre Julliard95914662005-04-13 14:45:27 +00001324
1325 /* set dsBitfields values */
Alexandre Julliard95914662005-04-13 14:45:27 +00001326 if (usage == DIB_PAL_COLORS || bpp <= 8)
1327 {
1328 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1329 }
1330 else switch( bpp )
1331 {
1332 case 15:
1333 case 16:
Michael Kaufmann0f2c2b82005-08-08 18:40:14 +00001334 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0x7c00;
1335 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
1336 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
Alexandre Julliard95914662005-04-13 14:45:27 +00001337 break;
1338 case 24:
1339 case 32:
Michael Kaufmann0f2c2b82005-08-08 18:40:14 +00001340 dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors : 0xff0000;
1341 dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
1342 dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
Alexandre Julliard95914662005-04-13 14:45:27 +00001343 break;
1344 }
1345
1346 /* get storage location for DIB bits */
1347
1348 if (section)
1349 {
1350 SYSTEM_INFO SystemInfo;
1351 DWORD mapOffset;
1352 INT mapSize;
1353
1354 GetSystemInfo( &SystemInfo );
1355 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1356 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1357 mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1358 if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1359 }
Alexandre Julliard95914662005-04-13 14:45:27 +00001360 else
1361 {
1362 offset = 0;
1363 dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1364 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1365 }
1366 dib->dshSection = section;
1367 dib->dsOffset = offset;
1368
1369 if (!dib->dsBm.bmBits)
1370 {
1371 HeapFree( GetProcessHeap(), 0, dib );
1372 return 0;
1373 }
Stephane Lussier23259ce2000-07-11 22:04:44 +00001374
1375 /* If the reference hdc is null, take the desktop dc */
1376 if (hdc == 0)
1377 {
1378 hdc = CreateCompatibleDC(0);
1379 bDesktopDC = TRUE;
1380 }
1381
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001382 if (!(dc = get_dc_ptr( hdc ))) goto error;
Alexandre Julliard95914662005-04-13 14:45:27 +00001383
1384 /* create Device Dependent Bitmap and add DIB pointer */
1385 ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1386 (bpp == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1387
Alexandre Julliard5811a2c2009-01-28 16:20:56 +01001388 if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001389 {
Alexandre Julliard95914662005-04-13 14:45:27 +00001390 bmp->dib = dib;
1391 bmp->funcs = dc->funcs;
Alexandre Julliardf7ffbe42006-11-08 19:57:30 +01001392 /* create local copy of DIB palette */
1393 if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
Alexandre Julliard95914662005-04-13 14:45:27 +00001394 GDI_ReleaseObj( ret );
1395
1396 if (dc->funcs->pCreateDIBSection)
1397 {
1398 if (!dc->funcs->pCreateDIBSection(dc->physDev, ret, bmi, usage))
1399 {
1400 DeleteObject( ret );
1401 ret = 0;
1402 }
1403 }
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001404 }
Ulrich Weigand4f85bad1999-02-09 15:30:22 +00001405
Alexandre Julliard67a9edb2008-02-05 17:35:40 +01001406 release_dc_ptr( dc );
Alexandre Julliard95914662005-04-13 14:45:27 +00001407 if (bDesktopDC) DeleteDC( hdc );
1408 if (ret && bits) *bits = dib->dsBm.bmBits;
1409 return ret;
Stephane Lussier23259ce2000-07-11 22:04:44 +00001410
Alexandre Julliard95914662005-04-13 14:45:27 +00001411error:
1412 if (bDesktopDC) DeleteDC( hdc );
1413 if (section) UnmapViewOfFile( mapBits );
1414 else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1415 HeapFree( GetProcessHeap(), 0, dib );
1416 return 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001417}