a68b14a2a1e805da2c3041871bc10c3c905b42ff
[reactos.git] / reactos / subsys / win32k / objects / dib.c
1 /*
2 * $Id: dib.c,v 1.57 2004/12/12 01:40:38 weiden 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;
123 INT result = 0;
124 BOOL copyBitsResult;
125 SURFOBJ *DestSurf, *SourceSurf;
126 SIZEL SourceSize;
127 POINTL ZeroPoint;
128 RECTL DestRect;
129 XLATEOBJ *XlateObj;
130 PPALGDI hDCPalette;
131 //RGBQUAD *lpRGB;
132 HPALETTE DDB_Palette, DIB_Palette;
133 ULONG DDB_Palette_Type, DIB_Palette_Type;
134 INT DIBWidth;
135
136 // Check parameters
137 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
138 {
139 return 0;
140 }
141
142 // Get RGB values
143 //if (ColorUse == DIB_PAL_COLORS)
144 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
145 //else
146 // lpRGB = &bmi->bmiColors[0];
147
148 DestSurf = &bitmap->SurfObj;
149
150 // Create source surface
151 SourceSize.cx = bmi->bmiHeader.biWidth;
152 SourceSize.cy = abs(bmi->bmiHeader.biHeight);
153
154 // Determine width of DIB
155 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
156
157 SourceBitmap = EngCreateBitmap(SourceSize,
158 DIBWidth,
159 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
160 0 < bmi->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
161 (PVOID) Bits);
162 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
163
164 // Destination palette obtained from the hDC
165 hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
166 if (NULL == hDCPalette)
167 {
168 EngUnlockSurface(SourceSurf);
169 EngDeleteSurface((HSURF)SourceBitmap);
170 BITMAPOBJ_UnlockBitmap(hBitmap);
171 SetLastWin32Error(ERROR_INVALID_HANDLE);
172 return 0;
173 }
174 DDB_Palette_Type = hDCPalette->Mode;
175 DDB_Palette = DC->DevInfo->hpalDefault;
176 PALETTE_UnlockPalette(DC->DevInfo->hpalDefault);
177
178 // Source palette obtained from the BITMAPINFO
179 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
180 if (NULL == DIB_Palette)
181 {
182 EngUnlockSurface(SourceSurf);
183 EngDeleteSurface((HSURF)SourceBitmap);
184 BITMAPOBJ_UnlockBitmap(hBitmap);
185 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
186 return 0;
187 }
188
189 // Determine XLATEOBJ for color translation
190 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
191 if (NULL == XlateObj)
192 {
193 PALETTE_FreePalette(DIB_Palette);
194 EngUnlockSurface(SourceSurf);
195 EngDeleteSurface((HSURF)SourceBitmap);
196 BITMAPOBJ_UnlockBitmap(hBitmap);
197 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
198 return 0;
199 }
200
201 // Zero point
202 ZeroPoint.x = 0;
203 ZeroPoint.y = 0;
204
205 // Determine destination rectangle
206 DestRect.top = 0;
207 DestRect.left = 0;
208 DestRect.right = SourceSize.cx;
209 DestRect.bottom = SourceSize.cy;
210
211 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
212
213 // If it succeeded, return number of scanlines copies
214 if(copyBitsResult == TRUE)
215 {
216 result = SourceSize.cy - 1;
217 }
218
219 // Clean up
220 EngDeleteXlate(XlateObj);
221 PALETTE_FreePalette(DIB_Palette);
222 EngUnlockSurface(SourceSurf);
223 EngDeleteSurface((HSURF)SourceBitmap);
224
225 // if (ColorUse == DIB_PAL_COLORS)
226 // WinFree((LPSTR)lpRGB);
227
228 BITMAPOBJ_UnlockBitmap(hBitmap);
229
230 return result;
231 }
232
233 // Converts a DIB to a device-dependent bitmap
234 INT STDCALL
235 NtGdiSetDIBits(
236 HDC hDC,
237 HBITMAP hBitmap,
238 UINT StartScan,
239 UINT ScanLines,
240 CONST VOID *Bits,
241 CONST BITMAPINFO *bmi,
242 UINT ColorUse)
243 {
244 PDC Dc;
245 INT Ret;
246
247 Dc = DC_LockDc(hDC);
248 if (NULL == Dc)
249 {
250 SetLastWin32Error(ERROR_INVALID_HANDLE);
251 return 0;
252 }
253
254 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
255
256 DC_UnlockDc(hDC);
257
258 return Ret;
259 }
260
261 INT STDCALL
262 NtGdiSetDIBitsToDevice(
263 HDC hDC,
264 INT XDest,
265 INT YDest,
266 DWORD Width,
267 DWORD Height,
268 INT XSrc,
269 INT YSrc,
270 UINT StartScan,
271 UINT ScanLines,
272 CONST VOID *Bits,
273 CONST BITMAPINFO *bmi,
274 UINT ColorUse)
275 {
276 UNIMPLEMENTED;
277 return 0;
278 }
279
280 /* Converts a device-dependent bitmap to a DIB */
281 INT STDCALL
282 NtGdiGetDIBits(HDC hDC,
283 HBITMAP hBitmap,
284 UINT StartScan,
285 UINT ScanLines,
286 LPVOID Bits,
287 LPBITMAPINFO Info,
288 UINT Usage)
289 {
290 BITMAPOBJ *BitmapObj;
291 SURFOBJ *DestSurfObj;
292 XLATEOBJ *XlateObj;
293 HBITMAP DestBitmap;
294 SIZEL DestSize;
295 HPALETTE hSourcePalette;
296 HPALETTE hDestPalette;
297 PPALGDI SourcePalette;
298 PPALGDI DestPalette;
299 ULONG SourcePaletteType;
300 ULONG DestPaletteType;
301 PDC Dc;
302 POINTL SourcePoint;
303 RECTL DestRect;
304 ULONG Result = 0;
305 ULONG Index;
306
307 /* Get handle for the palette in DC. */
308 Dc = DC_LockDc(hDC);
309 if (Dc == NULL)
310 {
311 SetLastWin32Error(ERROR_INVALID_HANDLE);
312 return 0;
313 }
314 hSourcePalette = Dc->w.hPalette;
315 /* FIXME: This is incorrect. hDestPalette should be something other. */
316 hDestPalette = Dc->DevInfo->hpalDefault;
317 DC_UnlockDc(hDC);
318
319 /* Get pointer to the source bitmap object. */
320 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
321 if (BitmapObj == NULL)
322 {
323 SetLastWin32Error(ERROR_INVALID_HANDLE);
324 return 0;
325 }
326
327 if (Bits == NULL)
328 {
329 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) ||
330 Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
331 {
332 Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
333 Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
334 /* Report negtive height for top-down bitmaps. */
335 if (BitmapObj->SurfObj.lDelta > 0)
336 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
337 Info->bmiHeader.biPlanes = 1;
338 Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
339 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
340 {
341 switch (BitmapObj->SurfObj.iBitmapFormat)
342 {
343 case BMF_1BPP: case BMF_4BPP: case BMF_8BPP:
344 case BMF_16BPP: case BMF_24BPP: case BMF_32BPP:
345 Info->bmiHeader.biCompression = BI_RGB;
346 break;
347 case BMF_4RLE:
348 Info->bmiHeader.biCompression = BI_RLE4;
349 break;
350 case BMF_8RLE:
351 Info->bmiHeader.biCompression = BI_RLE8;
352 break;
353 case BMF_JPEG:
354 Info->bmiHeader.biCompression = BI_JPEG;
355 break;
356 case BMF_PNG:
357 Info->bmiHeader.biCompression = BI_PNG;
358 break;
359 }
360 Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
361 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
362 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
363 Info->bmiHeader.biClrUsed =
364 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
365 Result = BitmapObj->SurfObj.sizlBitmap.cy;
366 }
367 }
368 }
369 else
370 {
371 if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
372 {
373 Result = 0;
374 }
375 else
376 {
377 ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
378 DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
379 DestSize.cy = ScanLines;
380 DestBitmap = EngCreateBitmap(
381 DestSize, BitmapObj->SurfObj.lDelta,
382 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
383 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
384 Bits);
385 DestSurfObj = EngLockSurface((HSURF)DestBitmap);
386
387 SourcePalette = PALETTE_LockPalette(hSourcePalette);
388 /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
389 ASSERT(SourcePalette);
390 SourcePaletteType = SourcePalette->Mode;
391 PALETTE_UnlockPalette(hSourcePalette);
392
393 DestPalette = PALETTE_LockPalette(hDestPalette);
394 /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
395 ASSERT(DestPalette);
396 DestPaletteType = DestPalette->Mode;
397
398 /* Copy palette. */
399 /* FIXME: This is largely incomplete. */
400 if (Info->bmiHeader.biBitCount <= 8)
401 {
402 if (Usage == DIB_RGB_COLORS)
403 {
404 for (Index = 0;
405 Index < (1 << Info->bmiHeader.biBitCount) &&
406 Index < DestPalette->NumColors;
407 Index++)
408 {
409 Info->bmiColors[Index].rgbRed =
410 DestPalette->IndexedColors[Index].peRed;
411 Info->bmiColors[Index].rgbGreen =
412 DestPalette->IndexedColors[Index].peGreen;
413 Info->bmiColors[Index].rgbBlue =
414 DestPalette->IndexedColors[Index].peBlue;
415 }
416 }
417 if (Usage == DIB_PAL_COLORS)
418 {
419 DbgPrint("GetDIBits with DIB_PAL_COLORS isn't implemented yet.");
420 }
421 }
422
423 PALETTE_UnlockPalette(hDestPalette);
424
425 XlateObj = IntEngCreateXlate(
426 DestPaletteType, SourcePaletteType, hDestPalette, hSourcePalette);
427
428 SourcePoint.x = 0;
429 SourcePoint.y = StartScan;
430
431 /* Determine destination rectangle */
432 DestRect.top = 0;
433 DestRect.left = 0;
434 DestRect.right = DestSize.cx;
435 DestRect.bottom = DestSize.cy;
436
437 if (EngCopyBits(DestSurfObj, &BitmapObj->SurfObj,
438 NULL, XlateObj, &DestRect, &SourcePoint))
439 {
440 Result = ScanLines;
441 }
442
443 EngDeleteXlate(XlateObj);
444 EngUnlockSurface(DestSurfObj);
445 }
446 }
447
448 BITMAPOBJ_UnlockBitmap(hBitmap);
449
450 return Result;
451 }
452
453 INT STDCALL NtGdiStretchDIBits(HDC hDC,
454 INT XDest,
455 INT YDest,
456 INT DestWidth,
457 INT DestHeight,
458 INT XSrc,
459 INT YSrc,
460 INT SrcWidth,
461 INT SrcHeight,
462 CONST VOID *Bits,
463 CONST BITMAPINFO *BitsInfo,
464 UINT Usage,
465 DWORD ROP)
466 {
467 HBITMAP hBitmap, hOldBitmap;
468 HDC hdcMem;
469
470 if (!Bits || !BitsInfo)
471 {
472 SetLastWin32Error(ERROR_INVALID_PARAMETER);
473 return 0;
474 }
475
476 hdcMem = NtGdiCreateCompatableDC(hDC);
477 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
478 BitsInfo->bmiHeader.biHeight);
479 hOldBitmap = NtGdiSelectObject(hdcMem, hBitmap);
480
481 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
482 BitsInfo->bmiHeader.biCompression == BI_RLE8)
483 {
484 /* copy existing bitmap from destination dc */
485 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
486 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
487 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP);
488 else
489 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
490 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
491 ROP);
492 }
493
494 NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
495 BitsInfo, Usage);
496
497 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
498 left (negative biHeight) */
499 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
500 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
501 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
502 ROP);
503 else
504 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
505 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
506 SrcWidth, SrcHeight, ROP);
507
508 NtGdiSelectObject(hdcMem, hOldBitmap);
509 NtGdiDeleteDC(hdcMem);
510 NtGdiDeleteObject(hBitmap);
511
512 return SrcHeight;
513 }
514
515 LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
516 LONG Count,
517 LPVOID Bits)
518 {
519 PBITMAPOBJ bmp;
520 LONG height, ret;
521
522 bmp = BITMAPOBJ_LockBitmap (hBitmap);
523 if (!bmp)
524 {
525 return 0;
526 }
527
528 /* If the bits vector is null, the function should return the read size */
529 if (Bits == NULL)
530 {
531 ret = bmp->SurfObj.cjBits;
532 BITMAPOBJ_UnlockBitmap (hBitmap);
533 return ret;
534 }
535
536 if (Count < 0)
537 {
538 DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
539 Count = -Count;
540 }
541
542 /* Only get entire lines */
543 height = Count / abs(bmp->SurfObj.lDelta);
544 if (height > bmp->SurfObj.sizlBitmap.cy)
545 {
546 height = bmp->SurfObj.sizlBitmap.cy;
547 }
548 Count = height * abs(bmp->SurfObj.lDelta);
549 if (Count == 0)
550 {
551 DPRINT("Less then one entire line requested\n");
552 BITMAPOBJ_UnlockBitmap (hBitmap);
553 return 0;
554 }
555
556 DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
557 hBitmap, Count, Bits, bmp->SurfObj.sizlBitmap.cx,
558 bmp->SurfObj.sizlBitmap.cy,
559 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat), height );
560 #if 0
561 /* FIXME: Call DDI CopyBits here if available */
562 if(bmp->DDBitmap)
563 {
564 DPRINT("Calling device specific BitmapBits\n");
565 if(bmp->DDBitmap->funcs->pBitmapBits)
566 {
567 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
568 DDB_GET);
569 }
570 else
571 {
572 ERR_(bitmap)("BitmapBits == NULL??\n");
573 ret = 0;
574 }
575 }
576 else
577 #endif
578 {
579 memcpy(Bits, bmp->SurfObj.pvBits, Count);
580 ret = Count;
581 }
582
583 BITMAPOBJ_UnlockBitmap (hBitmap);
584
585 return ret;
586 }
587
588 static HBITMAP FASTCALL
589 IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
590 DWORD init, LPCVOID bits, const BITMAPINFO *data,
591 UINT coloruse)
592 {
593 HBITMAP handle;
594 BOOL fColor;
595 DWORD width;
596 int height;
597 WORD bpp;
598 WORD compr;
599
600 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
601
602 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
603 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
604
605 if (bpp != 1) fColor = TRUE;
606 else if ((coloruse != DIB_RGB_COLORS) ||
607 (init != CBM_INIT) || !data) fColor = FALSE;
608 else
609 {
610 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
611 {
612 RGBQUAD *rgb = data->bmiColors;
613 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
614
615 // Check if the first color of the colormap is black
616 if ((col == RGB(0, 0, 0)))
617 {
618 rgb++;
619 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
620
621 // If the second color is white, create a monochrome bitmap
622 fColor = (col != RGB(0xff,0xff,0xff));
623 }
624 else fColor = TRUE;
625 }
626 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
627 {
628 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
629 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
630
631 if ((col == RGB(0,0,0)))
632 {
633 rgb++;
634 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
635 fColor = (col != RGB(0xff,0xff,0xff));
636 }
637 else fColor = TRUE;
638 }
639 else
640 {
641 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
642 return 0;
643 }
644 }
645
646 // Now create the bitmap
647 if (fColor)
648 {
649 handle = IntCreateCompatibleBitmap(Dc, width, height);
650 }
651 else
652 {
653 handle = NtGdiCreateBitmap( width, height, 1, 1, NULL);
654 }
655
656 if (height < 0)
657 height = -height;
658
659 if (NULL != handle && CBM_INIT == init)
660 {
661 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
662 }
663
664 return handle;
665 }
666
667 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
668 // The DDB that is created will be whatever bit depth your reference DC is
669 HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
670 DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
671 UINT ColorUse)
672 {
673 PDC Dc;
674 HBITMAP Bmp;
675
676 Dc = DC_LockDc(hDc);
677 if (NULL == Dc)
678 {
679 SetLastWin32Error(ERROR_INVALID_HANDLE);
680 return NULL;
681 }
682
683 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
684
685 DC_UnlockDc(hDc);
686
687 return Bmp;
688 }
689
690 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
691 CONST BITMAPINFO *bmi,
692 UINT Usage,
693 VOID *Bits,
694 HANDLE hSection,
695 DWORD dwOffset)
696 {
697 HBITMAP hbitmap = 0;
698 DC *dc;
699 BOOL bDesktopDC = FALSE;
700
701 // If the reference hdc is null, take the desktop dc
702 if (hDC == 0)
703 {
704 hDC = NtGdiCreateCompatableDC(0);
705 bDesktopDC = TRUE;
706 }
707
708 if ((dc = DC_LockDc(hDC)))
709 {
710 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
711 hSection, dwOffset, 0);
712 DC_UnlockDc(hDC);
713 }
714
715 if (bDesktopDC)
716 NtGdiDeleteDC(hDC);
717
718 return hbitmap;
719 }
720
721 HBITMAP STDCALL
722 DIB_CreateDIBSection(
723 PDC dc, BITMAPINFO *bmi, UINT usage,
724 LPVOID *bits, HANDLE section,
725 DWORD offset, DWORD ovr_pitch)
726 {
727 HBITMAP res = 0;
728 BITMAPOBJ *bmp = NULL;
729 DIBSECTION *dib = NULL;
730
731 // Fill BITMAP32 structure with DIB data
732 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
733 INT effHeight;
734 ULONG totalSize;
735 UINT Entries = 0;
736 BITMAP bm;
737 SIZEL Size;
738
739 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
740 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
741 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
742
743 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
744 bm.bmType = 0;
745 bm.bmWidth = bi->biWidth;
746 bm.bmHeight = effHeight;
747 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
748
749 bm.bmPlanes = bi->biPlanes;
750 bm.bmBitsPixel = bi->biBitCount;
751 bm.bmBits = NULL;
752
753 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
754 // we're dealing with a compressed bitmap. Otherwise, use width * height.
755 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
756 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
757
758 if (section)
759 {
760 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
761 0L, offset, totalSize); */
762 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
763 return 0;
764 }
765 else if (ovr_pitch && offset)
766 bm.bmBits = (LPVOID) offset;
767 else {
768 offset = 0;
769 bm.bmBits = EngAllocUserMem(totalSize, 0);
770 }
771
772 if(usage == DIB_PAL_COLORS)
773 memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
774
775 // Allocate Memory for DIB and fill structure
776 if (bm.bmBits)
777 {
778 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
779 RtlZeroMemory(dib, sizeof(DIBSECTION));
780 }
781
782 if (dib)
783 {
784 dib->dsBm = bm;
785 dib->dsBmih = *bi;
786 dib->dsBmih.biSizeImage = totalSize;
787
788 /* Set dsBitfields values */
789 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
790 {
791 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
792 }
793 else switch(bi->biBitCount)
794 {
795 case 16:
796 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
797 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
798 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f; break;
799
800 case 24:
801 dib->dsBitfields[0] = 0xff0000;
802 dib->dsBitfields[1] = 0x00ff00;
803 dib->dsBitfields[2] = 0x0000ff;
804 break;
805
806 case 32:
807 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
808 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
809 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
810 break;
811 }
812 dib->dshSection = section;
813 dib->dsOffset = offset;
814 }
815
816 // Create Device Dependent Bitmap and add DIB pointer
817 if (dib)
818 {
819 Size.cx = bm.bmWidth;
820 Size.cy = bm.bmHeight;
821 res = IntCreateBitmap(Size, bm.bmWidthBytes,
822 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
823 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
824 (bi->biHeight > 0 ? 0 : BMF_TOPDOWN),
825 bm.bmBits);
826 if (! res)
827 {
828 return NULL;
829 }
830 bmp = BITMAPOBJ_LockBitmap(res);
831 if (NULL == bmp)
832 {
833 NtGdiDeleteObject(bmp);
834 return NULL;
835 }
836 bmp->dib = (DIBSECTION *) dib;
837
838 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
839 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
840 NtGdiSetDIBColorTable. */
841 if(bi->biBitCount == 1) { Entries = 2; } else
842 if(bi->biBitCount == 4) { Entries = 16; } else
843 if(bi->biBitCount == 8) { Entries = 256; }
844
845 bmp->ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD)*Entries, TAG_COLORMAP);
846 RtlCopyMemory(bmp->ColorMap, bmi->bmiColors, sizeof(RGBQUAD)*Entries);
847 }
848
849 // Clean up in case of errors
850 if (!res || !bmp || !dib || !bm.bmBits)
851 {
852 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
853 /* if (bm.bmBits)
854 {
855 if (section)
856 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
857 else if (!offset)
858 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
859 } */
860
861 if (dib) { ExFreePool(dib); dib = NULL; }
862 if (bmp) { bmp = NULL; }
863 if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
864 }
865
866 if (bmp)
867 {
868 BITMAPOBJ_UnlockBitmap(res);
869 }
870
871 // Return BITMAP handle and storage location
872 if (NULL != bm.bmBits && NULL != bits)
873 {
874 *bits = bm.bmBits;
875 }
876
877 return res;
878 }
879
880 /***********************************************************************
881 * DIB_GetDIBWidthBytes
882 *
883 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
884 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
885 * 11/16/1999 (RJJ) lifted from wine
886 */
887 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
888 {
889 int words;
890
891 switch(depth)
892 {
893 case 1: words = (width + 31) >> 5; break;
894 case 4: words = (width + 7) >> 3; break;
895 case 8: words = (width + 3) >> 2; break;
896 case 15:
897 case 16: words = (width + 1) >> 1; break;
898 case 24: words = (width * 3 + 3) >> 2; break;
899
900 default:
901 DPRINT("(%d): Unsupported depth\n", depth );
902 /* fall through */
903 case 32:
904 words = width;
905 }
906 return words << 2;
907 }
908
909 /***********************************************************************
910 * DIB_GetDIBImageBytes
911 *
912 * Return the number of bytes used to hold the image in a DIB bitmap.
913 * 11/16/1999 (RJJ) lifted from wine
914 */
915
916 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
917 {
918 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
919 }
920
921 /***********************************************************************
922 * DIB_BitmapInfoSize
923 *
924 * Return the size of the bitmap info structure including color table.
925 * 11/16/1999 (RJJ) lifted from wine
926 */
927
928 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
929 {
930 int colors;
931
932 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
933 {
934 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
935 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
936 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
937 }
938 else /* assume BITMAPINFOHEADER */
939 {
940 colors = info->bmiHeader.biClrUsed;
941 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
942 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
943 }
944 }
945
946 INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
947 PDWORD width,
948 PINT height,
949 PWORD bpp,
950 PWORD compr)
951 {
952 if (header->biSize == sizeof(BITMAPINFOHEADER))
953 {
954 *width = header->biWidth;
955 *height = header->biHeight;
956 *bpp = header->biBitCount;
957 *compr = header->biCompression;
958 return 1;
959 }
960 if (header->biSize == sizeof(BITMAPCOREHEADER))
961 {
962 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
963 *width = core->bcWidth;
964 *height = core->bcHeight;
965 *bpp = core->bcBitCount;
966 *compr = 0;
967 return 0;
968 }
969 DPRINT("(%ld): wrong size for header\n", header->biSize );
970 return -1;
971 }
972
973 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
974 // The specified Device Context (DC) defines what the DIB should be converted to
975 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
976 // change to NtGdiSetDIBits
977 {
978 HBITMAP hBmp = 0;
979 PBITMAPOBJ pBmp = NULL;
980 DIBSECTION *dib;
981 LPBYTE pbits = NULL;
982
983 // Get a pointer to the packed DIB's data
984 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
985 dib = hPackedDIB;
986
987 pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
988
989 // Create a DDB from the DIB
990 hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
991 (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
992
993 // GlobalUnlock(hPackedDIB);
994
995 // Retrieve the internal Pixmap from the DDB
996 pBmp = BITMAPOBJ_LockBitmap(hBmp);
997
998 return pBmp;
999 }
1000
1001 RGBQUAD * FASTCALL
1002 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1003 {
1004 RGBQUAD *lpRGB;
1005 ULONG nNumColors,i;
1006 USHORT *lpIndex;
1007 PPALGDI palGDI;
1008
1009 palGDI = PALETTE_LockPalette(dc->w.hPalette);
1010
1011 if (NULL == palGDI)
1012 {
1013 // RELEASEDCINFO(hDC);
1014 return NULL;
1015 }
1016
1017 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1018 if (lpbmi->bmiHeader.biClrUsed)
1019 {
1020 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1021 }
1022
1023 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1024 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1025
1026 for (i = 0; i < nNumColors; i++)
1027 {
1028 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1029 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1030 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1031 lpIndex++;
1032 }
1033 // RELEASEDCINFO(hDC);
1034 PALETTE_UnlockPalette(dc->w.hPalette);
1035
1036 return lpRGB;
1037 }
1038
1039 HPALETTE FASTCALL
1040 BuildDIBPalette (PBITMAPINFO bmi, PINT paletteType)
1041 {
1042 BYTE bits;
1043 ULONG ColorCount;
1044 PALETTEENTRY *palEntries = NULL;
1045 HPALETTE hPal;
1046
1047 // Determine Bits Per Pixel
1048 bits = bmi->bmiHeader.biBitCount;
1049
1050 // Determine paletteType from Bits Per Pixel
1051 if (bits <= 8)
1052 {
1053 *paletteType = PAL_INDEXED;
1054 }
1055 else if(bits < 24)
1056 {
1057 *paletteType = PAL_BITFIELDS;
1058 }
1059 else
1060 {
1061 *paletteType = PAL_BGR;
1062 }
1063
1064 if (bmi->bmiHeader.biClrUsed == 0)
1065 {
1066 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1067 }
1068 else
1069 {
1070 ColorCount = bmi->bmiHeader.biClrUsed;
1071 }
1072
1073 if (PAL_INDEXED == *paletteType)
1074 {
1075 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1076 }
1077 else
1078 {
1079 hPal = PALETTE_AllocPalette( *paletteType, ColorCount, (ULONG*)palEntries, 0, 0, 0 );
1080 }
1081
1082 return hPal;
1083 }
1084
1085 /* EOF */