mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 02:43:09 +00:00
[MSPAINT] Speed up for black and white (#5563)
Follow-up to #5554. - Speed up ImageModel::PushBlackAndWhite by using GetDIBits and SetDIBits. CORE-19094
This commit is contained in:
parent
49dbc8fbbb
commit
455c1fe1b9
3 changed files with 104 additions and 35 deletions
|
@ -13,6 +13,13 @@ float g_xDpi = 96;
|
||||||
float g_yDpi = 96;
|
float g_yDpi = 96;
|
||||||
SYSTEMTIME g_fileTime;
|
SYSTEMTIME g_fileTime;
|
||||||
|
|
||||||
|
#define WIDTHBYTES(i) (((i) + 31) / 32 * 4)
|
||||||
|
|
||||||
|
struct BITMAPINFOEX : BITMAPINFO
|
||||||
|
{
|
||||||
|
RGBQUAD bmiColorsExtra[256 - 1];
|
||||||
|
};
|
||||||
|
|
||||||
/* FUNCTIONS ********************************************************/
|
/* FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
// Convert DPI (dots per inch) into PPCM (pixels per centimeter)
|
// Convert DPI (dots per inch) into PPCM (pixels per centimeter)
|
||||||
|
@ -519,3 +526,89 @@ HBITMAP BitmapFromHEMF(HENHMETAFILE hEMF)
|
||||||
|
|
||||||
return hbm;
|
return hbm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL IsBitmapBlackAndWhite(HBITMAP hbm)
|
||||||
|
{
|
||||||
|
BITMAP bm;
|
||||||
|
if (!::GetObjectW(hbm, sizeof(bm), &bm))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bm.bmBitsPixel == 1)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
BITMAPINFOEX bmi;
|
||||||
|
ZeroMemory(&bmi, sizeof(bmi));
|
||||||
|
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
|
||||||
|
bmi.bmiHeader.biWidth = bm.bmWidth;
|
||||||
|
bmi.bmiHeader.biHeight = bm.bmHeight;
|
||||||
|
bmi.bmiHeader.biPlanes = 1;
|
||||||
|
bmi.bmiHeader.biBitCount = 24;
|
||||||
|
|
||||||
|
DWORD widthbytes = WIDTHBYTES(24 * bm.bmWidth);
|
||||||
|
DWORD cbBits = widthbytes * bm.bmHeight;
|
||||||
|
LPBYTE pbBits = new BYTE[cbBits];
|
||||||
|
|
||||||
|
HDC hdc = ::CreateCompatibleDC(NULL);
|
||||||
|
::GetDIBits(hdc, hbm, 0, bm.bmHeight, pbBits, &bmi, DIB_RGB_COLORS);
|
||||||
|
::DeleteDC(hdc);
|
||||||
|
|
||||||
|
BOOL bBlackAndWhite = TRUE;
|
||||||
|
for (LONG y = 0; y < bm.bmHeight; ++y)
|
||||||
|
{
|
||||||
|
LPBYTE pbLine = &pbBits[widthbytes * y];
|
||||||
|
for (LONG x = 0; x < bm.bmWidth; ++x)
|
||||||
|
{
|
||||||
|
BYTE Blue = *pbLine++;
|
||||||
|
BYTE Green = *pbLine++;
|
||||||
|
BYTE Red = *pbLine++;
|
||||||
|
COLORREF rgbColor = RGB(Red, Green, Blue);
|
||||||
|
if (rgbColor != RGB(0, 0, 0) && rgbColor != RGB(255, 255, 255))
|
||||||
|
{
|
||||||
|
bBlackAndWhite = FALSE;
|
||||||
|
goto Finish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish:
|
||||||
|
delete[] pbBits;
|
||||||
|
|
||||||
|
return bBlackAndWhite;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP ConvertToBlackAndWhite(HBITMAP hbm)
|
||||||
|
{
|
||||||
|
BITMAP bm;
|
||||||
|
if (!::GetObject(hbm, sizeof(bm), &bm))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BITMAPINFOEX bmi;
|
||||||
|
ZeroMemory(&bmi, sizeof(bmi));
|
||||||
|
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bmi.bmiHeader.biWidth = bm.bmWidth;
|
||||||
|
bmi.bmiHeader.biHeight = bm.bmHeight;
|
||||||
|
bmi.bmiHeader.biPlanes = 1;
|
||||||
|
bmi.bmiHeader.biBitCount = 1;
|
||||||
|
bmi.bmiColors[1].rgbBlue = 255;
|
||||||
|
bmi.bmiColors[1].rgbGreen = 255;
|
||||||
|
bmi.bmiColors[1].rgbRed = 255;
|
||||||
|
HDC hdc = ::CreateCompatibleDC(NULL);
|
||||||
|
LPVOID pvMonoBits;
|
||||||
|
HBITMAP hMonoBitmap = ::CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvMonoBits, NULL, 0);
|
||||||
|
if (!hMonoBitmap)
|
||||||
|
{
|
||||||
|
::DeleteDC(hdc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP hNewBitmap = CreateDIBWithProperties(bm.bmWidth, bm.bmHeight);
|
||||||
|
if (hNewBitmap)
|
||||||
|
{
|
||||||
|
::GetDIBits(hdc, hbm, 0, bm.bmHeight, pvMonoBits, &bmi, DIB_RGB_COLORS);
|
||||||
|
::SetDIBits(hdc, hNewBitmap, 0, bm.bmHeight, pvMonoBits, &bmi, DIB_RGB_COLORS);
|
||||||
|
}
|
||||||
|
::DeleteObject(hMonoBitmap);
|
||||||
|
::DeleteDC(hdc);
|
||||||
|
|
||||||
|
return hNewBitmap;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
BOOL IsBitmapBlackAndWhite(HBITMAP hbm);
|
||||||
HBITMAP CreateDIBWithProperties(int width, int height);
|
HBITMAP CreateDIBWithProperties(int width, int height);
|
||||||
HBITMAP CreateMonoBitmap(int width, int height, BOOL bWhite);
|
HBITMAP CreateMonoBitmap(int width, int height, BOOL bWhite);
|
||||||
HBITMAP CreateColorDIB(int width, int height, COLORREF rgb);
|
HBITMAP CreateColorDIB(int width, int height, COLORREF rgb);
|
||||||
HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight);
|
HBITMAP CachedBufferDIB(HBITMAP hbm, int minimalWidth, int minimalHeight);
|
||||||
|
HBITMAP ConvertToBlackAndWhite(HBITMAP hbm);
|
||||||
|
|
||||||
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx = 0, INT cy = 0);
|
HBITMAP CopyMonoImage(HBITMAP hbm, INT cx = 0, INT cy = 0);
|
||||||
|
|
||||||
|
|
|
@ -270,44 +270,18 @@ HBITMAP ImageModel::CopyBitmap()
|
||||||
|
|
||||||
BOOL ImageModel::IsBlackAndWhite()
|
BOOL ImageModel::IsBlackAndWhite()
|
||||||
{
|
{
|
||||||
LONG cxWidth = GetWidth(), cyHeight = GetHeight();
|
::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
|
||||||
for (LONG y = 0; y < cyHeight; ++y)
|
BOOL bBlackAndWhite = IsBitmapBlackAndWhite(m_hBms[m_currInd]);
|
||||||
{
|
m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); // Re-select
|
||||||
for (LONG x = 0; x < cxWidth; ++x)
|
return bBlackAndWhite;
|
||||||
{
|
|
||||||
COLORREF rgbColor = ::GetPixel(m_hDrawingDC, x, y);
|
|
||||||
if (rgbColor != RGB(0, 0, 0) && rgbColor != RGB(255, 255, 255))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageModel::PushBlackAndWhite()
|
void ImageModel::PushBlackAndWhite()
|
||||||
{
|
{
|
||||||
HBITMAP hNewBitmap = CopyBitmap();
|
::SelectObject(m_hDrawingDC, m_hbmOld); // De-select
|
||||||
if (!hNewBitmap)
|
HBITMAP hNewBitmap = ConvertToBlackAndWhite(m_hBms[m_currInd]);
|
||||||
return;
|
m_hbmOld = ::SelectObject(m_hDrawingDC, m_hBms[m_currInd]); // Re-select
|
||||||
|
|
||||||
HDC hdc2 = ::CreateCompatibleDC(NULL);
|
if (hNewBitmap)
|
||||||
HGDIOBJ hbm2Old = ::SelectObject(hdc2, hNewBitmap);
|
PushImageForUndo(hNewBitmap);
|
||||||
LONG cxWidth = GetWidth(), cyHeight = GetHeight();
|
|
||||||
for (LONG y = 0; y < cyHeight; ++y)
|
|
||||||
{
|
|
||||||
for (LONG x = 0; x < cxWidth; ++x)
|
|
||||||
{
|
|
||||||
COLORREF rgbColor = ::GetPixel(m_hDrawingDC, x, y);
|
|
||||||
BYTE Red = GetRValue(rgbColor);
|
|
||||||
BYTE Green = GetGValue(rgbColor);
|
|
||||||
BYTE Blue = GetBValue(rgbColor);
|
|
||||||
if ((Red + Green + Blue) / 3 >= 255 / 2)
|
|
||||||
::SetPixelV(hdc2, x, y, RGB(255, 255, 255)); // White
|
|
||||||
else
|
|
||||||
::SetPixelV(hdc2, x, y, RGB(0, 0, 0)); // Black
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::SelectObject(hdc2, hbm2Old);
|
|
||||||
::DeleteDC(hdc2);
|
|
||||||
|
|
||||||
PushImageForUndo(hNewBitmap);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue