Сглаживание в MFC - PullRequest
       21

Сглаживание в MFC

0 голосов
/ 08 октября 2018

Я пытаюсь реализовать сглаживание в своем приложении MFC, я использую технику, описанную в этого руководства .

  • Создание растрового изображения (2x, 4x, 8x) размер исходного растрового изображения.
  • Нарисуйте растровое изображение с измененным размером (я использую только простые фигуры (линии, круги и т. Д.)).
  • Установите для StretchBlt Mode значение HalfTone.
  • И измените размер с помощью StretchBlt до исходного размера.

Используя этот способ, рисование растрового изображения с измененным размером работает, но я хочу создать более общую функцию, которая получает растровое изображение срисунок уже сделан и возвращен с сглаживанием, я попробовал это:

static HBITMAP AntiAliasing(HBITMAP hBitmap)
{
    int escala = 4;

    HBITMAP bmp = __copia(hBitmap); //  Copy the bitmap.

    HDC hMemDC = CreateCompatibleDC(NULL);
    HBITMAP bmpAntigo1 = (HBITMAP)::SelectObject(hMemDC, bmp);

    BITMAP bitmap;
    ::GetObject(hBitmap, sizeof(BITMAP), &bitmap);

    //  Create a bitmap (2x, 4x, 8x) the size of the original bitmap.
    HDC hDCDimensionado = ::CreateCompatibleDC(hMemDC);
    HBITMAP bmpDimensionado = ::CreateCompatibleBitmap(hDCDimensionado, 
                                                        bitmap.bmWidth * escala, 
                                                        bitmap.bmHeight * escala);

    HBITMAP hBmpVelho = (HBITMAP)::SelectObject(hDCDimensionado, bmpDimensionado);

    //  I also tried with {BLACKONWHITE, HALFTONE, WHITEONBLACK}
    int oldStretchBltMode2 = ::SetStretchBltMode(hDCDimensionado, COLORONCOLOR);    

    //  Resize the  bitmap to the new size.
    ::StretchBlt(hDCDimensionado,
        0, 0, bitmap.bmWidth * escala, bitmap.bmHeight * escala, 
        hMemDC, 
        0, 0, bitmap.bmWidth, bitmap.bmHeight, 
        SRCCOPY);

    /*
    *   Here the bitmap has lost his colors and became black and white.
    */

    ::SetStretchBltMode(hDCDimensionado, oldStretchBltMode2);

    //  Set StretchBltMode to halfTone so can mimic the anti aliasing effect.
    int oldStretchBltMode = ::SetStretchBltMode(hMemDC, HALFTONE);

    //  resize to the original size.
    ::StretchBlt(hMemDC, 
        0, 0, bitmap.bmWidth, bitmap.bmHeight, 
        hDCDimensionado, 
        0, 0, escala * bitmap.bmWidth, escala * bitmap.bmHeight, 
        SRCCOPY);

    ::SetStretchBltMode(hMemDC, oldStretchBltMode);
    ::SelectObject(hMemDC, bmpAntigo1);
    ::DeleteDC(hMemDC);
    ::SelectObject(hDCDimensionado, hBmpVelho);
    DeleteDC(hDCDimensionado);

    return bmp;
}

Но эта функция не работает, результат теряет свои цвета (все рисунки стали черными), и нет антиaliasing.

Любая помощь будет оценена!

1 Ответ

0 голосов
/ 08 октября 2018

Из документации для CreateCompatibleBitmap:

Примечание. При создании контекста устройства памяти изначально в нем выбирается монохромное растровое изображение 1: 1.Если этот контекст устройства памяти используется в CreateCompatibleBitmap, созданное растровое изображение является монохромным растровым изображением.Чтобы создать цветное растровое изображение, используйте HDC, который использовался для создания контекста устройства памяти, как показано в следующем коде:

Измените код и введите hdc для рабочего стола, как показано ниже:

HDC hdc = ::GetDC(0);
HBITMAP bmpDimensionado = ::CreateCompatibleBitmap(hdc, ...)
::ReleaseDC(0, hdc);


Это покажет изображение, однако этот метод не даст желаемого эффекта, поскольку он просто увеличивает каждый пиксель до большего размера и уменьшает его до исходного пикселя.Нет смешения с соседними пикселями.

Используйте другие методы, такие как Direct2D с эффектом размытия по Гауссу, или используйте вместо этого GDI + с режимом интерполяции:

Gdiplus::GdiplusStartup...

void foo(HDC hdc)
{
    Gdiplus::Bitmap bitmap(L"file.bmp");
    if(bitmap.GetLastStatus() != 0)
        return 0;
    auto w = bitmap.GetWidth();
    auto h = bitmap.GetHeight();

    auto maxw = w * 2;
    auto maxh = h * 2;
    Gdiplus::Bitmap membmp(maxw, maxh);
    Gdiplus::Graphics memgr(&membmp);
    memgr.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBilinear);
    memgr.DrawImage(&bitmap, 0, 0, maxw, maxh);

    Gdiplus::Graphics gr(hdc);
    gr.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBilinear);
    gr.DrawImage(&membmp, 0, 0, w, h);
}


Если целевое окно по крайней мереVista, используйте GDI + версии 1.1 с эффектом размытия.См. Также Как включить GDI + 1.1 в проекте MFC
#define GDIPVER 0x0110 //add this to precompiled header file

void blur(HDC hdc)
{
    Gdiplus::Graphics graphics(hdc);
    Gdiplus::Bitmap bitmap(L"file.bmp");
    if(bitmap.GetLastStatus() != 0)
        return;

    Gdiplus::Blur blur;
    Gdiplus::BlurParams blur_param;
    blur_param.radius = 3; //change the radius for different result
    blur_param.expandEdge = TRUE;
    blur.SetParameters(&blur_param);
    bitmap.ApplyEffect(&blur, NULL);

    graphics.DrawImage(&bitmap, 0, 0);
}
...