mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 08:15:41 +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
1 changed files with 123 additions and 69 deletions
|
@ -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.
|
* Create the alpha bitmap for a 32-bpp icon that has an alpha channel.
|
||||||
*/
|
*/
|
||||||
static HBITMAP create_alpha_bitmap(
|
static
|
||||||
_In_ HBITMAP color,
|
HBITMAP
|
||||||
_In_opt_ const BITMAPINFO *src_info,
|
create_alpha_bitmap(
|
||||||
_In_opt_ const void *color_bits )
|
_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;
|
HBITMAP alpha = NULL, hbmpOld;
|
||||||
BITMAPINFO *info = NULL;
|
|
||||||
HDC hdc = NULL, hdcScreen;
|
HDC hdc = NULL, hdcScreen;
|
||||||
void *bits = NULL;
|
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
|
void *bits = NULL;
|
||||||
int i;
|
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);
|
hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
|
||||||
if (!hdcScreen)
|
if (!hdcScreen)
|
||||||
return NULL;
|
return NULL;
|
||||||
if(GetDeviceCaps(hdcScreen, BITSPIXEL) != 32)
|
|
||||||
goto done;
|
|
||||||
hdc = CreateCompatibleDC(hdcScreen);
|
hdc = CreateCompatibleDC(hdcScreen);
|
||||||
if (!hdc)
|
if (!hdc)
|
||||||
goto done;
|
|
||||||
|
|
||||||
if(src_info)
|
|
||||||
{
|
{
|
||||||
WORD bpp;
|
DeleteDC(hdcScreen);
|
||||||
DWORD compr;
|
return NULL;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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]));
|
info = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(BITMAPINFO, bmiColors[256]));
|
||||||
if(!info)
|
if(!info)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -308,46 +293,116 @@ static HBITMAP create_alpha_bitmap(
|
||||||
|
|
||||||
bits = HeapAlloc(GetProcessHeap(), 0, info->bmiHeader.biSizeImage);
|
bits = HeapAlloc(GetProcessHeap(), 0, info->bmiHeader.biSizeImage);
|
||||||
if(!bits)
|
if(!bits)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, info);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
if(!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
|
if(!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, info);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
if (!bmi_has_alpha( info, bits ))
|
if (!bmi_has_alpha( info, bits ))
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, info);
|
||||||
goto done;
|
goto done;
|
||||||
width = bm.bmWidth;
|
|
||||||
height = bm.bmHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pre-multiply by alpha */
|
/* pre-multiply by alpha */
|
||||||
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
|
for (i = 0, ptr = bits; i < width * height; i++, ptr += 4)
|
||||||
{
|
{
|
||||||
unsigned int alpha = ptr[3];
|
unsigned int alpha = ptr[3];
|
||||||
ptr[0] = ptr[0] * alpha / 255;
|
ptr[0] = (ptr[0] * alpha) / 255;
|
||||||
ptr[1] = ptr[1] * alpha / 255;
|
ptr[1] = (ptr[1] * alpha) / 255;
|
||||||
ptr[2] = ptr[2] * alpha / 255;
|
ptr[2] = (ptr[2] * alpha) / 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the bitmap */
|
/* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */
|
||||||
alpha = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
|
alpha = CreateDIBitmap(hdc, NULL, CBM_INIT | 2, bits, info, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, info);
|
||||||
|
HeapFree(GetProcessHeap(), 0, bits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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)
|
if(!alpha)
|
||||||
goto done;
|
goto done;
|
||||||
hbmpOld = SelectObject(hdc, alpha);
|
hbmpOld = SelectObject(hdc, alpha);
|
||||||
if(!hbmpOld)
|
if(!hbmpOld)
|
||||||
|
{
|
||||||
|
DeleteObject(alpha);
|
||||||
|
alpha = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
if(!StretchDIBits( hdc, 0, 0, bm.bmWidth, bm.bmHeight,
|
}
|
||||||
0, 0, width, height,
|
if(!StretchDIBits( hdc, 0, 0, width, height,
|
||||||
bits, src_info ? src_info : info, DIB_RGB_COLORS, SRCCOPY ))
|
0, 0, orig_width, orig_height,
|
||||||
|
bits, src_info, DIB_RGB_COLORS, SRCCOPY ))
|
||||||
{
|
{
|
||||||
SelectObject(hdc, hbmpOld);
|
SelectObject(hdc, hbmpOld);
|
||||||
hbmpOld = NULL;
|
hbmpOld = NULL;
|
||||||
DeleteObject(alpha);
|
DeleteObject(alpha);
|
||||||
alpha = NULL;
|
alpha = NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SelectObject(hdc, hbmpOld);
|
SelectObject(hdc, hbmpOld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
DeleteDC(hdcScreen);
|
DeleteDC(hdcScreen);
|
||||||
if(hdc) DeleteDC( hdc );
|
DeleteDC( hdc );
|
||||||
if(info) HeapFree( GetProcessHeap(), 0, info );
|
|
||||||
if(bits) HeapFree(GetProcessHeap(), 0, bits);
|
if(bits) HeapFree(GetProcessHeap(), 0, bits);
|
||||||
|
|
||||||
TRACE("Returning 0x%08x.\n", alpha);
|
TRACE("Returning 0x%08x.\n", alpha);
|
||||||
|
@ -571,8 +626,7 @@ static BOOL CURSORICON_GetCursorDataFromBMI(
|
||||||
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
|
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
|
||||||
goto done;
|
goto done;
|
||||||
pdata->bpp = GetDeviceCaps(hdcScreen, BITSPIXEL);
|
pdata->bpp = GetDeviceCaps(hdcScreen, BITSPIXEL);
|
||||||
if(pdata->bpp == 32)
|
pdata->hbmAlpha = create_alpha_bitmap(NULL, pbmiCopy, pvColor, pdata->cx, pdata->cy);
|
||||||
pdata->hbmAlpha = create_alpha_bitmap(pdata->hbmColor, pbmiCopy, pvColor);
|
|
||||||
|
|
||||||
/* Now convert the info to monochrome for the mask bits */
|
/* Now convert the info to monochrome for the mask bits */
|
||||||
if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
|
if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
|
||||||
|
@ -673,7 +727,7 @@ static BOOL CURSORICON_GetCursorDataFromIconInfo(
|
||||||
pCursorData->cx = bm.bmWidth;
|
pCursorData->cx = bm.bmWidth;
|
||||||
pCursorData->cy = bm.bmHeight;
|
pCursorData->cy = bm.bmHeight;
|
||||||
if(pCursorData->bpp == 32)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue