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