mirror of
https://github.com/reactos/reactos.git
synced 2024-08-12 06:06:27 +00:00
[USER32]
- Use CreateDIBitmap with the CDM_CREATEDIB undocumented flag to create alpha bitmaps. This permits to create display compatible yet 32bpp DDBs. CORE-8695 #comment PLease retest, should be OK now. svn path=/trunk/; revision=64967
This commit is contained in:
parent
a09a102a08
commit
954bd930d0
|
@ -241,56 +241,41 @@ static BOOL bmi_has_alpha( const BITMAPINFO *info, const void *bits )
|
|||
*
|
||||
* Create the alpha bitmap for a 32-bpp icon that has an alpha channel.
|
||||
*/
|
||||
static HBITMAP create_alpha_bitmap(
|
||||
_In_ HBITMAP color,
|
||||
_In_opt_ const BITMAPINFO *src_info,
|
||||
_In_opt_ const void *color_bits )
|
||||
static
|
||||
HBITMAP
|
||||
create_alpha_bitmap(
|
||||
_In_opt_ HBITMAP color,
|
||||
_In_opt_ BITMAPINFO *src_info,
|
||||
_In_opt_ const void *color_bits,
|
||||
_In_ LONG width,
|
||||
_In_ LONG height)
|
||||
{
|
||||
HBITMAP alpha = NULL, hbmpOld;
|
||||
BITMAPINFO *info = NULL;
|
||||
HDC hdc = NULL, hdcScreen;
|
||||
void *bits = NULL;
|
||||
unsigned char *ptr;
|
||||
void *bits = NULL;
|
||||
int i;
|
||||
LONG width, height;
|
||||
BITMAP bm;
|
||||
|
||||
if (!GetObjectW( color, sizeof(bm), &bm ))
|
||||
return NULL;
|
||||
if (bm.bmBitsPixel != 32)
|
||||
return NULL;
|
||||
|
||||
hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
|
||||
if(!hdcScreen)
|
||||
if (!hdcScreen)
|
||||
return NULL;
|
||||
if(GetDeviceCaps(hdcScreen, BITSPIXEL) != 32)
|
||||
goto done;
|
||||
hdc = CreateCompatibleDC(hdcScreen);
|
||||
if(!hdc)
|
||||
goto done;
|
||||
|
||||
if(src_info)
|
||||
if (!hdc)
|
||||
{
|
||||
WORD bpp;
|
||||
DWORD compr;
|
||||
int size;
|
||||
|
||||
if(!bmi_has_alpha(src_info, color_bits))
|
||||
goto done;
|
||||
|
||||
if(!DIB_GetBitmapInfo(&src_info->bmiHeader, &width, &height, &bpp, &compr))
|
||||
goto done;
|
||||
if(bpp != 32)
|
||||
goto done;
|
||||
|
||||
size = get_dib_image_size(width, height, bpp);
|
||||
bits = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if(!bits)
|
||||
goto done;
|
||||
CopyMemory(bits, color_bits, size);
|
||||
DeleteDC(hdcScreen);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
||||
if (color)
|
||||
{
|
||||
BITMAP bm;
|
||||
BITMAPINFO *info = NULL;
|
||||
|
||||
if (!GetObjectW( color, sizeof(bm), &bm ))
|
||||
goto done;
|
||||
if (bm.bmBitsPixel != 32)
|
||||
goto done;
|
||||
|
||||
info = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(BITMAPINFO, bmiColors[256]));
|
||||
if(!info)
|
||||
goto done;
|
||||
|
@ -308,46 +293,116 @@ static HBITMAP create_alpha_bitmap(
|
|||
|
||||
bits = HeapAlloc(GetProcessHeap(), 0, info->bmiHeader.biSizeImage);
|
||||
if(!bits)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
goto done;
|
||||
}
|
||||
if(!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
goto done;
|
||||
}
|
||||
if (!bmi_has_alpha( info, bits ))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
goto done;
|
||||
width = bm.bmWidth;
|
||||
height = bm.bmHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/* pre-multiply by alpha */
|
||||
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
|
||||
{
|
||||
unsigned int alpha = ptr[3];
|
||||
ptr[0] = ptr[0] * alpha / 255;
|
||||
ptr[1] = ptr[1] * alpha / 255;
|
||||
ptr[2] = ptr[2] * alpha / 255;
|
||||
/* pre-multiply by alpha */
|
||||
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
|
||||
{
|
||||
unsigned int alpha = ptr[3];
|
||||
ptr[0] = (ptr[0] * alpha) / 255;
|
||||
ptr[1] = (ptr[1] * alpha) / 255;
|
||||
ptr[2] = (ptr[2] * alpha) / 255;
|
||||
}
|
||||
|
||||
/* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */
|
||||
alpha = CreateDIBitmap(hdc, NULL, CBM_INIT | 2, bits, info, DIB_RGB_COLORS);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, info);
|
||||
HeapFree(GetProcessHeap(), 0, bits);
|
||||
}
|
||||
|
||||
/* Create the bitmap */
|
||||
alpha = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
|
||||
if(!alpha)
|
||||
goto done;
|
||||
hbmpOld = SelectObject(hdc, alpha);
|
||||
if(!hbmpOld)
|
||||
goto done;
|
||||
if(!StretchDIBits( hdc, 0, 0, bm.bmWidth, bm.bmHeight,
|
||||
0, 0, width, height,
|
||||
bits, src_info ? src_info : info, DIB_RGB_COLORS, SRCCOPY ))
|
||||
else
|
||||
{
|
||||
SelectObject(hdc, hbmpOld);
|
||||
hbmpOld = NULL;
|
||||
DeleteObject(alpha);
|
||||
alpha = NULL;
|
||||
WORD bpp;
|
||||
DWORD compr;
|
||||
int size;
|
||||
LONG orig_width, orig_height;
|
||||
|
||||
if(!bmi_has_alpha(src_info, color_bits))
|
||||
goto done;
|
||||
|
||||
if(!DIB_GetBitmapInfo(&src_info->bmiHeader, &orig_width, &orig_height, &bpp, &compr))
|
||||
goto done;
|
||||
if(bpp != 32)
|
||||
goto done;
|
||||
|
||||
size = get_dib_image_size(orig_width, orig_height, bpp);
|
||||
bits = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if(!bits)
|
||||
goto done;
|
||||
CopyMemory(bits, color_bits, size);
|
||||
/* pre-multiply by alpha */
|
||||
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
|
||||
{
|
||||
unsigned int alpha = ptr[3];
|
||||
ptr[0] = (ptr[0] * alpha) / 255;
|
||||
ptr[1] = (ptr[1] * alpha) / 255;
|
||||
ptr[2] = (ptr[2] * alpha) / 255;
|
||||
}
|
||||
|
||||
/* Create the bitmap. Set the bitmap info to have the right width and height */
|
||||
if(src_info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||
{
|
||||
((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcWidth = width;
|
||||
((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_info->bmiHeader.biWidth = width;
|
||||
src_info->bmiHeader.biHeight = height;
|
||||
}
|
||||
/* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */
|
||||
alpha = CreateDIBitmap(hdcScreen, NULL, 2, NULL, src_info, DIB_RGB_COLORS);
|
||||
/* Restore values */
|
||||
if(src_info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||
{
|
||||
((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcWidth = orig_width;
|
||||
((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = orig_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_info->bmiHeader.biWidth = orig_width;
|
||||
src_info->bmiHeader.biHeight = orig_height;
|
||||
}
|
||||
if(!alpha)
|
||||
goto done;
|
||||
hbmpOld = SelectObject(hdc, alpha);
|
||||
if(!hbmpOld)
|
||||
{
|
||||
DeleteObject(alpha);
|
||||
alpha = NULL;
|
||||
goto done;
|
||||
}
|
||||
if(!StretchDIBits( hdc, 0, 0, width, height,
|
||||
0, 0, orig_width, orig_height,
|
||||
bits, src_info, DIB_RGB_COLORS, SRCCOPY ))
|
||||
{
|
||||
SelectObject(hdc, hbmpOld);
|
||||
hbmpOld = NULL;
|
||||
DeleteObject(alpha);
|
||||
alpha = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectObject(hdc, hbmpOld);
|
||||
}
|
||||
}
|
||||
SelectObject(hdc, hbmpOld);
|
||||
|
||||
done:
|
||||
DeleteDC(hdcScreen);
|
||||
if(hdc) DeleteDC( hdc );
|
||||
if(info) HeapFree( GetProcessHeap(), 0, info );
|
||||
DeleteDC( hdc );
|
||||
if(bits) HeapFree(GetProcessHeap(), 0, bits);
|
||||
|
||||
TRACE("Returning 0x%08x.\n", alpha);
|
||||
|
@ -571,8 +626,7 @@ static BOOL CURSORICON_GetCursorDataFromBMI(
|
|||
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
|
||||
goto done;
|
||||
pdata->bpp = GetDeviceCaps(hdcScreen, BITSPIXEL);
|
||||
if(pdata->bpp == 32)
|
||||
pdata->hbmAlpha = create_alpha_bitmap(pdata->hbmColor, pbmiCopy, pvColor);
|
||||
pdata->hbmAlpha = create_alpha_bitmap(NULL, pbmiCopy, pvColor, pdata->cx, pdata->cy);
|
||||
|
||||
/* Now convert the info to monochrome for the mask bits */
|
||||
if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
|
||||
|
@ -673,7 +727,7 @@ static BOOL CURSORICON_GetCursorDataFromIconInfo(
|
|||
pCursorData->cx = bm.bmWidth;
|
||||
pCursorData->cy = bm.bmHeight;
|
||||
if(pCursorData->bpp == 32)
|
||||
pCursorData->hbmAlpha = create_alpha_bitmap(pCursorData->hbmColor, NULL, NULL);
|
||||
pCursorData->hbmAlpha = create_alpha_bitmap(pCursorData->hbmColor, NULL, NULL, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue