blob: 4947f122d97bc5f8139cee44d17f6ba1f0776ea1 [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 Julliard3a5816f1994-12-27 14:11:53 +00006 */
7
Michael Veksler92ae2191999-05-02 11:39:09 +00008#include "winbase.h"
Alexandre Julliard8d24ae61994-04-05 21:42:43 +00009#include "bitmap.h"
Alexandre Julliarda2f2e011995-06-06 16:40:35 +000010#include "callback.h"
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000011#include "dc.h"
Alexandre Julliard15657091999-05-23 10:25:25 +000012#include "debugtools.h"
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000013#include "palette.h"
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000014
Alexandre Julliard946a4442000-07-30 13:50:27 +000015DEFAULT_DEBUG_CHANNEL(bitmap);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000016
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000017/***********************************************************************
18 * DIB_GetDIBWidthBytes
19 *
20 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
21 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
22 */
23int DIB_GetDIBWidthBytes( int width, int depth )
Alexandre Julliard234bc241994-12-10 13:02:28 +000024{
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000025 int words;
26
27 switch(depth)
28 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000029 case 1: words = (width + 31) / 32; break;
30 case 4: words = (width + 7) / 8; break;
31 case 8: words = (width + 3) / 4; break;
32 case 15:
33 case 16: words = (width + 1) / 2; break;
34 case 24: words = (width * 3 + 3)/4; break;
35
36 default:
Alexandre Julliard15657091999-05-23 10:25:25 +000037 WARN("(%d): Unsupported depth\n", depth );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000038 /* fall through */
39 case 32:
40 words = width;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000041 }
42 return 4 * words;
Alexandre Julliard234bc241994-12-10 13:02:28 +000043}
Alexandre Julliard401710d1993-09-04 10:09:32 +000044
Huw D M Davies608629b1999-04-18 12:07:00 +000045/***********************************************************************
46 * DIB_GetDIBImageBytes
47 *
48 * Return the number of bytes used to hold the image in a DIB bitmap.
49 */
50int DIB_GetDIBImageBytes( int width, int height, int depth )
51{
52 return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
53}
54
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000055
Alexandre Julliard401710d1993-09-04 10:09:32 +000056/***********************************************************************
57 * DIB_BitmapInfoSize
58 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000059 * Return the size of the bitmap info structure including color table.
Alexandre Julliard401710d1993-09-04 10:09:32 +000060 */
Huw D M Davies56166a61999-04-19 16:45:24 +000061int DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
Alexandre Julliard401710d1993-09-04 10:09:32 +000062{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000063 int colors;
64
65 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
66 {
67 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
Alexandre Julliard23946ad1997-06-16 17:43:53 +000068 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000069 return sizeof(BITMAPCOREHEADER) + colors *
70 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
71 }
72 else /* assume BITMAPINFOHEADER */
73 {
74 colors = info->bmiHeader.biClrUsed;
Alexandre Julliard23946ad1997-06-16 17:43:53 +000075 if (!colors && (info->bmiHeader.biBitCount <= 8))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000076 colors = 1 << info->bmiHeader.biBitCount;
77 return sizeof(BITMAPINFOHEADER) + colors *
78 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
79 }
Alexandre Julliard401710d1993-09-04 10:09:32 +000080}
81
82
83/***********************************************************************
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000084 * DIB_GetBitmapInfo
85 *
86 * Get the info from a bitmap header.
87 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
88 */
Huw D M Davies87f87bf1998-10-28 09:53:53 +000089int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
Alexandre Julliarda845b881998-06-01 10:44:35 +000090 int *height, WORD *bpp, WORD *compr )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000091{
92 if (header->biSize == sizeof(BITMAPINFOHEADER))
93 {
94 *width = header->biWidth;
95 *height = header->biHeight;
96 *bpp = header->biBitCount;
Alexandre Julliarda845b881998-06-01 10:44:35 +000097 *compr = header->biCompression;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000098 return 1;
99 }
100 if (header->biSize == sizeof(BITMAPCOREHEADER))
101 {
102 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
103 *width = core->bcWidth;
104 *height = core->bcHeight;
105 *bpp = core->bcBitCount;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000106 *compr = 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000107 return 0;
108 }
Alexandre Julliard15657091999-05-23 10:25:25 +0000109 WARN("(%ld): wrong size for header\n", header->biSize );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000110 return -1;
111}
112
113
114/***********************************************************************
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000115 * StretchDIBits16 (GDI.439)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000116 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000117INT16 WINAPI StretchDIBits16(HDC16 hdc, INT16 xDst, INT16 yDst, INT16 widthDst,
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000118 INT16 heightDst, INT16 xSrc, INT16 ySrc, INT16 widthSrc,
119 INT16 heightSrc, const VOID *bits,
120 const BITMAPINFO *info, UINT16 wUsage, DWORD dwRop )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000121{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000122 return (INT16)StretchDIBits( hdc, xDst, yDst, widthDst, heightDst,
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000123 xSrc, ySrc, widthSrc, heightSrc, bits,
124 info, wUsage, dwRop );
125}
126
127
128/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000129 * StretchDIBits (GDI32.351)
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000130 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000131INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
132 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
133 INT heightSrc, const void *bits,
134 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000135{
Huw D M Davies14c99d01998-10-24 10:44:05 +0000136 DC *dc = DC_GetDCPtr( hdc );
137 if(!dc) return FALSE;
Alexandre Julliardded30381995-07-06 17:18:27 +0000138
Huw D M Davies14c99d01998-10-24 10:44:05 +0000139 if(dc->funcs->pStretchDIBits)
140 return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst,
141 heightDst, xSrc, ySrc, widthSrc,
142 heightSrc, bits, info, wUsage,
143 dwRop);
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000144 else { /* use StretchBlt */
Alexandre Julliard54e47751999-10-13 16:16:23 +0000145 HBITMAP hBitmap, hOldBitmap;
146 HDC hdcMem;
Matthew J. Francised744e71999-10-24 17:28:23 +0000147
Alexandre Julliard54e47751999-10-13 16:16:23 +0000148 hBitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
149 bits, info, wUsage );
150 hdcMem = CreateCompatibleDC( hdc );
151 hOldBitmap = SelectObject( hdcMem, hBitmap );
Matthew J. Francised744e71999-10-24 17:28:23 +0000152 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
153 left (negative biHeight) */
Alexandre Julliard54e47751999-10-13 16:16:23 +0000154 StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
Matthew J. Francised744e71999-10-24 17:28:23 +0000155 hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
Alexandre Julliard54e47751999-10-13 16:16:23 +0000156 widthSrc, heightSrc, dwRop );
157 SelectObject( hdcMem, hOldBitmap );
158 DeleteDC( hdcMem );
159 DeleteObject( hBitmap );
160 return heightSrc;
Huw D M Davies14c99d01998-10-24 10:44:05 +0000161 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000162}
163
Alexandre Julliard54e47751999-10-13 16:16:23 +0000164
Alexandre Julliard2787be81995-05-22 18:23:01 +0000165/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000166 * SetDIBits16 (GDI.440)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000167 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000168INT16 WINAPI SetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
169 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
170 UINT16 coloruse )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000171{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000172 return SetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000173}
174
175
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000176/******************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000177 * SetDIBits [GDI32.312] Sets pixels in a bitmap using colors from DIB
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000178 *
179 * PARAMS
180 * hdc [I] Handle to device context
181 * hbitmap [I] Handle to bitmap
182 * startscan [I] Starting scan line
183 * lines [I] Number of scan lines
184 * bits [I] Array of bitmap bits
185 * info [I] Address of structure with data
186 * coloruse [I] Type of color indexes to use
187 *
188 * RETURNS
189 * Success: Number of scan lines copied
190 * Failure: 0
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000191 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000192INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000193 UINT lines, LPCVOID bits, const BITMAPINFO *info,
194 UINT coloruse )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000195{
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000196 DC *dc;
197 BITMAPOBJ *bitmap;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000198 INT result;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000199
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000200 /* Check parameters */
201 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
202 if (!dc)
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000203 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000204 dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
205 if (!dc) return 0;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000206 }
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000207
208 if (!(bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000209 {
210 GDI_HEAP_UNLOCK( hdc );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000211 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000212 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000213
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000214 result = BITMAP_Driver->pSetDIBits(bitmap, dc, startscan,
215 lines, bits, info,
216 coloruse, hbitmap);
Alexandre Julliarda845b881998-06-01 10:44:35 +0000217
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000218 GDI_HEAP_UNLOCK( hdc );
219 GDI_HEAP_UNLOCK( hbitmap );
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000220
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000221 return result;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000222}
Alexandre Julliard401710d1993-09-04 10:09:32 +0000223
Alexandre Julliard401710d1993-09-04 10:09:32 +0000224
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000225/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000226 * SetDIBitsToDevice16 (GDI.443)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000227 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000228INT16 WINAPI SetDIBitsToDevice16(HDC16 hdc, INT16 xDest, INT16 yDest, INT16 cx,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000229 INT16 cy, INT16 xSrc, INT16 ySrc, UINT16 startscan,
230 UINT16 lines, LPCVOID bits, const BITMAPINFO *info,
231 UINT16 coloruse )
232{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000233 return SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, ySrc,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000234 startscan, lines, bits, info, coloruse );
235}
236
237
238/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000239 * SetDIBitsToDevice (GDI32.313)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000240 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000241INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
242 DWORD cy, INT xSrc, INT ySrc, UINT startscan,
243 UINT lines, LPCVOID bits, const BITMAPINFO *info,
244 UINT coloruse )
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000245{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000246 INT ret;
Huw D M Davies91d16081998-11-06 11:03:00 +0000247 DC *dc;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000248
Huw D M Davies91d16081998-11-06 11:03:00 +0000249 if (!(dc = DC_GetDCPtr( hdc ))) return 0;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000250
Huw D M Davies91d16081998-11-06 11:03:00 +0000251 if(dc->funcs->pSetDIBitsToDevice)
252 ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
253 ySrc, startscan, lines, bits,
254 info, coloruse );
255 else {
Alexandre Julliard15657091999-05-23 10:25:25 +0000256 FIXME("unimplemented on hdc %08x\n", hdc);
Huw D M Davies91d16081998-11-06 11:03:00 +0000257 ret = 0;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000258 }
Alexandre Julliard642d3131998-07-12 19:29:36 +0000259
Huw D M Davies91d16081998-11-06 11:03:00 +0000260 GDI_HEAP_UNLOCK( hdc );
261 return ret;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000262}
263
Alexandre Julliarde658d821997-11-30 17:45:40 +0000264/***********************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000265 * SetDIBColorTable16 (GDI.602)
266 */
267UINT16 WINAPI SetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
268 RGBQUAD *colors )
269{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000270 return SetDIBColorTable( hdc, startpos, entries, colors );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000271}
272
273/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000274 * SetDIBColorTable (GDI32.311)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000275 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000276UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
Alexandre Julliarde658d821997-11-30 17:45:40 +0000277 RGBQUAD *colors )
278{
279 DC * dc;
280 PALETTEENTRY * palEntry;
281 PALETTEOBJ * palette;
282 RGBQUAD *end;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000283
Alexandre Julliarde658d821997-11-30 17:45:40 +0000284 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
285 if (!dc)
286 {
287 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
288 if (!dc) return 0;
289 }
290
291 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
292 {
293 return 0;
294 }
295
296 /* Transfer color info */
297
298 if (dc->w.bitsPerPixel <= 8) {
299 palEntry = palette->logpalette.palPalEntry + startpos;
Gerard Patel9dd16f01999-08-15 16:38:07 +0000300 if (startpos + entries > (1 << dc->w.bitsPerPixel))
Alexandre Julliarde658d821997-11-30 17:45:40 +0000301 entries = (1 << dc->w.bitsPerPixel) - startpos;
Gerard Patel9dd16f01999-08-15 16:38:07 +0000302
303 if (startpos + entries > palette->logpalette.palNumEntries)
304 entries = palette->logpalette.palNumEntries - startpos;
305
306 for (end = colors + entries; colors < end; palEntry++, colors++)
307 {
308 palEntry->peRed = colors->rgbRed;
309 palEntry->peGreen = colors->rgbGreen;
310 palEntry->peBlue = colors->rgbBlue;
311 }
Alexandre Julliarde658d821997-11-30 17:45:40 +0000312 } else {
313 entries = 0;
314 }
315 GDI_HEAP_UNLOCK( dc->w.hPalette );
316 return entries;
317}
318
319/***********************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000320 * GetDIBColorTable16 (GDI.603)
321 */
322UINT16 WINAPI GetDIBColorTable16( HDC16 hdc, UINT16 startpos, UINT16 entries,
323 RGBQUAD *colors )
324{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000325 return GetDIBColorTable( hdc, startpos, entries, colors );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000326}
327
328/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000329 * GetDIBColorTable (GDI32.169)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000330 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000331UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries,
Alexandre Julliarde658d821997-11-30 17:45:40 +0000332 RGBQUAD *colors )
333{
334 DC * dc;
335 PALETTEENTRY * palEntry;
336 PALETTEOBJ * palette;
337 RGBQUAD *end;
338
339 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
340 if (!dc)
341 {
342 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
343 if (!dc) return 0;
344 }
345
346 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
347 {
348 return 0;
349 }
350
351 /* Transfer color info */
352
353 if (dc->w.bitsPerPixel <= 8) {
354 palEntry = palette->logpalette.palPalEntry + startpos;
355 if (startpos + entries > (1 << dc->w.bitsPerPixel)) {
356 entries = (1 << dc->w.bitsPerPixel) - startpos;
357 }
358 for (end = colors + entries; colors < end; palEntry++, colors++)
359 {
360 colors->rgbRed = palEntry->peRed;
361 colors->rgbGreen = palEntry->peGreen;
362 colors->rgbBlue = palEntry->peBlue;
363 colors->rgbReserved = 0;
364 }
365 } else {
366 entries = 0;
367 }
368 GDI_HEAP_UNLOCK( dc->w.hPalette );
369 return entries;
370}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000371
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000372/* FIXME the following two structs should be combined with __sysPalTemplate in
373 objects/color.c - this should happen after de-X11-ing both of these
374 files.
375 NB. RGBQUAD and PALETTENTRY have different orderings of red, green
376 and blue - sigh */
377
378static RGBQUAD EGAColors[16] = {
379/* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
380 { 0x00, 0x00, 0x00, 0x00 },
381 { 0x00, 0x00, 0x80, 0x00 },
382 { 0x00, 0x80, 0x00, 0x00 },
383 { 0x00, 0x80, 0x80, 0x00 },
384 { 0x80, 0x00, 0x00, 0x00 },
385 { 0x80, 0x00, 0x80, 0x00 },
386 { 0x80, 0x80, 0x00, 0x00 },
387 { 0x80, 0x80, 0x80, 0x00 },
388 { 0xc0, 0xc0, 0xc0, 0x00 },
389 { 0x00, 0x00, 0xff, 0x00 },
390 { 0x00, 0xff, 0x00, 0x00 },
391 { 0x00, 0xff, 0xff, 0x00 },
392 { 0xff, 0x00, 0x00, 0x00 },
393 { 0xff, 0x00, 0xff, 0x00 },
394 { 0xff, 0xff, 0x00, 0x00 },
395 { 0xff, 0xff, 0xff, 0x00 }
396};
397
398
399static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
400/* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
401 { 0x00, 0x00, 0x00, 0x00 },
402 { 0x00, 0x00, 0x80, 0x00 },
403 { 0x00, 0x80, 0x00, 0x00 },
404 { 0x00, 0x80, 0x80, 0x00 },
405 { 0x80, 0x00, 0x00, 0x00 },
406 { 0x80, 0x00, 0x80, 0x00 },
407 { 0x80, 0x80, 0x00, 0x00 },
408 { 0xc0, 0xc0, 0xc0, 0x00 },
409 { 0xc0, 0xdc, 0xc0, 0x00 },
410 { 0xf0, 0xca, 0xa6, 0x00 },
411 { 0xf0, 0xfb, 0xff, 0x00 },
412 { 0xa4, 0xa0, 0xa0, 0x00 },
413 { 0x80, 0x80, 0x80, 0x00 },
414 { 0x00, 0x00, 0xf0, 0x00 },
415 { 0x00, 0xff, 0x00, 0x00 },
416 { 0x00, 0xff, 0xff, 0x00 },
417 { 0xff, 0x00, 0x00, 0x00 },
418 { 0xff, 0x00, 0xff, 0x00 },
419 { 0xff, 0xff, 0x00, 0x00 },
420 { 0xff, 0xff, 0xff, 0x00 }
421};
422
Alexandre Julliard401710d1993-09-04 10:09:32 +0000423/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000424 * GetDIBits16 (GDI.441)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000425 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000426INT16 WINAPI GetDIBits16( HDC16 hdc, HBITMAP16 hbitmap, UINT16 startscan,
Zygo Blaxell1084b2c1999-02-09 14:13:12 +0000427 UINT16 lines, LPVOID bits, BITMAPINFO * info,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000428 UINT16 coloruse )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000429{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000430 return GetDIBits( hdc, hbitmap, startscan, lines, bits, info, coloruse );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000431}
432
433
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000434/******************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000435 * GetDIBits [GDI32.170] Retrieves bits of bitmap and copies to buffer
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000436 *
437 * RETURNS
438 * Success: Number of scan lines copied from bitmap
439 * Failure: 0
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000440 *
441 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/func/src/f30_14.htm
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000442 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000443INT WINAPI GetDIBits(
444 HDC hdc, /* [in] Handle to device context */
445 HBITMAP hbitmap, /* [in] Handle to bitmap */
446 UINT startscan, /* [in] First scan line to set in dest bitmap */
447 UINT lines, /* [in] Number of scan lines to copy */
Zygo Blaxell1084b2c1999-02-09 14:13:12 +0000448 LPVOID bits, /* [out] Address of array for bitmap bits */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000449 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000450 UINT coloruse) /* [in] RGB or palette index */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000451{
452 DC * dc;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000453 BITMAPOBJ * bmp;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000454 PALETTEENTRY * palEntry;
455 PALETTEOBJ * palette;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000456 int i;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000457
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000458 if (!info) return 0;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000459 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
460 if (!dc)
461 {
462 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
463 if (!dc) return 0;
464 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000465 if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000466 {
467 GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000468 return 0;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000469 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000470 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000471 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000472 GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000473 GDI_HEAP_UNLOCK( hbitmap );
474 return 0;
475 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000476
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000477 /* Transfer color info */
478
479 if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
480
Eric Kohlc0112671998-11-15 18:10:11 +0000481 info->bmiHeader.biClrUsed = 0;
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000482
483 if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
484 palEntry = palette->logpalette.palPalEntry;
485 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
486 if (coloruse == DIB_RGB_COLORS) {
487 info->bmiColors[i].rgbRed = palEntry->peRed;
488 info->bmiColors[i].rgbGreen = palEntry->peGreen;
489 info->bmiColors[i].rgbBlue = palEntry->peBlue;
490 info->bmiColors[i].rgbReserved = 0;
491 }
492 else ((WORD *)info->bmiColors)[i] = (WORD)i;
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000493 }
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000494 } else {
495 switch (info->bmiHeader.biBitCount) {
496 case 1:
497 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
498 info->bmiColors[0].rgbBlue = 0;
499 info->bmiColors[0].rgbReserved = 0;
500 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
501 info->bmiColors[1].rgbBlue = 0xff;
502 info->bmiColors[1].rgbReserved = 0;
503 break;
504
505 case 4:
506 memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
507 break;
508
509 case 8:
510 {
511 INT r, g, b;
512 RGBQUAD *color;
513
514 memcpy(info->bmiColors, DefLogPalette,
515 10 * sizeof(RGBQUAD));
516 memcpy(info->bmiColors + 246, DefLogPalette + 10,
517 10 * sizeof(RGBQUAD));
518 color = info->bmiColors + 10;
519 for(r = 0; r <= 5; r++) /* FIXME */
520 for(g = 0; g <= 5; g++)
521 for(b = 0; b <= 5; b++) {
522 color->rgbRed = (r * 0xff) / 5;
523 color->rgbGreen = (g * 0xff) / 5;
524 color->rgbBlue = (b * 0xff) / 5;
525 color->rgbReserved = 0;
526 color++;
527 }
528 }
529 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000530 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000531 }
Alexandre Julliarda845b881998-06-01 10:44:35 +0000532
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000533 GDI_HEAP_UNLOCK( dc->w.hPalette );
534
Kai Morich9e9fc1b1999-09-13 15:13:24 +0000535 if (bits && lines)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000536 {
Karl Lessard41875791999-09-03 16:49:17 +0000537 /* If the bitmap object already have a dib section that contains image data, get the bits from it*/
Karl Lessarddee464c1999-09-14 11:51:01 +0000538 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
Karl Lessard41875791999-09-03 16:49:17 +0000539 {
540 /*FIXME: Only RGB dibs supported for now */
541 int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
542 int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
Patrik Stridvall0ee98cc2000-02-26 13:17:55 +0000543 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000544 int x, y;
545
546 if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
547 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000548 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
Karl Lessard41875791999-09-03 16:49:17 +0000549 dstwidthb = -dstwidthb;
550 }
551
552 switch( info->bmiHeader.biBitCount ) {
553
Karl Lessarddee464c1999-09-14 11:51:01 +0000554 case 15:
Karl Lessard41875791999-09-03 16:49:17 +0000555 case 16: /* 16 bpp dstDIB */
556 {
557 LPWORD dstbits = (LPWORD)dbits;
558 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
559
560 /* FIXME: BI_BITFIELDS not supported yet */
561
562 switch(bmp->dib->dsBm.bmBitsPixel) {
563
564 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
565 {
566 /* FIXME: BI_BITFIELDS not supported yet */
567 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
568 memcpy(dbits, sbits, srcwidthb);
569 }
570 break;
571
572 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
573 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000574 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000575
576 for( y = 0; y < lines; y++) {
577 for( x = 0; x < srcwidth; x++ )
578 *dstbits++ = ((*srcbits++ >> 3) & bmask) |
579 (((WORD)*srcbits++ << 2) & gmask) |
580 (((WORD)*srcbits++ << 7) & rmask);
581 dstbits = (LPWORD)(dbits+=dstwidthb);
Huw D M Davies1bb98601999-09-19 12:04:17 +0000582 srcbits = (sbits += srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000583 }
584 }
585 break;
586
587 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
588 {
589 LPDWORD srcbits = (LPDWORD)sbits;
590 DWORD val;
591
592 for( y = 0; y < lines; y++) {
593 for( x = 0; x < srcwidth; x++ ) {
594 val = *srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000595 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
596 ((val >> 9) & rmask));
Karl Lessard41875791999-09-03 16:49:17 +0000597 }
Huw D M Davies1bb98601999-09-19 12:04:17 +0000598 dstbits = (LPWORD)(dbits+=dstwidthb);
599 srcbits = (LPDWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000600 }
601 }
602 break;
603
604 default: /* ? bit bmp -> 16 bit DIB */
605 FIXME("15/16 bit DIB %d bit bitmap\n",
606 bmp->bitmap.bmBitsPixel);
607 break;
608 }
609 }
610 break;
611
612 case 24: /* 24 bpp dstDIB */
613 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000614 LPBYTE dstbits = dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000615
616 switch(bmp->dib->dsBm.bmBitsPixel) {
617
618 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
619 {
620 LPWORD srcbits = (LPWORD)sbits;
621 WORD val;
622
623 /* FIXME: BI_BITFIELDS not supported yet */
624 for( y = 0; y < lines; y++) {
625 for( x = 0; x < srcwidth; x++ ) {
626 val = *srcbits++;
Karl Lessard41875791999-09-03 16:49:17 +0000627 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000628 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
629 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
Karl Lessard41875791999-09-03 16:49:17 +0000630 }
Huw D M Davies1bb98601999-09-19 12:04:17 +0000631 dstbits = (LPBYTE)(dbits+=dstwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000632 srcbits = (LPWORD)(sbits+=srcwidthb);
633 }
634 }
635 break;
636
637 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
638 {
639 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
640 memcpy(dbits, sbits, srcwidthb);
641 }
642 break;
643
644 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
645 {
646 LPBYTE srcbits = (LPBYTE)sbits;
647
648 for( y = 0; y < lines; y++) {
649 for( x = 0; x < srcwidth; x++, srcbits++ ) {
650 *dstbits++ = *srcbits++;
651 *dstbits++ = *srcbits++;
652 *dstbits++ = *srcbits++;
653 }
654 dstbits=(LPBYTE)(dbits+=dstwidthb);
655 srcbits = (LPBYTE)(sbits+=srcwidthb);
656 }
657 }
658 break;
659
660 default: /* ? bit bmp -> 24 bit DIB */
661 FIXME("24 bit DIB %d bit bitmap\n",
662 bmp->bitmap.bmBitsPixel);
663 break;
664 }
665 }
666 break;
667
668 case 32: /* 32 bpp dstDIB */
669 {
670 LPDWORD dstbits = (LPDWORD)dbits;
Karl Lessard41875791999-09-03 16:49:17 +0000671
672 /* FIXME: BI_BITFIELDS not supported yet */
673
674 switch(bmp->dib->dsBm.bmBitsPixel) {
675 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
676 {
677 LPWORD srcbits = (LPWORD)sbits;
678 DWORD val;
679
680 /* FIXME: BI_BITFIELDS not supported yet */
681 for( y = 0; y < lines; y++) {
682 for( x = 0; x < srcwidth; x++ ) {
683 val = (DWORD)*srcbits++;
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000684 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
Karl Lessard41875791999-09-03 16:49:17 +0000685 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000686 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
Karl Lessard41875791999-09-03 16:49:17 +0000687 }
Huw D M Davies1bb98601999-09-19 12:04:17 +0000688 dstbits=(LPDWORD)(dbits+=dstwidthb);
689 srcbits=(LPWORD)(sbits+=srcwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000690 }
691 }
692 break;
693
694 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
695 {
Huw D M Davies1bb98601999-09-19 12:04:17 +0000696 LPBYTE srcbits = sbits;
Karl Lessard41875791999-09-03 16:49:17 +0000697
698 for( y = 0; y < lines; y++) {
Karl Lessardc73a1fd1999-09-19 14:15:41 +0000699 for( x = 0; x < srcwidth; x++, srcbits+=3 )
700 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
Huw D M Davies1bb98601999-09-19 12:04:17 +0000701 dstbits=(LPDWORD)(dbits+=dstwidthb);
Karl Lessard41875791999-09-03 16:49:17 +0000702 srcbits=(sbits+=srcwidthb);
703 }
704 }
705 break;
706
707 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
708 {
709 /* FIXME: BI_BITFIELDS not supported yet */
710 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
711 memcpy(dbits, sbits, srcwidthb);
712 }
713 break;
714
715 default: /* ? bit bmp -> 16 bit DIB */
716 FIXME("15/16 bit DIB %d bit bitmap\n",
717 bmp->bitmap.bmBitsPixel);
718 break;
719 }
720 }
721 break;
722
723 default: /* ? bit DIB */
724 FIXME("Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
725 break;
726 }
727 }
728 /* Otherwise, get bits from the XImage */
729 else if(!BITMAP_Driver->pGetDIBits(bmp, dc, startscan, lines, bits, info, coloruse, hbitmap))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000730 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000731 GDI_HEAP_UNLOCK( hdc );
732 GDI_HEAP_UNLOCK( hbitmap );
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000733
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000734 return FALSE;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000735 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000736 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000737 else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
738 {
739 /* fill in struct members */
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000740
741 if( info->bmiHeader.biBitCount == 0)
742 {
743 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
744 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
745 info->bmiHeader.biPlanes = 1;
746 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
Huw D M Davies608629b1999-04-18 12:07:00 +0000747 info->bmiHeader.biSizeImage =
748 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
749 bmp->bitmap.bmHeight,
750 bmp->bitmap.bmBitsPixel );
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000751 info->bmiHeader.biCompression = 0;
752 }
753 else
754 {
Huw D M Davies608629b1999-04-18 12:07:00 +0000755 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
756 info->bmiHeader.biWidth,
757 info->bmiHeader.biHeight,
758 info->bmiHeader.biBitCount );
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000759 }
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000760 }
Huw D M Daviescc3e5d71999-03-25 10:48:01 +0000761
Alexandre Julliard15657091999-05-23 10:25:25 +0000762 TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
Huw D M Davies3da9ff31999-02-24 09:47:37 +0000763 info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
764 info->bmiHeader.biHeight);
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000765
766 GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000767 GDI_HEAP_UNLOCK( hbitmap );
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000768
Alexandre Julliard401710d1993-09-04 10:09:32 +0000769 return lines;
770}
771
772
773/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000774 * CreateDIBitmap16 (GDI.442)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000775 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000776HBITMAP16 WINAPI CreateDIBitmap16( HDC16 hdc, const BITMAPINFOHEADER * header,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000777 DWORD init, LPCVOID bits, const BITMAPINFO * data,
778 UINT16 coloruse )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000779{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000780 return CreateDIBitmap( hdc, header, init, bits, data, coloruse );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000781}
782
783
784/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000785 * CreateDIBitmap (GDI32.37)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000786 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000787HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000788 DWORD init, LPCVOID bits, const BITMAPINFO *data,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000789 UINT coloruse )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000790{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000791 HBITMAP handle;
792 BOOL fColor;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000793 DWORD width;
794 int height;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000795 WORD bpp;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000796 WORD compr;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000797
Alexandre Julliarda845b881998-06-01 10:44:35 +0000798 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000799 if (height < 0) height = -height;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000800
801 /* Check if we should create a monochrome or color bitmap. */
802 /* We create a monochrome bitmap only if it has exactly 2 */
Francois Boisvert3d696d91999-09-23 11:40:38 +0000803 /* colors, which are black followed by white, nothing else. */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000804 /* In all other cases, we create a color bitmap. */
805
806 if (bpp != 1) fColor = TRUE;
807 else if ((coloruse != DIB_RGB_COLORS) ||
808 (init != CBM_INIT) || !data) fColor = FALSE;
809 else
810 {
811 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
812 {
813 RGBQUAD *rgb = data->bmiColors;
814 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
Francois Boisvert3d696d91999-09-23 11:40:38 +0000815
816 /* Check if the first color of the colormap is black */
817 if ((col == RGB(0,0,0)))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000818 {
819 rgb++;
820 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
Francois Boisvert3d696d91999-09-23 11:40:38 +0000821 /* If the second color is white, create a monochrome bitmap */
822 fColor = (col != RGB(0xff,0xff,0xff));
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000823 }
Francois Boisvert3d696d91999-09-23 11:40:38 +0000824 /* Note : If the first color of the colormap is white
825 followed by black, we have to create a color bitmap.
826 If we don't the white will be displayed in black later on!*/
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000827 else fColor = TRUE;
828 }
829 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
830 {
831 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
832 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
Francois Boisvert3d696d91999-09-23 11:40:38 +0000833 if ((col == RGB(0,0,0)))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000834 {
835 rgb++;
836 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
Francois Boisvert3d696d91999-09-23 11:40:38 +0000837 fColor = (col != RGB(0xff,0xff,0xff));
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000838 }
839 else fColor = TRUE;
840 }
841 else
842 {
Alexandre Julliard15657091999-05-23 10:25:25 +0000843 WARN("(%ld): wrong size for data\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000844 data->bmiHeader.biSize );
845 return 0;
846 }
847 }
848
849 /* Now create the bitmap */
850
Alexandre Julliard946a4442000-07-30 13:50:27 +0000851 if (fColor)
852 {
853 HDC tmpdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
854 handle = CreateCompatibleBitmap( tmpdc, width, height );
855 DeleteDC( tmpdc );
856 }
857 else handle = CreateBitmap( width, height, 1, 1, NULL );
858
Alexandre Julliard401710d1993-09-04 10:09:32 +0000859 if (!handle) return 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000860
861 if (init == CBM_INIT)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000862 SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000863 return handle;
864}
Alexandre Julliard77b99181997-09-14 17:17:23 +0000865
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000866/***********************************************************************
867 * CreateDIBSection16 (GDI.489)
868 */
869HBITMAP16 WINAPI CreateDIBSection16 (HDC16 hdc, BITMAPINFO *bmi, UINT16 usage,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000870 SEGPTR *bits, HANDLE section,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000871 DWORD offset)
872{
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000873 HBITMAP16 hbitmap;
Stephane Lussier23259ce2000-07-11 22:04:44 +0000874 DC *dc;
875 BOOL bDesktopDC = FALSE;
876
877 /* If the reference hdc is null, take the desktop dc */
878 if (hdc == 0)
879 {
880 hdc = CreateCompatibleDC(0);
881 bDesktopDC = TRUE;
882 }
883
884 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000885 if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
886 if(!dc) return (HBITMAP16) NULL;
Ulrich Weigand4f85bad1999-02-09 15:30:22 +0000887
Ove Kaaven8b9f3382000-04-29 16:47:07 +0000888 hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset, 0);
889
890 GDI_HEAP_UNLOCK(hdc);
891
Stephane Lussier23259ce2000-07-11 22:04:44 +0000892 if (bDesktopDC)
893 DeleteDC(hdc);
894
Ove Kaaven8b9f3382000-04-29 16:47:07 +0000895 return hbitmap;
896}
897
898/***********************************************************************
899 * DIB_CreateDIBSection
900 */
901HBITMAP DIB_CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
902 LPVOID *bits, HANDLE section,
903 DWORD offset, DWORD ovr_pitch)
904{
905 HBITMAP hbitmap;
Stephane Lussier23259ce2000-07-11 22:04:44 +0000906 DC *dc;
907 BOOL bDesktopDC = FALSE;
908
909 /* If the reference hdc is null, take the desktop dc */
910 if (hdc == 0)
911 {
912 hdc = CreateCompatibleDC(0);
913 bDesktopDC = TRUE;
914 }
915
916 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
Ove Kaaven8b9f3382000-04-29 16:47:07 +0000917 if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
918 if(!dc) return (HBITMAP) NULL;
919
920 hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset, ovr_pitch);
Ulrich Weigand4f85bad1999-02-09 15:30:22 +0000921
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000922 GDI_HEAP_UNLOCK(hdc);
Ulrich Weigand4f85bad1999-02-09 15:30:22 +0000923
Stephane Lussier23259ce2000-07-11 22:04:44 +0000924 if (bDesktopDC)
925 DeleteDC(hdc);
926
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000927 return hbitmap;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000928}
929
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000930/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000931 * CreateDIBSection (GDI32.36)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000932 */
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000933HBITMAP WINAPI CreateDIBSection(HDC hdc, BITMAPINFO *bmi, UINT usage,
934 LPVOID *bits, HANDLE section,
935 DWORD offset)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000936{
Ove Kaaven8b9f3382000-04-29 16:47:07 +0000937 return DIB_CreateDIBSection(hdc, bmi, usage, bits, section, offset, 0);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000938}
Alexandre Julliarda845b881998-06-01 10:44:35 +0000939
Alexandre Julliard642d3131998-07-12 19:29:36 +0000940/***********************************************************************
941 * DIB_DeleteDIBSection
942 */
943void DIB_DeleteDIBSection( BITMAPOBJ *bmp )
944{
945 if (bmp && bmp->dib)
946 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000947 DIBSECTION *dib = bmp->dib;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000948
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000949 if (dib->dsBm.bmBits)
Jesper Skov5c3e4571998-11-01 19:27:22 +0000950 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000951 if (dib->dshSection)
952 UnmapViewOfFile(dib->dsBm.bmBits);
Ove Kaaven8b9f3382000-04-29 16:47:07 +0000953 else if (!dib->dsOffset)
Marcus Meissner718b0e42000-01-23 02:18:52 +0000954 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
Jesper Skov5c3e4571998-11-01 19:27:22 +0000955 }
Alexandre Julliard642d3131998-07-12 19:29:36 +0000956
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000957 BITMAP_Driver->pDeleteDIBSection(bmp);
Ulrich Weigand4f85bad1999-02-09 15:30:22 +0000958
Alexandre Julliard642d3131998-07-12 19:29:36 +0000959 HeapFree(GetProcessHeap(), 0, dib);
960 bmp->dib = NULL;
961 }
962}
963
Turchanov Sergey9cd4df11998-10-18 13:39:41 +0000964/***********************************************************************
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000965 * DIB_CreateDIBFromBitmap
966 * Allocates a packed DIB and copies the bitmap data into it.
967 */
968HGLOBAL DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp)
969{
970 BITMAPOBJ *pBmp = NULL;
971 HGLOBAL hPackedDIB = 0;
972 LPBYTE pPackedDIB = NULL;
973 LPBITMAPINFOHEADER pbmiHeader = NULL;
974 unsigned int width, height, depth, cDataSize = 0, cPackedSize = 0,
975 OffsetBits = 0, nLinesCopied = 0;
976
977 /* Get a pointer to the BITMAPOBJ structure */
978 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
979
980 /* Get the bitmap dimensions */
981 width = pBmp->bitmap.bmWidth;
982 height = pBmp->bitmap.bmHeight;
983 depth = pBmp->bitmap.bmBitsPixel;
984
985 /*
986 * A packed DIB contains a BITMAPINFO structure followed immediately by
987 * an optional color palette and the pixel data.
988 */
989
990 /* Calculate the size of the packed DIB */
991 cDataSize = DIB_GetDIBImageBytes( width, height, depth );
992 cPackedSize = sizeof(BITMAPINFOHEADER)
993 + ( (depth <= 8) ? (sizeof(RGBQUAD) * (1 << depth)) : 0 )
994 + cDataSize;
995 /* Get the offset to the bits */
996 OffsetBits = cPackedSize - cDataSize;
997
998 /* Allocate the packed DIB */
999 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
1000 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE /*| GMEM_ZEROINIT*/,
1001 cPackedSize );
1002 if ( !hPackedDIB )
1003 {
1004 WARN("Could not allocate packed DIB!\n");
1005 goto END;
1006 }
1007
1008 /* A packed DIB starts with a BITMAPINFOHEADER */
1009 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1010 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
1011
1012 /* Init the BITMAPINFOHEADER */
1013 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
1014 pbmiHeader->biWidth = width;
1015 pbmiHeader->biHeight = height;
1016 pbmiHeader->biPlanes = 1;
1017 pbmiHeader->biBitCount = depth;
1018 pbmiHeader->biCompression = BI_RGB;
1019 pbmiHeader->biSizeImage = 0;
1020 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
1021 pbmiHeader->biClrUsed = 0;
1022 pbmiHeader->biClrImportant = 0;
1023
1024 /* Retrieve the DIB bits from the bitmap and fill in the
1025 * DIB color table if present */
1026
1027 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
1028 hBmp, /* Handle to bitmap */
1029 0, /* First scan line to set in dest bitmap */
1030 height, /* Number of scan lines to copy */
1031 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
1032 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
1033 0); /* RGB or palette index */
1034 GlobalUnlock(hPackedDIB);
1035
1036 /* Cleanup if GetDIBits failed */
1037 if (nLinesCopied != height)
1038 {
1039 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, height);
1040 GlobalFree(hPackedDIB);
1041 hPackedDIB = 0;
1042 }
1043
1044END:
1045 return hPackedDIB;
1046}