Author: jimtabor Date: Mon Sep 4 07:08:18 2006 New Revision: 23906
URL: http://svn.reactos.org/svn/reactos?rev=23906&view=rev Log: User32 bitmap.c: - Patch by Michael Kaufmann - CopyImage: Handle the flags LR_COPYDELETEORG, LR_CREATEDIBSECTION, and LR_MONOCHROME.
Modified: trunk/reactos/dll/win32/user32/windows/bitmap.c
Modified: trunk/reactos/dll/win32/user32/windows/bitmap.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/bi... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/bitmap.c (original) +++ trunk/reactos/dll/win32/user32/windows/bitmap.c Mon Sep 4 07:08:18 2006 @@ -562,36 +562,200 @@ IN INT desiredy, IN UINT flags) { - HBITMAP res; - BITMAP bm; - +/* + * BUGS + * Only Windows NT 4.0 supports the LR_COPYRETURNORG flag for bitmaps, + * all other versions (95/2000/XP have been tested) ignore it. + * + * NOTES + * If LR_CREATEDIBSECTION is absent, the copy will be monochrome for + * a monochrome source bitmap or if LR_MONOCHROME is present, otherwise + * the copy will have the same depth as the screen. + * The content of the image will only be copied if the bit depth of the + * original image is compatible with the bit depth of the screen, or + * if the source is a DIB section. + * The LR_MONOCHROME flag is ignored if LR_CREATEDIBSECTION is present. + */ switch (type) { case IMAGE_BITMAP: { - DPRINT("WARNING: Incomplete implementation of CopyImage!\n"); - /* - * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE, - * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME. - */ - if (!GetObjectW(hnd, sizeof(bm), &bm)) - return NULL; - bm.bmBits = NULL; - if ((res = CreateBitmapIndirect(&bm))) + HBITMAP res = NULL; + DIBSECTION ds; + int objSize; + BITMAPINFO * bi; + + objSize = GetObjectW( hnd, sizeof(ds), &ds ); + if (!objSize) return 0; + if ((desiredx < 0) || (desiredy < 0)) return 0; + + if (flags & LR_COPYFROMRESOURCE) { - char *buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight); - if (buf == NULL) - { - DeleteObject(res); - return NULL; - } - GetBitmapBits(hnd, bm.bmWidthBytes * bm.bmHeight, buf); - SetBitmapBits(res, bm.bmWidthBytes * bm.bmHeight, buf); - HeapFree(GetProcessHeap(), 0, buf); + DPRINT1("FIXME: The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n"); } - return res; + + if (desiredx == 0) desiredx = ds.dsBm.bmWidth; + if (desiredy == 0) desiredy = ds.dsBm.bmHeight; + + /* Allocate memory for a BITMAPINFOHEADER structure and a + color table. The maximum number of colors in a color table + is 256 which corresponds to a bitmap with depth 8. + Bitmaps with higher depths don't have color tables. */ + bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + if (!bi) return 0; + + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes; + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + bi->bmiHeader.biCompression = BI_RGB; + + if (flags & LR_CREATEDIBSECTION) + { + /* Create a DIB section. LR_MONOCHROME is ignored */ + void * bits; + HDC dc = CreateCompatibleDC(NULL); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB. + Get its attributes to create an exact copy */ + memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER)); + } + + /* Get the color table or the color masks */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + + bi->bmiHeader.biWidth = desiredx; + bi->bmiHeader.biHeight = desiredy; + bi->bmiHeader.biSizeImage = 0; + + res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0); + DeleteDC(dc); + } + else + { + /* Create a device-dependent bitmap */ + + BOOL monochrome = (flags & LR_MONOCHROME); + + if (objSize == sizeof(DIBSECTION)) + { + /* The source bitmap is a DIB section. + Get its attributes */ + HDC dc = CreateCompatibleDC(NULL); + bi->bmiHeader.biSize = sizeof(bi->bmiHeader); + bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel; + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + DeleteDC(dc); + + if (!monochrome && ds.dsBm.bmBitsPixel == 1) + { + /* Look if the colors of the DIB are black and white */ + + monochrome = + (bi->bmiColors[0].rgbRed == 0xff + && bi->bmiColors[0].rgbGreen == 0xff + && bi->bmiColors[0].rgbBlue == 0xff + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0 + && bi->bmiColors[1].rgbGreen == 0 + && bi->bmiColors[1].rgbBlue == 0 + && bi->bmiColors[1].rgbReserved == 0) + || + (bi->bmiColors[0].rgbRed == 0 + && bi->bmiColors[0].rgbGreen == 0 + && bi->bmiColors[0].rgbBlue == 0 + && bi->bmiColors[0].rgbReserved == 0 + && bi->bmiColors[1].rgbRed == 0xff + && bi->bmiColors[1].rgbGreen == 0xff + && bi->bmiColors[1].rgbBlue == 0xff + && bi->bmiColors[1].rgbReserved == 0); + } + } + else if (!monochrome) + { + monochrome = ds.dsBm.bmBitsPixel == 1; + } + + if (monochrome) + { + res = CreateBitmap(desiredx, desiredy, 1, 1, NULL); + } + else + { + HDC screenDC = GetDC(NULL); + res = CreateCompatibleBitmap(screenDC, desiredx, desiredy); + ReleaseDC(NULL, screenDC); + } + } + + if (res) + { + /* Only copy the bitmap if it's a DIB section or if it's + compatible to the screen */ + BOOL copyContents; + + if (objSize == sizeof(DIBSECTION)) + { + copyContents = TRUE; + } + else + { + HDC screenDC = GetDC(NULL); + int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL); + ReleaseDC(NULL, screenDC); + + copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth); + } + + if (copyContents) + { + /* The source bitmap may already be selected in a device context, + use GetDIBits/StretchDIBits and not StretchBlt */ + + HDC dc; + void * bits; + + dc = CreateCompatibleDC(NULL); + + bi->bmiHeader.biWidth = ds.dsBm.bmWidth; + bi->bmiHeader.biHeight = ds.dsBm.bmHeight; + bi->bmiHeader.biSizeImage = 0; + bi->bmiHeader.biClrUsed = 0; + bi->bmiHeader.biClrImportant = 0; + + /* Fill in biSizeImage */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS); + bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage); + + if (bits) + { + HBITMAP oldBmp; + + /* Get the image bits of the source bitmap */ + GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS); + + /* Copy it to the destination bitmap */ + oldBmp = SelectObject(dc, res); + StretchDIBits(dc, 0, 0, desiredx, desiredy, + 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight, + bits, bi, DIB_RGB_COLORS, SRCCOPY); + SelectObject(dc, oldBmp); + + HeapFree(GetProcessHeap(), 0, bits); + } + + DeleteDC(dc); + } + + if (flags & LR_COPYDELETEORG) + { + DeleteObject(hnd); + } + } + HeapFree(GetProcessHeap(), 0, bi); + return (HICON)res; } - case IMAGE_ICON: { static BOOL IconMsgDisplayed = FALSE; @@ -602,6 +766,7 @@ IconMsgDisplayed = TRUE; } return CopyIcon(hnd); +// return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags); }
case IMAGE_CURSOR: @@ -613,9 +778,13 @@ DPRINT("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n"); IconMsgDisplayed = TRUE; } + /* Should call CURSORICON_ExtCopy but more testing + * needs to be done before we change this + */ + if (flags) DPRINT1("FIXME: Flags are ignored\n"); return CopyCursor(hnd); } } - return NULL; } +