- Allocate memory from PagedPool instead of NonPagedPool where possible.
[reactos.git] / reactos / subsys / win32k / objects / dib.c
1 /*
2 * $Id: dib.c,v 1.51 2004/06/20 00:45:37 navaraf Exp $
3 *
4 * ReactOS W32 Subsystem
5 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 #include <w32k.h>
22
23 UINT STDCALL
24 NtGdiSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
25 {
26 PDC dc;
27 PBITMAPOBJ BitmapObj;
28
29 if (!(dc = DC_LockDc(hDC))) return 0;
30
31 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
32 if (BitmapObj == NULL)
33 {
34 DC_UnlockDc(hDC);
35 SetLastWin32Error(ERROR_INVALID_PARAMETER);
36 return 0;
37 }
38
39 if (BitmapObj->dib == NULL)
40 {
41 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
42 DC_UnlockDc(hDC);
43 SetLastWin32Error(ERROR_INVALID_PARAMETER);
44 return 0;
45 }
46
47 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
48 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
49 {
50 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
51 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
52
53 MmCopyFromCaller(BitmapObj->ColorMap + StartIndex, Colors, Entries * sizeof(RGBQUAD));
54
55 /* Rebuild the palette. */
56 NtGdiDeleteObject(dc->w.hPalette);
57 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED,
58 1 << BitmapObj->dib->dsBmih.biBitCount,
59 (PULONG)BitmapObj->ColorMap, 0, 0, 0);
60 }
61 else
62 Entries = 0;
63
64 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
65 DC_UnlockDc(hDC);
66
67 return Entries;
68 }
69
70 UINT STDCALL
71 NtGdiGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors)
72 {
73 PDC dc;
74 PBITMAPOBJ BitmapObj;
75
76 if (!(dc = DC_LockDc(hDC))) return 0;
77
78 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
79 if (BitmapObj == NULL)
80 {
81 DC_UnlockDc(hDC);
82 SetLastWin32Error(ERROR_INVALID_PARAMETER);
83 return 0;
84 }
85
86 if (BitmapObj->dib == NULL)
87 {
88 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
89 DC_UnlockDc(hDC);
90 SetLastWin32Error(ERROR_INVALID_PARAMETER);
91 return 0;
92 }
93
94 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
95 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
96 {
97 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
98 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
99
100 MmCopyToCaller(Colors, BitmapObj->ColorMap + StartIndex, Entries * sizeof(RGBQUAD));
101 }
102 else
103 Entries = 0;
104
105 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
106 DC_UnlockDc(hDC);
107
108 return Entries;
109 }
110
111 // Converts a DIB to a device-dependent bitmap
112 static INT FASTCALL
113 IntSetDIBits(
114 PDC DC,
115 HBITMAP hBitmap,
116 UINT StartScan,
117 UINT ScanLines,
118 CONST VOID *Bits,
119 CONST BITMAPINFO *bmi,
120 UINT ColorUse)
121 {
122 BITMAPOBJ *bitmap;
123 HBITMAP SourceBitmap, DestBitmap;
124 INT result = 0;
125 BOOL copyBitsResult;
126 SURFOBJ *DestSurf, *SourceSurf;
127 PSURFGDI DestGDI;
128 SIZEL SourceSize;
129 POINTL ZeroPoint;
130 RECTL DestRect;
131 XLATEOBJ *XlateObj;
132 PPALGDI hDCPalette;
133 //RGBQUAD *lpRGB;
134 HPALETTE DDB_Palette, DIB_Palette;
135 ULONG DDB_Palette_Type, DIB_Palette_Type;
136 const BYTE *vBits = (const BYTE*)Bits;
137 INT scanDirection = 1, DIBWidth;
138
139 // Check parameters
140 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
141 {
142 return 0;
143 }
144
145 // Get RGB values
146 //if (ColorUse == DIB_PAL_COLORS)
147 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
148 //else
149 // lpRGB = &bmi->bmiColors[0];
150
151 // Create a temporary surface for the destination bitmap
152 DestBitmap = BitmapToSurf(bitmap, DC->GDIDevice);
153
154 DestSurf = (SURFOBJ*) AccessUserObject( (ULONG)DestBitmap );
155 DestGDI = (PSURFGDI) AccessInternalObjectFromUserObject( DestSurf );
156
157 // Create source surface
158 SourceSize.cx = bmi->bmiHeader.biWidth;
159 SourceSize.cy = abs(bmi->bmiHeader.biHeight);
160
161 // Determine width of DIB
162 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
163
164 // Determine DIB Vertical Orientation
165 if(bmi->bmiHeader.biHeight > 0)
166 {
167 scanDirection = -1;
168 vBits += DIBWidth * bmi->bmiHeader.biHeight - DIBWidth;
169 }
170
171 SourceBitmap = EngCreateBitmap(SourceSize,
172 DIBWidth * scanDirection,
173 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
174 0,
175 (PVOID)vBits );
176 SourceSurf = (SURFOBJ*)AccessUserObject((ULONG)SourceBitmap);
177
178 // Destination palette obtained from the hDC
179 hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
180 if (NULL == hDCPalette)
181 {
182 EngDeleteSurface((HSURF)SourceBitmap);
183 EngDeleteSurface((HSURF)DestBitmap);
184 BITMAPOBJ_UnlockBitmap(hBitmap);
185 SetLastWin32Error(ERROR_INVALID_HANDLE);
186 return 0;
187 }
188 DDB_Palette_Type = hDCPalette->Mode;
189 DDB_Palette = DC->DevInfo->hpalDefault;
190 PALETTE_UnlockPalette(DC->DevInfo->hpalDefault);
191
192 // Source palette obtained from the BITMAPINFO
193 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
194 if (NULL == DIB_Palette)
195 {
196 EngDeleteSurface((HSURF)SourceBitmap);
197 EngDeleteSurface((HSURF)DestBitmap);
198 BITMAPOBJ_UnlockBitmap(hBitmap);
199 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
200 return 0;
201 }
202
203 // Determine XLATEOBJ for color translation
204 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
205 if (NULL == XlateObj)
206 {
207 PALETTE_FreePalette(DIB_Palette);
208 EngDeleteSurface((HSURF)SourceBitmap);
209 EngDeleteSurface((HSURF)DestBitmap);
210 BITMAPOBJ_UnlockBitmap(hBitmap);
211 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
212 return 0;
213 }
214
215 // Zero point
216 ZeroPoint.x = 0;
217 ZeroPoint.y = 0;
218
219 // Determine destination rectangle
220 DestRect.top = 0;
221 DestRect.left = 0;
222 DestRect.right = SourceSize.cx;
223 DestRect.bottom = SourceSize.cy;
224
225 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
226
227 // If it succeeded, return number of scanlines copies
228 if(copyBitsResult == TRUE)
229 {
230 result = SourceSize.cy - 1;
231 }
232
233 // Clean up
234 EngDeleteXlate(XlateObj);
235 PALETTE_FreePalette(DIB_Palette);
236 EngDeleteSurface((HSURF)SourceBitmap);
237 EngDeleteSurface((HSURF)DestBitmap);
238
239 // if (ColorUse == DIB_PAL_COLORS)
240 // WinFree((LPSTR)lpRGB);
241
242 BITMAPOBJ_UnlockBitmap(hBitmap);
243
244 return result;
245 }
246
247 // Converts a DIB to a device-dependent bitmap
248 INT STDCALL
249 NtGdiSetDIBits(
250 HDC hDC,
251 HBITMAP hBitmap,
252 UINT StartScan,
253 UINT ScanLines,
254 CONST VOID *Bits,
255 CONST BITMAPINFO *bmi,
256 UINT ColorUse)
257 {
258 PDC Dc;
259 INT Ret;
260
261 Dc = DC_LockDc(hDC);
262 if (NULL == Dc)
263 {
264 SetLastWin32Error(ERROR_INVALID_HANDLE);
265 return 0;
266 }
267
268 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
269
270 DC_UnlockDc(hDC);
271
272 return Ret;
273 }
274
275 INT STDCALL
276 NtGdiSetDIBitsToDevice(
277 HDC hDC,
278 INT XDest,
279 INT YDest,
280 DWORD Width,
281 DWORD Height,
282 INT XSrc,
283 INT YSrc,
284 UINT StartScan,
285 UINT ScanLines,
286 CONST VOID *Bits,
287 CONST BITMAPINFO *bmi,
288 UINT ColorUse)
289 {
290 UNIMPLEMENTED;
291 return 0;
292 }
293
294 // Converts a device-dependent bitmap to a DIB
295 #if 0
296 INT STDCALL NtGdiGetDIBits(HDC hDC,
297 HBITMAP hBitmap,
298 UINT StartScan,
299 UINT ScanLines,
300 LPVOID Bits,
301 LPBITMAPINFO UnsafeInfo,
302 UINT Usage)
303 #else
304 INT STDCALL NtGdiGetDIBits(
305 HDC hdc, /* [in] Handle to device context */
306 HBITMAP hbitmap, /* [in] Handle to bitmap */
307 UINT startscan, /* [in] First scan line to set in dest bitmap */
308 UINT lines, /* [in] Number of scan lines to copy */
309 LPVOID bits, /* [out] Address of array for bitmap bits */
310 BITMAPINFO * info, /* [out] Address of structure with bitmap data */
311 UINT coloruse) /* [in] RGB or palette index */
312 #endif
313 {
314 #if 0
315 BITMAPINFO Info;
316 BITMAPCOREHEADER *Core;
317 PBITMAPOBJ BitmapObj;
318 INT Result;
319 NTSTATUS Status;
320 PDC DCObj;
321 PPALGDI PalGdi;
322 struct
323 {
324 BITMAPINFO Info;
325 DWORD BitFields[3];
326 } InfoWithBitFields;
327 DWORD *BitField;
328 DWORD InfoSize;
329
330 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
331 if (NULL == BitmapObj)
332 {
333 SetLastWin32Error(ERROR_INVALID_HANDLE);
334 return 0;
335 }
336
337 RtlZeroMemory(&Info, sizeof(BITMAPINFO));
338 Status = MmCopyFromCaller(&(Info.bmiHeader.biSize),
339 &(UnsafeInfo->bmiHeader.biSize),
340 sizeof(DWORD));
341 if (! NT_SUCCESS(Status))
342 {
343 SetLastNtError(Status);
344 BITMAPOBJ_UnlockBitmap(hBitmap);
345 return 0;
346 }
347
348 /* If the bits are not requested, UnsafeInfo can point to either a
349 BITMAPINFOHEADER or a BITMAPCOREHEADER */
350 if (sizeof(BITMAPINFOHEADER) != Info.bmiHeader.biSize &&
351 (sizeof(BITMAPCOREHEADER) != Info.bmiHeader.biSize ||
352 NULL != Bits))
353 {
354 SetLastWin32Error(ERROR_INVALID_PARAMETER);
355 BITMAPOBJ_UnlockBitmap(hBitmap);
356 return 0;
357 }
358
359 Status = MmCopyFromCaller(&(Info.bmiHeader),
360 &(UnsafeInfo->bmiHeader),
361 Info.bmiHeader.biSize);
362 if (! NT_SUCCESS(Status))
363 {
364 SetLastNtError(Status);
365 BITMAPOBJ_UnlockBitmap(hBitmap);
366 return 0;
367 }
368
369 if (NULL == Bits)
370 {
371 if (sizeof(BITMAPINFOHEADER) == Info.bmiHeader.biSize)
372 {
373 if (0 != Info.bmiHeader.biBitCount)
374 {
375 DPRINT("NtGdiGetDIBits(): This operation isn't fully implemented yet.");
376 /*UNIMPLEMENTED;*/
377 }
378
379 Info.bmiHeader.biWidth = BitmapObj->bitmap.bmWidth;
380 Info.bmiHeader.biHeight = BitmapObj->bitmap.bmHeight;
381 Info.bmiHeader.biPlanes = BitmapObj->bitmap.bmPlanes;
382 Info.bmiHeader.biBitCount = BitmapObj->bitmap.bmBitsPixel;
383 Info.bmiHeader.biCompression = BI_RGB;
384 Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes;
385 }
386 else
387 {
388 Core = (BITMAPCOREHEADER *)(&Info.bmiHeader);
389 if (0 != Core->bcBitCount)
390 {
391 UNIMPLEMENTED;
392 }
393
394 Core->bcWidth = BitmapObj->bitmap.bmWidth;
395 Core->bcHeight = BitmapObj->bitmap.bmHeight;
396 Core->bcPlanes = BitmapObj->bitmap.bmPlanes;
397 Core->bcBitCount = BitmapObj->bitmap.bmBitsPixel;
398 }
399
400 Status = MmCopyToCaller(UnsafeInfo, &Info, Info.bmiHeader.biSize);
401 if (! NT_SUCCESS(Status))
402 {
403 SetLastNtError(Status);
404 BITMAPOBJ_UnlockBitmap(hBitmap);
405 return 0;
406 }
407 Result = 1;
408 }
409 else if (0 == StartScan && Info.bmiHeader.biHeight == (LONG) (StartScan + ScanLines) &&
410 Info.bmiHeader.biWidth == BitmapObj->bitmap.bmWidth &&
411 Info.bmiHeader.biHeight == BitmapObj->bitmap.bmHeight &&
412 Info.bmiHeader.biPlanes == BitmapObj->bitmap.bmPlanes &&
413 Info.bmiHeader.biBitCount == BitmapObj->bitmap.bmBitsPixel &&
414 8 < Info.bmiHeader.biBitCount)
415 {
416 Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes;
417 Status = MmCopyToCaller(Bits, BitmapObj->bitmap.bmBits, Info.bmiHeader.biSizeImage);
418 if (! NT_SUCCESS(Status))
419 {
420 SetLastNtError(Status);
421 BITMAPOBJ_UnlockBitmap(hBitmap);
422 return 0;
423 }
424 RtlZeroMemory(&InfoWithBitFields, sizeof(InfoWithBitFields));
425 RtlCopyMemory(&(InfoWithBitFields.Info), &Info, sizeof(BITMAPINFO));
426 if (BI_BITFIELDS == Info.bmiHeader.biCompression)
427 {
428 DCObj = DC_LockDc(hDC);
429 if (NULL == DCObj)
430 {
431 SetLastWin32Error(ERROR_INVALID_HANDLE);
432 BITMAPOBJ_UnlockBitmap(hBitmap);
433 return 0;
434 }
435 PalGdi = PALETTE_LockPalette(DCObj->w.hPalette);
436 BitField = (DWORD *) ((char *) &InfoWithBitFields + InfoWithBitFields.Info.bmiHeader.biSize);
437 BitField[0] = PalGdi->RedMask;
438 BitField[1] = PalGdi->GreenMask;
439 BitField[2] = PalGdi->BlueMask;
440 PALETTE_UnlockPalette(DCObj->w.hPalette);
441 InfoSize = InfoWithBitFields.Info.bmiHeader.biSize + 3 * sizeof(DWORD);
442 DC_UnlockDc(hDC);
443 }
444 else
445 {
446 InfoSize = Info.bmiHeader.biSize;
447 }
448 Status = MmCopyToCaller(UnsafeInfo, &InfoWithBitFields, InfoSize);
449 if (! NT_SUCCESS(Status))
450 {
451 SetLastNtError(Status);
452 BITMAPOBJ_UnlockBitmap(hBitmap);
453 return 0;
454 }
455 }
456 else
457 {
458 UNIMPLEMENTED;
459 }
460
461 BITMAPOBJ_UnlockBitmap(hBitmap);
462
463 return Result;
464 #else
465 PDC dc;
466 PBITMAPOBJ bmp;
467 int i;
468
469 if (!info) return 0;
470 if (!(dc = DC_LockDc( hdc ))) return 0;
471 if (!(bmp = BITMAPOBJ_LockBitmap(hbitmap)))
472 {
473 DC_UnlockDc( hdc );
474 return 0;
475 }
476
477 /* Transfer color info */
478
479 if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
480
481 info->bmiHeader.biClrUsed = 0;
482
483 /* If the bitmap object already has a dib section at the
484 same color depth then get the color map from it */
485 if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == info->bmiHeader.biBitCount) {
486 NtGdiGetDIBColorTable(hdc, 0, 1 << info->bmiHeader.biBitCount, info->bmiColors);
487 }
488 else {
489 if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
490 /* Generate the color map from the selected palette */
491 PALETTEENTRY * palEntry;
492 PPALGDI palette;
493 if (!(palette = PALETTE_LockPalette(dc->w.hPalette))) {
494 DC_UnlockDc( hdc );
495 BITMAPOBJ_UnlockBitmap( hbitmap );
496 return 0;
497 }
498 palEntry = palette->IndexedColors;
499 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
500 if (coloruse == DIB_RGB_COLORS) {
501 info->bmiColors[i].rgbRed = palEntry->peRed;
502 info->bmiColors[i].rgbGreen = palEntry->peGreen;
503 info->bmiColors[i].rgbBlue = palEntry->peBlue;
504 info->bmiColors[i].rgbReserved = 0;
505 }
506 else ((WORD *)info->bmiColors)[i] = (WORD)i;
507 }
508 PALETTE_UnlockPalette( dc->w.hPalette );
509 } else {
510 switch (info->bmiHeader.biBitCount) {
511 case 1:
512 info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
513 info->bmiColors[0].rgbBlue = 0;
514 info->bmiColors[0].rgbReserved = 0;
515 info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
516 info->bmiColors[1].rgbBlue = 0xff;
517 info->bmiColors[1].rgbReserved = 0;
518 break;
519
520 case 4:
521 memcpy(info->bmiColors, COLOR_GetSystemPaletteTemplate(), NB_RESERVED_COLORS * sizeof(PALETTEENTRY));
522 break;
523
524 case 8:
525 {
526 INT r, g, b;
527 RGBQUAD *color;
528
529 memcpy(info->bmiColors, COLOR_GetSystemPaletteTemplate(),
530 10 * sizeof(RGBQUAD));
531 memcpy(info->bmiColors + 246, COLOR_GetSystemPaletteTemplate() + 10,
532 10 * sizeof(RGBQUAD));
533 color = info->bmiColors + 10;
534 for(r = 0; r <= 5; r++) /* FIXME */
535 for(g = 0; g <= 5; g++)
536 for(b = 0; b <= 5; b++) {
537 color->rgbRed = (r * 0xff) / 5;
538 color->rgbGreen = (g * 0xff) / 5;
539 color->rgbBlue = (b * 0xff) / 5;
540 color->rgbReserved = 0;
541 color++;
542 }
543 }
544 }
545 }
546 }
547 }
548
549 if (bits && lines)
550 {
551 /* If the bitmap object already have a dib section that contains image data, get the bits from it */
552 if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
553 {
554 /*FIXME: Only RGB dibs supported for now */
555 unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
556 int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
557 LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
558 unsigned int x, y;
559
560 if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
561 {
562 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
563 dstwidthb = -dstwidthb;
564 }
565
566 switch( info->bmiHeader.biBitCount ) {
567
568 case 15:
569 case 16: /* 16 bpp dstDIB */
570 {
571 LPWORD dstbits = (LPWORD)dbits;
572 WORD rmask = 0x7c00, gmask= 0x03e0, bmask = 0x001f;
573
574 /* FIXME: BI_BITFIELDS not supported yet */
575
576 switch(bmp->dib->dsBm.bmBitsPixel) {
577
578 case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */
579 {
580 /* FIXME: BI_BITFIELDS not supported yet */
581 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
582 memcpy(dbits, sbits, srcwidthb);
583 }
584 break;
585
586 case 24: /* 24 bpp srcDIB -> 16 bpp dstDIB */
587 {
588 LPBYTE srcbits = sbits;
589
590 for( y = 0; y < lines; y++) {
591 for( x = 0; x < srcwidth; x++, srcbits += 3)
592 *dstbits++ = ((srcbits[0] >> 3) & bmask) |
593 (((WORD)srcbits[1] << 2) & gmask) |
594 (((WORD)srcbits[2] << 7) & rmask);
595
596 dstbits = (LPWORD)(dbits+=dstwidthb);
597 srcbits = (sbits += srcwidthb);
598 }
599 }
600 break;
601
602 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
603 {
604 LPDWORD srcbits = (LPDWORD)sbits;
605 DWORD val;
606
607 for( y = 0; y < lines; y++) {
608 for( x = 0; x < srcwidth; x++ ) {
609 val = *srcbits++;
610 *dstbits++ = (WORD)(((val >> 3) & bmask) | ((val >> 6) & gmask) |
611 ((val >> 9) & rmask));
612 }
613 dstbits = (LPWORD)(dbits+=dstwidthb);
614 srcbits = (LPDWORD)(sbits+=srcwidthb);
615 }
616 }
617 break;
618
619 default: /* ? bit bmp -> 16 bit DIB */
620 DPRINT1("FIXME: 15/16 bit DIB %d bit bitmap\n",
621 bmp->bitmap.bmBitsPixel);
622 break;
623 }
624 }
625 break;
626
627 case 24: /* 24 bpp dstDIB */
628 {
629 LPBYTE dstbits = dbits;
630
631 switch(bmp->dib->dsBm.bmBitsPixel) {
632
633 case 16: /* 16 bpp srcDIB -> 24 bpp dstDIB */
634 {
635 LPWORD srcbits = (LPWORD)sbits;
636 WORD val;
637
638 /* FIXME: BI_BITFIELDS not supported yet */
639 for( y = 0; y < lines; y++) {
640 for( x = 0; x < srcwidth; x++ ) {
641 val = *srcbits++;
642 *dstbits++ = (BYTE)(((val << 3) & 0xf8) | ((val >> 2) & 0x07));
643 *dstbits++ = (BYTE)(((val >> 2) & 0xf8) | ((val >> 7) & 0x07));
644 *dstbits++ = (BYTE)(((val >> 7) & 0xf8) | ((val >> 12) & 0x07));
645 }
646 dstbits = (LPBYTE)(dbits+=dstwidthb);
647 srcbits = (LPWORD)(sbits+=srcwidthb);
648 }
649 }
650 break;
651
652 case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */
653 {
654 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
655 memcpy(dbits, sbits, srcwidthb);
656 }
657 break;
658
659 case 32: /* 32 bpp srcDIB -> 24 bpp dstDIB */
660 {
661 LPBYTE srcbits = (LPBYTE)sbits;
662
663 for( y = 0; y < lines; y++) {
664 for( x = 0; x < srcwidth; x++, srcbits++ ) {
665 *dstbits++ = *srcbits++;
666 *dstbits++ = *srcbits++;
667 *dstbits++ = *srcbits++;
668 }
669 dstbits=(LPBYTE)(dbits+=dstwidthb);
670 srcbits = (LPBYTE)(sbits+=srcwidthb);
671 }
672 }
673 break;
674
675 default: /* ? bit bmp -> 24 bit DIB */
676 DPRINT1("FIXME: 24 bit DIB %d bit bitmap\n",
677 bmp->bitmap.bmBitsPixel);
678 break;
679 }
680 }
681 break;
682
683 case 32: /* 32 bpp dstDIB */
684 {
685 LPDWORD dstbits = (LPDWORD)dbits;
686
687 /* FIXME: BI_BITFIELDS not supported yet */
688
689 switch(bmp->dib->dsBm.bmBitsPixel) {
690 case 16: /* 16 bpp srcDIB -> 32 bpp dstDIB */
691 {
692 LPWORD srcbits = (LPWORD)sbits;
693 DWORD val;
694
695 /* FIXME: BI_BITFIELDS not supported yet */
696 for( y = 0; y < lines; y++) {
697 for( x = 0; x < srcwidth; x++ ) {
698 val = (DWORD)*srcbits++;
699 *dstbits++ = ((val << 3) & 0xf8) | ((val >> 2) & 0x07) |
700 ((val << 6) & 0xf800) | ((val << 1) & 0x0700) |
701 ((val << 9) & 0xf80000) | ((val << 4) & 0x070000);
702 }
703 dstbits=(LPDWORD)(dbits+=dstwidthb);
704 srcbits=(LPWORD)(sbits+=srcwidthb);
705 }
706 }
707 break;
708
709 case 24: /* 24 bpp srcDIB -> 32 bpp dstDIB */
710 {
711 LPBYTE srcbits = sbits;
712
713 for( y = 0; y < lines; y++) {
714 for( x = 0; x < srcwidth; x++, srcbits+=3 )
715 *dstbits++ = ((DWORD)*srcbits) & 0x00ffffff;
716 dstbits=(LPDWORD)(dbits+=dstwidthb);
717 srcbits=(sbits+=srcwidthb);
718 }
719 }
720 break;
721
722 case 32: /* 32 bpp srcDIB -> 16 bpp dstDIB */
723 {
724 /* FIXME: BI_BITFIELDS not supported yet */
725 for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
726 memcpy(dbits, sbits, srcwidthb);
727 }
728 break;
729
730 default: /* ? bit bmp -> 32 bit DIB */
731 DPRINT1("FIXME: 32 bit DIB %d bit bitmap\n",
732 bmp->bitmap.bmBitsPixel);
733 break;
734 }
735 }
736 break;
737
738 default: /* ? bit DIB */
739 DPRINT1("FIXME: Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
740 break;
741 }
742 }
743 /* Otherwise, get bits from the XImage */
744 else
745 {
746 UNIMPLEMENTED;
747 }
748 }
749 else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
750 {
751 /* fill in struct members */
752
753 if( info->bmiHeader.biBitCount == 0)
754 {
755 info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
756 info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
757 info->bmiHeader.biPlanes = 1;
758 info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
759 info->bmiHeader.biSizeImage =
760 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
761 bmp->bitmap.bmHeight,
762 bmp->bitmap.bmBitsPixel );
763 info->bmiHeader.biCompression = 0;
764 }
765 else
766 {
767 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
768 info->bmiHeader.biWidth,
769 info->bmiHeader.biHeight,
770 info->bmiHeader.biBitCount );
771 }
772 }
773
774 DC_UnlockDc( hdc );
775 BITMAPOBJ_UnlockBitmap( hbitmap );
776
777 return lines;
778 #endif
779 }
780
781 INT STDCALL NtGdiStretchDIBits(HDC hDC,
782 INT XDest,
783 INT YDest,
784 INT DestWidth,
785 INT DestHeight,
786 INT XSrc,
787 INT YSrc,
788 INT SrcWidth,
789 INT SrcHeight,
790 CONST VOID *Bits,
791 CONST BITMAPINFO *BitsInfo,
792 UINT Usage,
793 DWORD ROP)
794 {
795 HBITMAP hBitmap, hOldBitmap;
796 HDC hdcMem;
797
798 if (!Bits || !BitsInfo)
799 {
800 SetLastWin32Error(ERROR_INVALID_PARAMETER);
801 return 0;
802 }
803
804 hdcMem = NtGdiCreateCompatableDC(hDC);
805 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
806 BitsInfo->bmiHeader.biHeight);
807 hOldBitmap = NtGdiSelectObject(hdcMem, hBitmap);
808
809 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
810 BitsInfo->bmiHeader.biCompression == BI_RLE8)
811 {
812 /* copy existing bitmap from destination dc */
813 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
814 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
815 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP);
816 else
817 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
818 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
819 ROP);
820 }
821
822 NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
823 BitsInfo, Usage);
824
825 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
826 left (negative biHeight) */
827 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
828 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
829 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
830 ROP);
831 else
832 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
833 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
834 SrcWidth, SrcHeight, ROP);
835
836 NtGdiSelectObject(hdcMem, hOldBitmap);
837 NtGdiDeleteDC(hdcMem);
838 NtGdiDeleteObject(hBitmap);
839
840 return SrcHeight;
841 }
842
843 LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
844 LONG Count,
845 LPVOID Bits)
846 {
847 PBITMAPOBJ bmp;
848 LONG height, ret;
849
850 bmp = BITMAPOBJ_LockBitmap (hBitmap);
851 if (!bmp)
852 {
853 return 0;
854 }
855
856 /* If the bits vector is null, the function should return the read size */
857 if (Bits == NULL)
858 {
859 return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
860 }
861
862 if (Count < 0)
863 {
864 DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
865 Count = -Count;
866 }
867
868 /* Only get entire lines */
869 height = Count / bmp->bitmap.bmWidthBytes;
870 if (height > bmp->bitmap.bmHeight)
871 {
872 height = bmp->bitmap.bmHeight;
873 }
874 Count = height * bmp->bitmap.bmWidthBytes;
875 if (Count == 0)
876 {
877 DPRINT("Less then one entire line requested\n");
878 return 0;
879 }
880
881 DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
882 hBitmap, Count, Bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
883 1 << bmp->bitmap.bmBitsPixel, height );
884 #if 0
885 /* FIXME: Call DDI CopyBits here if available */
886 if(bmp->DDBitmap)
887 {
888 DPRINT("Calling device specific BitmapBits\n");
889 if(bmp->DDBitmap->funcs->pBitmapBits)
890 {
891 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
892 DDB_GET);
893 }
894 else
895 {
896 ERR_(bitmap)("BitmapBits == NULL??\n");
897 ret = 0;
898 }
899 }
900 else
901 #endif
902 {
903 if(!bmp->bitmap.bmBits)
904 {
905 DPRINT ("Bitmap is empty\n");
906 ret = 0;
907 }
908 else
909 {
910 memcpy(Bits, bmp->bitmap.bmBits, Count);
911 ret = Count;
912 }
913 }
914
915 return ret;
916 }
917
918 static HBITMAP FASTCALL
919 IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
920 DWORD init, LPCVOID bits, const BITMAPINFO *data,
921 UINT coloruse)
922 {
923 HBITMAP handle;
924 BOOL fColor;
925 DWORD width;
926 int height;
927 WORD bpp;
928 WORD compr;
929
930 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
931 if (height < 0) height = -height;
932
933 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
934 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
935
936 if (bpp != 1) fColor = TRUE;
937 else if ((coloruse != DIB_RGB_COLORS) ||
938 (init != CBM_INIT) || !data) fColor = FALSE;
939 else
940 {
941 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
942 {
943 RGBQUAD *rgb = data->bmiColors;
944 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
945
946 // Check if the first color of the colormap is black
947 if ((col == RGB(0, 0, 0)))
948 {
949 rgb++;
950 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
951
952 // If the second color is white, create a monochrome bitmap
953 fColor = (col != RGB(0xff,0xff,0xff));
954 }
955 else fColor = TRUE;
956 }
957 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
958 {
959 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
960 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
961
962 if ((col == RGB(0,0,0)))
963 {
964 rgb++;
965 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
966 fColor = (col != RGB(0xff,0xff,0xff));
967 }
968 else fColor = TRUE;
969 }
970 else
971 {
972 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
973 return 0;
974 }
975 }
976
977 // Now create the bitmap
978 if (fColor)
979 {
980 handle = IntCreateCompatibleBitmap(Dc, width, height);
981 }
982 else
983 {
984 handle = NtGdiCreateBitmap( width, height, 1, 1, NULL);
985 }
986
987 if (NULL != handle && CBM_INIT == init)
988 {
989 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
990 }
991
992 return handle;
993 }
994
995 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
996 // The DDB that is created will be whatever bit depth your reference DC is
997 HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
998 DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
999 UINT ColorUse)
1000 {
1001 PDC Dc;
1002 HBITMAP Bmp;
1003
1004 Dc = DC_LockDc(hDc);
1005 if (NULL == Dc)
1006 {
1007 SetLastWin32Error(ERROR_INVALID_HANDLE);
1008 return NULL;
1009 }
1010
1011 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
1012
1013 DC_UnlockDc(hDc);
1014
1015 return Bmp;
1016 }
1017
1018 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
1019 CONST BITMAPINFO *bmi,
1020 UINT Usage,
1021 VOID *Bits,
1022 HANDLE hSection,
1023 DWORD dwOffset)
1024 {
1025 HBITMAP hbitmap = 0;
1026 DC *dc;
1027 BOOL bDesktopDC = FALSE;
1028
1029 // If the reference hdc is null, take the desktop dc
1030 if (hDC == 0)
1031 {
1032 hDC = NtGdiCreateCompatableDC(0);
1033 bDesktopDC = TRUE;
1034 }
1035
1036 if ((dc = DC_LockDc(hDC)))
1037 {
1038 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
1039 hSection, dwOffset, 0);
1040 DC_UnlockDc(hDC);
1041 }
1042
1043 if (bDesktopDC)
1044 NtGdiDeleteDC(hDC);
1045
1046 return hbitmap;
1047 }
1048
1049 HBITMAP STDCALL
1050 DIB_CreateDIBSection(
1051 PDC dc, BITMAPINFO *bmi, UINT usage,
1052 LPVOID *bits, HANDLE section,
1053 DWORD offset, DWORD ovr_pitch)
1054 {
1055 HBITMAP res = 0;
1056 BITMAPOBJ *bmp = NULL;
1057 DIBSECTION *dib = NULL;
1058
1059 // Fill BITMAP32 structure with DIB data
1060 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1061 INT effHeight;
1062 ULONG totalSize;
1063 UINT Entries = 0;
1064 BITMAP bm;
1065
1066 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1067 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1068 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1069
1070 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1071 bm.bmType = 0;
1072 bm.bmWidth = bi->biWidth;
1073 bm.bmHeight = effHeight;
1074 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1075
1076 bm.bmPlanes = bi->biPlanes;
1077 bm.bmBitsPixel = bi->biBitCount;
1078 bm.bmBits = NULL;
1079
1080 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1081 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1082 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1083 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
1084
1085 if (section)
1086 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
1087 0L, offset, totalSize); */
1088 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
1089 else if (ovr_pitch && offset)
1090 bm.bmBits = (LPVOID) offset;
1091 else {
1092 offset = 0;
1093 bm.bmBits = EngAllocUserMem(totalSize, 0);
1094 }
1095
1096 /* bm.bmBits = ExAllocatePool(PagedPool, totalSize); */
1097
1098 if(usage == DIB_PAL_COLORS)
1099 memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
1100
1101 // Allocate Memory for DIB and fill structure
1102 if (bm.bmBits)
1103 {
1104 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
1105 RtlZeroMemory(dib, sizeof(DIBSECTION));
1106 }
1107
1108 if (dib)
1109 {
1110 dib->dsBm = bm;
1111 dib->dsBmih = *bi;
1112 dib->dsBmih.biSizeImage = totalSize;
1113
1114 /* Set dsBitfields values */
1115 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1116 {
1117 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1118 }
1119 else switch(bi->biBitCount)
1120 {
1121 case 16:
1122 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
1123 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
1124 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f; break;
1125
1126 case 24:
1127 dib->dsBitfields[0] = 0xff;
1128 dib->dsBitfields[1] = 0xff00;
1129 dib->dsBitfields[2] = 0xff0000;
1130 break;
1131
1132 case 32:
1133 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff;
1134 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00;
1135 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000;
1136 break;
1137 }
1138 dib->dshSection = section;
1139 dib->dsOffset = offset;
1140 }
1141
1142 // Create Device Dependent Bitmap and add DIB pointer
1143 if (dib)
1144 {
1145 res = IntCreateDIBitmap(dc, bi, 0, NULL, bmi, usage);
1146 if (! res)
1147 {
1148 return NULL;
1149 }
1150 bmp = BITMAPOBJ_LockBitmap(res);
1151 if (NULL == bmp)
1152 {
1153 NtGdiDeleteObject(bmp);
1154 return NULL;
1155 }
1156 bmp->dib = (DIBSECTION *) dib;
1157 /* Install user-mode bits instead of kernel-mode bits */
1158 ExFreePool(bmp->bitmap.bmBits);
1159 bmp->bitmap.bmBits = bm.bmBits;
1160
1161 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
1162 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
1163 NtGdiSetDIBColorTable. */
1164 if(bi->biBitCount == 1) { Entries = 2; } else
1165 if(bi->biBitCount == 4) { Entries = 16; } else
1166 if(bi->biBitCount == 8) { Entries = 256; }
1167
1168 bmp->ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD)*Entries, TAG_COLORMAP);
1169 RtlCopyMemory(bmp->ColorMap, bmi->bmiColors, sizeof(RGBQUAD)*Entries);
1170 }
1171
1172 // Clean up in case of errors
1173 if (!res || !bmp || !dib || !bm.bmBits)
1174 {
1175 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
1176 /* if (bm.bmBits)
1177 {
1178 if (section)
1179 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
1180 else if (!offset)
1181 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
1182 } */
1183
1184 if (dib) { ExFreePool(dib); dib = NULL; }
1185 if (bmp) { bmp = NULL; }
1186 if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
1187 }
1188
1189 if (bmp)
1190 {
1191 BITMAPOBJ_UnlockBitmap(res);
1192 }
1193
1194 // Return BITMAP handle and storage location
1195 if (NULL != bm.bmBits && NULL != bits)
1196 {
1197 *bits = bm.bmBits;
1198 }
1199
1200 return res;
1201 }
1202
1203 /***********************************************************************
1204 * DIB_GetDIBWidthBytes
1205 *
1206 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1207 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1208 * 11/16/1999 (RJJ) lifted from wine
1209 */
1210 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
1211 {
1212 int words;
1213
1214 switch(depth)
1215 {
1216 case 1: words = (width + 31) >> 5; break;
1217 case 4: words = (width + 7) >> 3; break;
1218 case 8: words = (width + 3) >> 2; break;
1219 case 15:
1220 case 16: words = (width + 1) >> 1; break;
1221 case 24: words = (width * 3 + 3) >> 2; break;
1222
1223 default:
1224 DPRINT("(%d): Unsupported depth\n", depth );
1225 /* fall through */
1226 case 32:
1227 words = width;
1228 }
1229 return words << 2;
1230 }
1231
1232 /***********************************************************************
1233 * DIB_GetDIBImageBytes
1234 *
1235 * Return the number of bytes used to hold the image in a DIB bitmap.
1236 * 11/16/1999 (RJJ) lifted from wine
1237 */
1238
1239 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1240 {
1241 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1242 }
1243
1244 /***********************************************************************
1245 * DIB_BitmapInfoSize
1246 *
1247 * Return the size of the bitmap info structure including color table.
1248 * 11/16/1999 (RJJ) lifted from wine
1249 */
1250
1251 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1252 {
1253 int colors;
1254
1255 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1256 {
1257 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1258 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1259 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1260 }
1261 else /* assume BITMAPINFOHEADER */
1262 {
1263 colors = info->bmiHeader.biClrUsed;
1264 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1265 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1266 }
1267 }
1268
1269 INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
1270 PDWORD width,
1271 PINT height,
1272 PWORD bpp,
1273 PWORD compr)
1274 {
1275 if (header->biSize == sizeof(BITMAPINFOHEADER))
1276 {
1277 *width = header->biWidth;
1278 *height = header->biHeight;
1279 *bpp = header->biBitCount;
1280 *compr = header->biCompression;
1281 return 1;
1282 }
1283 if (header->biSize == sizeof(BITMAPCOREHEADER))
1284 {
1285 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
1286 *width = core->bcWidth;
1287 *height = core->bcHeight;
1288 *bpp = core->bcBitCount;
1289 *compr = 0;
1290 return 0;
1291 }
1292 DPRINT("(%ld): wrong size for header\n", header->biSize );
1293 return -1;
1294 }
1295
1296 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
1297 // The specified Device Context (DC) defines what the DIB should be converted to
1298 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
1299 // change to NtGdiSetDIBits
1300 {
1301 HBITMAP hBmp = 0;
1302 PBITMAPOBJ pBmp = NULL;
1303 DIBSECTION *dib;
1304 LPBYTE pbits = NULL;
1305
1306 // Get a pointer to the packed DIB's data
1307 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1308 dib = hPackedDIB;
1309
1310 pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
1311
1312 // Create a DDB from the DIB
1313 hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
1314 (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
1315
1316 // GlobalUnlock(hPackedDIB);
1317
1318 // Retrieve the internal Pixmap from the DDB
1319 pBmp = BITMAPOBJ_LockBitmap(hBmp);
1320
1321 return pBmp;
1322 }
1323
1324 RGBQUAD * FASTCALL
1325 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1326 {
1327 RGBQUAD *lpRGB;
1328 ULONG nNumColors,i;
1329 USHORT *lpIndex;
1330 PPALGDI palGDI;
1331
1332 palGDI = PALETTE_LockPalette(dc->w.hPalette);
1333
1334 if (NULL == palGDI)
1335 {
1336 // RELEASEDCINFO(hDC);
1337 return NULL;
1338 }
1339
1340 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1341 if (lpbmi->bmiHeader.biClrUsed)
1342 {
1343 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1344 }
1345
1346 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1347 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1348
1349 for (i = 0; i < nNumColors; i++)
1350 {
1351 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1352 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1353 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1354 lpIndex++;
1355 }
1356 // RELEASEDCINFO(hDC);
1357 PALETTE_UnlockPalette(dc->w.hPalette);
1358
1359 return lpRGB;
1360 }
1361
1362 PPALETTEENTRY STDCALL
1363 DIBColorTableToPaletteEntries (
1364 PPALETTEENTRY palEntries,
1365 const RGBQUAD *DIBColorTable,
1366 ULONG ColorCount
1367 )
1368 {
1369 ULONG i;
1370
1371 for (i = 0; i < ColorCount; i++)
1372 {
1373 palEntries->peRed = DIBColorTable->rgbRed;
1374 palEntries->peGreen = DIBColorTable->rgbGreen;
1375 palEntries->peBlue = DIBColorTable->rgbBlue;
1376 palEntries++;
1377 DIBColorTable++;
1378 }
1379
1380 return palEntries;
1381 }
1382
1383 HPALETTE FASTCALL
1384 BuildDIBPalette (PBITMAPINFO bmi, PINT paletteType)
1385 {
1386 BYTE bits;
1387 ULONG ColorCount;
1388 PALETTEENTRY *palEntries = NULL;
1389 HPALETTE hPal;
1390
1391 // Determine Bits Per Pixel
1392 bits = bmi->bmiHeader.biBitCount;
1393
1394 // Determine paletteType from Bits Per Pixel
1395 if (bits <= 8)
1396 {
1397 *paletteType = PAL_INDEXED;
1398 }
1399 else if(bits < 24)
1400 {
1401 *paletteType = PAL_BITFIELDS;
1402 }
1403 else
1404 {
1405 *paletteType = PAL_BGR;
1406 }
1407
1408 if (bmi->bmiHeader.biClrUsed == 0)
1409 {
1410 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1411 }
1412 else
1413 {
1414 ColorCount = bmi->bmiHeader.biClrUsed;
1415 }
1416
1417 if (PAL_INDEXED == *paletteType)
1418 {
1419 palEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY)*ColorCount, TAG_COLORMAP);
1420 DIBColorTableToPaletteEntries(palEntries, bmi->bmiColors, ColorCount);
1421 }
1422 hPal = PALETTE_AllocPalette( *paletteType, ColorCount, (ULONG*)palEntries, 0, 0, 0 );
1423 if (NULL != palEntries)
1424 {
1425 ExFreePool(palEntries);
1426 }
1427
1428 return hPal;
1429 }
1430
1431 /* EOF */