* Sync up to trunk head (r65120).
[reactos.git] / win32ss / gdi / ntgdi / bitmaps.c
1 /*
2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Bitmap functions
5 * FILE: subsys/win32k/objects/bitmaps.c
6 * PROGRAMER: Timo Kreuzer <timo.kreuzer@reactos.org>
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 void
15 NTAPI
16 UnsafeSetBitmapBits(
17 PSURFACE psurf,
18 IN ULONG cjBits,
19 IN PVOID pvBits)
20 {
21 PUCHAR pjDst, pjSrc;
22 LONG lDeltaDst, lDeltaSrc;
23 ULONG nWidth, nHeight, cBitsPixel;
24
25 nWidth = psurf->SurfObj.sizlBitmap.cx;
26 nHeight = psurf->SurfObj.sizlBitmap.cy;
27 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
28
29 /* Get pointers */
30 pjDst = psurf->SurfObj.pvScan0;
31 pjSrc = pvBits;
32 lDeltaDst = psurf->SurfObj.lDelta;
33 lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
34
35 while (nHeight--)
36 {
37 /* Copy one line */
38 memcpy(pjDst, pjSrc, lDeltaSrc);
39 pjSrc += lDeltaSrc;
40 pjDst += lDeltaDst;
41 }
42
43 }
44
45 HBITMAP
46 NTAPI
47 GreCreateBitmapEx(
48 _In_ ULONG nWidth,
49 _In_ ULONG nHeight,
50 _In_ ULONG cjWidthBytes,
51 _In_ ULONG iFormat,
52 _In_ USHORT fjBitmap,
53 _In_ ULONG cjSizeImage,
54 _In_opt_ PVOID pvBits,
55 _In_ FLONG flags)
56 {
57 PSURFACE psurf;
58 HBITMAP hbmp;
59 PVOID pvCompressedBits = NULL;
60
61 /* Verify format */
62 if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
63
64 /* The infamous RLE hack */
65 if ((iFormat == BMF_4RLE) || (iFormat == BMF_8RLE))
66 {
67 pvCompressedBits = pvBits;
68 pvBits = NULL;
69 iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
70 }
71
72 /* Allocate a surface */
73 psurf = SURFACE_AllocSurface(STYPE_BITMAP,
74 nWidth,
75 nHeight,
76 iFormat,
77 fjBitmap,
78 cjWidthBytes,
79 pvBits);
80 if (!psurf)
81 {
82 DPRINT1("SURFACE_AllocSurface failed.\n");
83 return NULL;
84 }
85
86 /* The infamous RLE hack */
87 if (pvCompressedBits)
88 {
89 SIZEL sizl;
90 LONG lDelta;
91
92 sizl.cx = nWidth;
93 sizl.cy = nHeight;
94 lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]);
95
96 pvBits = psurf->SurfObj.pvBits;
97 DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat);
98 }
99
100 /* Get the handle for the bitmap */
101 hbmp = (HBITMAP)psurf->SurfObj.hsurf;
102
103 /* Mark as API bitmap */
104 psurf->flags |= (flags | API_BITMAP);
105
106 /* Unlock the surface and return */
107 SURFACE_UnlockSurface(psurf);
108 return hbmp;
109 }
110
111 /* Creates a DDB surface,
112 * as in CreateCompatibleBitmap or CreateBitmap.
113 * Note that each scanline must be 32bit aligned!
114 */
115 HBITMAP
116 NTAPI
117 GreCreateBitmap(
118 _In_ ULONG nWidth,
119 _In_ ULONG nHeight,
120 _In_ ULONG cPlanes,
121 _In_ ULONG cBitsPixel,
122 _In_opt_ PVOID pvBits)
123 {
124 /* Call the extended function */
125 return GreCreateBitmapEx(nWidth,
126 nHeight,
127 0, /* Auto width */
128 BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
129 0, /* No bitmap flags */
130 0, /* Auto size */
131 pvBits,
132 DDB_SURFACE /* DDB */);
133 }
134
135 HBITMAP
136 APIENTRY
137 NtGdiCreateBitmap(
138 IN INT nWidth,
139 IN INT nHeight,
140 IN UINT cPlanes,
141 IN UINT cBitsPixel,
142 IN OPTIONAL LPBYTE pUnsafeBits)
143 {
144 HBITMAP hbmp;
145 ULONG cRealBpp, cjWidthBytes, iFormat;
146 ULONGLONG cjSize;
147 PSURFACE psurf;
148
149 /* Calculate bitmap format and real bits per pixel. */
150 iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB);
151 cRealBpp = gajBitsPerFormat[iFormat];
152
153 /* Calculate width and image size in bytes */
154 cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp);
155 cjSize = (ULONGLONG)cjWidthBytes * nHeight;
156
157 /* Check parameters (possible overflow of cjSize!) */
158 if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) ||
159 (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL))
160 {
161 DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n",
162 nWidth, nHeight, cBitsPixel, cPlanes);
163 EngSetLastError(ERROR_INVALID_PARAMETER);
164 return NULL;
165 }
166
167 /* Allocate the surface (but don't set the bits) */
168 psurf = SURFACE_AllocSurface(STYPE_BITMAP,
169 nWidth,
170 nHeight,
171 iFormat,
172 0,
173 0,
174 NULL);
175 if (!psurf)
176 {
177 DPRINT1("SURFACE_AllocSurface failed.\n");
178 return NULL;
179 }
180
181 /* Mark as API and DDB bitmap */
182 psurf->flags |= (API_BITMAP | DDB_SURFACE);
183
184 /* Check if we have bits to set */
185 if (pUnsafeBits)
186 {
187 /* Protect with SEH and copy the bits */
188 _SEH2_TRY
189 {
190 ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1);
191 UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
192 }
193 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
194 {
195 GDIOBJ_vDeleteObject(&psurf->BaseObject);
196 _SEH2_YIELD(return NULL;)
197 }
198 _SEH2_END
199 }
200 else
201 {
202 /* Zero the bits */
203 RtlZeroMemory(psurf->SurfObj.pvBits, psurf->SurfObj.cjBits);
204 }
205
206 /* Get the handle for the bitmap */
207 hbmp = (HBITMAP)psurf->SurfObj.hsurf;
208
209 /* Unlock the surface */
210 SURFACE_UnlockSurface(psurf);
211
212 return hbmp;
213 }
214
215
216 HBITMAP FASTCALL
217 IntCreateCompatibleBitmap(
218 PDC Dc,
219 INT Width,
220 INT Height,
221 UINT Planes,
222 UINT Bpp)
223 {
224 HBITMAP Bmp = NULL;
225 PPALETTE ppal;
226
227 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
228 if (0 == Width || 0 == Height)
229 {
230 return NtGdiGetStockObject(DEFAULT_BITMAP);
231 }
232
233 if (Dc->dctype != DC_TYPE_MEMORY)
234 {
235 PSURFACE psurf;
236
237 Bmp = GreCreateBitmap(abs(Width),
238 abs(Height),
239 Planes ? Planes : 1,
240 Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel,
241 NULL);
242 if (Bmp == NULL)
243 {
244 DPRINT1("Failed to allocate a bitmap!\n");
245 return NULL;
246 }
247
248 psurf = SURFACE_ShareLockSurface(Bmp);
249 ASSERT(psurf);
250
251 /* Dereference old palette and set new palette */
252 ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
253 ASSERT(ppal);
254 SURFACE_vSetPalette(psurf, ppal);
255 PALETTE_ShareUnlockPalette(ppal);
256
257 /* Set flags */
258 psurf->flags = API_BITMAP;
259 psurf->hdc = NULL; // FIXME:
260 psurf->SurfObj.hdev = (HDEV)Dc->ppdev;
261 SURFACE_ShareUnlockSurface(psurf);
262 }
263 else
264 {
265 DIBSECTION dibs;
266 INT Count;
267 PSURFACE psurf = Dc->dclevel.pSurface;
268 if(!psurf) psurf = psurfDefaultBitmap;
269 Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
270
271 if (Count == sizeof(BITMAP))
272 {
273 PSURFACE psurfBmp;
274
275 Bmp = GreCreateBitmap(abs(Width),
276 abs(Height),
277 Planes ? Planes : 1,
278 Bpp ? Bpp : dibs.dsBm.bmBitsPixel,
279 NULL);
280 psurfBmp = SURFACE_ShareLockSurface(Bmp);
281 ASSERT(psurfBmp);
282
283 /* Dereference old palette and set new palette */
284 SURFACE_vSetPalette(psurfBmp, psurf->ppal);
285
286 /* Set flags */
287 psurfBmp->flags = API_BITMAP;
288 psurfBmp->hdc = NULL; // FIXME:
289 psurf->SurfObj.hdev = (HDEV)Dc->ppdev;
290 SURFACE_ShareUnlockSurface(psurfBmp);
291 }
292 else if (Count == sizeof(DIBSECTION))
293 {
294 /* A DIB section is selected in the DC */
295 BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
296 PVOID Bits;
297 BITMAPINFO* bi = (BITMAPINFO*)buf;
298
299 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
300 bi->bmiHeader.biWidth = Width;
301 bi->bmiHeader.biHeight = Height;
302 bi->bmiHeader.biPlanes = Planes ? Planes : dibs.dsBmih.biPlanes;
303 bi->bmiHeader.biBitCount = Bpp ? Bpp : dibs.dsBmih.biBitCount;
304 bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
305 bi->bmiHeader.biSizeImage = 0;
306 bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
307 bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
308 bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed;
309 bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant;
310
311 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
312 {
313 /* Copy the color masks */
314 RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
315 }
316 else if (bi->bmiHeader.biBitCount <= 8)
317 {
318 /* Copy the color table */
319 UINT Index;
320 PPALETTE PalGDI;
321
322 if (!psurf->ppal)
323 {
324 EngSetLastError(ERROR_INVALID_HANDLE);
325 return 0;
326 }
327
328 PalGDI = psurf->ppal;
329
330 for (Index = 0;
331 Index < 256 && Index < PalGDI->NumColors;
332 Index++)
333 {
334 bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed;
335 bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
336 bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
337 bi->bmiColors[Index].rgbReserved = 0;
338 }
339 }
340
341 Bmp = DIB_CreateDIBSection(Dc,
342 bi,
343 DIB_RGB_COLORS,
344 &Bits,
345 NULL,
346 0,
347 0);
348 return Bmp;
349 }
350 }
351 return Bmp;
352 }
353
354 HBITMAP APIENTRY
355 NtGdiCreateCompatibleBitmap(
356 HDC hDC,
357 INT Width,
358 INT Height)
359 {
360 HBITMAP Bmp;
361 PDC Dc;
362
363 /* Check parameters */
364 if ((Width <= 0) || (Height <= 0) || ((Width * Height) > 0x3FFFFFFF))
365 {
366 EngSetLastError(ERROR_INVALID_PARAMETER);
367 return NULL;
368 }
369
370 if (!hDC)
371 return GreCreateBitmap(Width, Height, 1, 1, 0);
372
373 Dc = DC_LockDc(hDC);
374
375 DPRINT("NtGdiCreateCompatibleBitmap(%p,%d,%d, bpp:%u) = \n",
376 hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel);
377
378 if (NULL == Dc)
379 {
380 EngSetLastError(ERROR_INVALID_HANDLE);
381 return NULL;
382 }
383
384 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height, 0, 0);
385
386 DC_UnlockDc(Dc);
387 return Bmp;
388 }
389
390 BOOL
391 APIENTRY
392 NtGdiGetBitmapDimension(
393 HBITMAP hBitmap,
394 LPSIZE psizDim)
395 {
396 PSURFACE psurfBmp;
397 BOOL bResult = TRUE;
398
399 if (hBitmap == NULL)
400 return FALSE;
401
402 /* Lock the bitmap */
403 psurfBmp = SURFACE_ShareLockSurface(hBitmap);
404 if (psurfBmp == NULL)
405 {
406 EngSetLastError(ERROR_INVALID_HANDLE);
407 return FALSE;
408 }
409
410 /* Use SEH to copy the data to the caller */
411 _SEH2_TRY
412 {
413 ProbeForWrite(psizDim, sizeof(SIZE), 1);
414 *psizDim = psurfBmp->sizlDim;
415 }
416 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
417 {
418 bResult = FALSE;
419 }
420 _SEH2_END
421
422 /* Unlock the bitmap */
423 SURFACE_ShareUnlockSurface(psurfBmp);
424
425 return bResult;
426 }
427
428
429 VOID
430 FASTCALL
431 UnsafeGetBitmapBits(
432 PSURFACE psurf,
433 DWORD Bytes,
434 OUT PBYTE pvBits)
435 {
436 PUCHAR pjDst, pjSrc;
437 LONG lDeltaDst, lDeltaSrc;
438 ULONG nWidth, nHeight, cBitsPixel;
439
440 nWidth = psurf->SurfObj.sizlBitmap.cx;
441 nHeight = psurf->SurfObj.sizlBitmap.cy;
442 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
443
444 /* Get pointers */
445 pjSrc = psurf->SurfObj.pvScan0;
446 pjDst = pvBits;
447 lDeltaSrc = psurf->SurfObj.lDelta;
448 lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
449
450 while (nHeight--)
451 {
452 /* Copy one line */
453 RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
454 pjSrc += lDeltaSrc;
455 pjDst += lDeltaDst;
456 }
457 }
458
459 LONG
460 APIENTRY
461 NtGdiGetBitmapBits(
462 HBITMAP hBitmap,
463 ULONG cjBuffer,
464 OUT OPTIONAL PBYTE pUnsafeBits)
465 {
466 PSURFACE psurf;
467 ULONG cjSize;
468 LONG ret;
469
470 /* Check parameters */
471 if (pUnsafeBits != NULL && cjBuffer == 0)
472 {
473 return 0;
474 }
475
476 /* Lock the bitmap */
477 psurf = SURFACE_ShareLockSurface(hBitmap);
478 if (!psurf)
479 {
480 EngSetLastError(ERROR_INVALID_HANDLE);
481 return 0;
482 }
483
484 /* Calculate the size of the bitmap in bytes */
485 cjSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx,
486 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
487 abs(psurf->SurfObj.sizlBitmap.cy);
488
489 /* If the bits vector is null, the function should return the read size */
490 if (pUnsafeBits == NULL)
491 {
492 SURFACE_ShareUnlockSurface(psurf);
493 return cjSize;
494 }
495
496 /* Don't copy more bytes than the buffer has */
497 cjBuffer = min(cjBuffer, cjSize);
498
499 // FIXME: Use MmSecureVirtualMemory
500 _SEH2_TRY
501 {
502 ProbeForWrite(pUnsafeBits, cjBuffer, 1);
503 UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
504 ret = cjBuffer;
505 }
506 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
507 {
508 ret = 0;
509 }
510 _SEH2_END
511
512 SURFACE_ShareUnlockSurface(psurf);
513
514 return ret;
515 }
516
517
518 LONG APIENTRY
519 NtGdiSetBitmapBits(
520 HBITMAP hBitmap,
521 DWORD Bytes,
522 IN PBYTE pUnsafeBits)
523 {
524 LONG ret;
525 PSURFACE psurf;
526
527 if (pUnsafeBits == NULL || Bytes == 0)
528 {
529 return 0;
530 }
531
532 psurf = SURFACE_ShareLockSurface(hBitmap);
533 if (psurf == NULL)
534 {
535 EngSetLastError(ERROR_INVALID_HANDLE);
536 return 0;
537 }
538
539 _SEH2_TRY
540 {
541 ProbeForRead(pUnsafeBits, Bytes, 1);
542 UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
543 ret = 1;
544 }
545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
546 {
547 ret = 0;
548 }
549 _SEH2_END
550
551 SURFACE_ShareUnlockSurface(psurf);
552
553 return ret;
554 }
555
556 BOOL APIENTRY
557 NtGdiSetBitmapDimension(
558 HBITMAP hBitmap,
559 INT Width,
560 INT Height,
561 LPSIZE Size)
562 {
563 PSURFACE psurf;
564 BOOL Ret = TRUE;
565
566 if (hBitmap == NULL)
567 return FALSE;
568
569 psurf = SURFACE_ShareLockSurface(hBitmap);
570 if (psurf == NULL)
571 {
572 EngSetLastError(ERROR_INVALID_HANDLE);
573 return FALSE;
574 }
575
576 if (Size)
577 {
578 _SEH2_TRY
579 {
580 ProbeForWrite(Size, sizeof(SIZE), 1);
581 *Size = psurf->sizlDim;
582 }
583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
584 {
585 Ret = FALSE;
586 }
587 _SEH2_END
588 }
589
590 /* The dimension is changed even if writing the old value failed */
591 psurf->sizlDim.cx = Width;
592 psurf->sizlDim.cy = Height;
593
594 SURFACE_ShareUnlockSurface(psurf);
595
596 return Ret;
597 }
598
599 /* Internal Functions */
600
601 HBITMAP
602 FASTCALL
603 BITMAP_CopyBitmap(HBITMAP hBitmap)
604 {
605 HBITMAP hbmNew;
606 SURFACE *psurfSrc, *psurfNew;
607
608 /* Fail, if no source bitmap is given */
609 if (hBitmap == NULL) return 0;
610
611 /* Lock the source bitmap */
612 psurfSrc = SURFACE_ShareLockSurface(hBitmap);
613 if (psurfSrc == NULL)
614 {
615 return 0;
616 }
617
618 /* Allocate a new bitmap with the same dimensions as the source bmp */
619 hbmNew = GreCreateBitmapEx(psurfSrc->SurfObj.sizlBitmap.cx,
620 psurfSrc->SurfObj.sizlBitmap.cy,
621 abs(psurfSrc->SurfObj.lDelta),
622 psurfSrc->SurfObj.iBitmapFormat,
623 psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN,
624 psurfSrc->SurfObj.cjBits,
625 NULL,
626 psurfSrc->flags);
627
628 if (hbmNew)
629 {
630 /* Lock the new bitmap */
631 psurfNew = SURFACE_ShareLockSurface(hbmNew);
632 if (psurfNew)
633 {
634 /* Copy the bitmap bits to the new bitmap buffer */
635 RtlCopyMemory(psurfNew->SurfObj.pvBits,
636 psurfSrc->SurfObj.pvBits,
637 psurfNew->SurfObj.cjBits);
638
639
640 /* Reference the palette of the source bitmap and use it */
641 SURFACE_vSetPalette(psurfNew, psurfSrc->ppal);
642
643 /* Unlock the new surface */
644 SURFACE_ShareUnlockSurface(psurfNew);
645 }
646 else
647 {
648 /* Failed to lock the bitmap, shouldn't happen */
649 GreDeleteObject(hbmNew);
650 hbmNew = NULL;
651 }
652 }
653
654 /* Unlock the source bitmap and return the handle of the new bitmap */
655 SURFACE_ShareUnlockSurface(psurfSrc);
656 return hbmNew;
657 }
658
659 INT APIENTRY
660 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
661 {
662 PBITMAP pBitmap;
663
664 if (!buffer) return sizeof(BITMAP);
665 if ((UINT)Count < sizeof(BITMAP)) return 0;
666
667 /* Always fill a basic BITMAP structure */
668 pBitmap = buffer;
669 pBitmap->bmType = 0;
670 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
671 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
672 pBitmap->bmPlanes = 1;
673 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
674 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel);
675
676 /* Check for DIB section */
677 if (psurf->hSecure)
678 {
679 /* Set bmBits in this case */
680 pBitmap->bmBits = psurf->SurfObj.pvBits;
681 /* DIBs data are 32 bits aligned */
682 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel);
683
684 if (Count >= sizeof(DIBSECTION))
685 {
686 /* Fill rest of DIBSECTION */
687 PDIBSECTION pds = buffer;
688
689 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
690 pds->dsBmih.biWidth = pds->dsBm.bmWidth;
691 pds->dsBmih.biHeight = pds->dsBm.bmHeight;
692 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
693 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
694
695 switch (psurf->SurfObj.iBitmapFormat)
696 {
697 case BMF_1BPP:
698 case BMF_4BPP:
699 case BMF_8BPP:
700 pds->dsBmih.biCompression = BI_RGB;
701 break;
702
703 case BMF_16BPP:
704 if (psurf->ppal->flFlags & PAL_RGB16_555)
705 pds->dsBmih.biCompression = BI_RGB;
706 else
707 pds->dsBmih.biCompression = BI_BITFIELDS;
708 break;
709
710 case BMF_24BPP:
711 case BMF_32BPP:
712 /* 24/32bpp BI_RGB is actually BGR format */
713 if (psurf->ppal->flFlags & PAL_BGR)
714 pds->dsBmih.biCompression = BI_RGB;
715 else
716 pds->dsBmih.biCompression = BI_BITFIELDS;
717 break;
718
719 case BMF_4RLE:
720 pds->dsBmih.biCompression = BI_RLE4;
721 break;
722 case BMF_8RLE:
723 pds->dsBmih.biCompression = BI_RLE8;
724 break;
725 case BMF_JPEG:
726 pds->dsBmih.biCompression = BI_JPEG;
727 break;
728 case BMF_PNG:
729 pds->dsBmih.biCompression = BI_PNG;
730 break;
731 default:
732 ASSERT(FALSE); /* This shouldn't happen */
733 }
734
735 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
736 pds->dsBmih.biXPelsPerMeter = 0;
737 pds->dsBmih.biYPelsPerMeter = 0;
738 pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
739 pds->dsBmih.biClrImportant = psurf->biClrImportant;
740 pds->dsBitfields[0] = psurf->ppal->RedMask;
741 pds->dsBitfields[1] = psurf->ppal->GreenMask;
742 pds->dsBitfields[2] = psurf->ppal->BlueMask;
743 pds->dshSection = psurf->hDIBSection;
744 pds->dsOffset = psurf->dwOffset;
745
746 return sizeof(DIBSECTION);
747 }
748 }
749 else
750 {
751 /* Not set according to wine test, confirmed in win2k */
752 pBitmap->bmBits = NULL;
753 }
754
755 return sizeof(BITMAP);
756 }
757
758 /*
759 * @implemented
760 */
761 HDC
762 APIENTRY
763 NtGdiGetDCforBitmap(
764 IN HBITMAP hsurf)
765 {
766 HDC hdc = NULL;
767 PSURFACE psurf = SURFACE_ShareLockSurface(hsurf);
768 if (psurf)
769 {
770 hdc = psurf->hdc;
771 SURFACE_ShareUnlockSurface(psurf);
772 }
773 return hdc;
774 }
775
776
777 /* EOF */