Direct2D Bitmap操作

加入位图操作需要引入WIC组件,过程将更复杂:

View Code
#include "stdafx.h"

D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };

struct ComInitialize
{
    ComInitialize()
    {
        HR(CoInitialize(nullptr));
    }
    ~ComInitialize()
    {
        CoUninitialize();
    }
};

template <typename T>
void CreateInstance(REFCLSID clsid, ComPtr<T>& ptr)
{
    ASSERT(!ptr);
    HR(CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, 
        __uuidof(T), reinterpret_cast<void **>(ptr.GetAddressOf())));
}

struct SampleWindow : DesktopWindow<SampleWindow>
{
    ComPtr<IWICFormatConverter> m_image;
    ComPtr<ID2D1Bitmap> m_bitmap;
    D2D1_RECT_F m_location;

    void CreateDeviceIndependentResources()
    {
        ComPtr<IWICImagingFactory> imageFactory;
        CreateInstance(CLSID_WICImagingFactory, imageFactory);

        ComPtr<IWICBitmapDecoder> decoder;
        HR(imageFactory->CreateDecoderFromFilename(L"C:\\Users\\Flysha\\Desktop\\cnblogs.gif", 
            nullptr, GENERIC_READ, 
            WICDecodeMetadataCacheOnLoad, decoder.GetAddressOf()));

        ComPtr<IWICBitmapFrameDecode> frame;
        HR(decoder->GetFrame(0, frame.GetAddressOf()));

        ASSERT(!m_image);
        HR(imageFactory->CreateFormatConverter(m_image.GetAddressOf()));

        m_image->Initialize(frame.Get(), GUID_WICPixelFormat32bppPBGRA, 
            WICBitmapDitherTypeNone, nullptr, 0.0, 
            WICBitmapPaletteTypeCustom);
    }

    LRESULT MouseMoveHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
    {
        WORD x = LOWORD(lparam);
        WORD y = HIWORD(lparam);
        D2D1_POINT_2U size;
        m_image->GetSize(&size.x, &size.y);
        m_location = RectF(x, y, x + size.x, y + size.y);
        Invalidate();
        return 0;
    }

    void CreateDeviceResources()
    {
        HR(m_target->CreateBitmapFromWicBitmap(m_image.Get(), 
            m_bitmap.ReleaseAndGetAddressOf()));
    }

    void Draw()
    {
        m_target->Clear(COLOR_BLUE);
        m_target->DrawBitmap(m_bitmap.Get(), m_location, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;
    SampleWindow window;
    window.Run();
}

示例中加入了图片随鼠标移动而移动的功能。

可能通过将WIC图片(IWICFormatConverter)转换为D2D图片画笔(ID2D1BitmapBrush),可以设置更多有意思的效果:

View Code
#include "stdafx.h"

D2D1_COLOR_F const COLOR_BLUE   = { 0.26f, 0.56f, 0.87f, 1.0f };
D2D1_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };
D2D1_COLOR_F const COLOR_BLACK    = { 0.0f,  0.0f,  0.0f,  1.0f };
D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };
D2D1_COLOR_F const COLOR_RED    = { 1.0f,  0.0f,  0.0f,  1.0f };

struct ComInitialize
{
    ComInitialize()
    {
        HR(CoInitialize(nullptr));
    }
    ~ComInitialize()
    {
        CoUninitialize();
    }
};

template <typename T>
void CreateInstance(REFCLSID clsid, ComPtr<T>& ptr)
{
    ASSERT(!ptr);
    HR(CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, 
        __uuidof(T), reinterpret_cast<void **>(ptr.GetAddressOf())));
}

struct SampleWindow : DesktopWindow<SampleWindow>
{
    ComPtr<IWICFormatConverter> m_image;
    ComPtr<ID2D1BitmapBrush> m_brush;
    D2D1_RECT_F m_location;
    
    void CreateDeviceIndependentResources()
    {
        ComPtr<IWICImagingFactory> imageFactory;
        CreateInstance(CLSID_WICImagingFactory, imageFactory);

        ComPtr<IWICBitmapDecoder> decoder;
        HR(imageFactory->CreateDecoderFromFilename(L"C:\\Users\\Flysha\\Desktop\\cnblogs.gif", 
            nullptr, GENERIC_READ, 
            WICDecodeMetadataCacheOnLoad, decoder.GetAddressOf()));

        ComPtr<IWICBitmapFrameDecode> frame;
        HR(decoder->GetFrame(0, frame.GetAddressOf()));

        HR(imageFactory->CreateFormatConverter(m_image.GetAddressOf()));
        HR(m_image->Initialize(frame.Get(), GUID_WICPixelFormat32bppPBGRA, 
            WICBitmapDitherTypeNone, nullptr, 0.0, 
            WICBitmapPaletteTypeCustom));
    }

    LRESULT MouseMoveHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
    {
        WORD x = LOWORD(lparam);
        WORD y = HIWORD(lparam);
        D2D1_POINT_2U size;
        m_image->GetSize(&size.x, &size.y);
        m_location = RectF(x, y, x + (FLOAT)size.x, y + (FLOAT)size.y);
        Invalidate();
        return 0;
    }

    void CreateDeviceResources()
    {
        ComPtr<ID2D1Bitmap> bitmap;
        HR(m_target->CreateBitmapFromWicBitmap(m_image.Get(), 
            bitmap.GetAddressOf()));
        m_target->CreateBitmapBrush(bitmap.Get(), 
            m_brush.ReleaseAndGetAddressOf());
    }

    void Draw()
    {
        m_target->Clear(COLOR_BLUE);
        auto size = m_target->GetSize();
        auto rect = RectF(0.0f, 0.0f, size.width, size.height);
        m_brush->SetExtendModeX(D2D1_EXTEND_MODE_WRAP);
        m_brush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);
        m_target->FillRectangle(rect, m_brush.Get());
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;
    SampleWindow window;
    window.Run();
}

除此之外,还可以直接将IWICBitmap保存为图形文件:

View Code
#include "stdafx.h"

void SaveAs(ComPtr<IWICImagingFactory>& imageFactory, 
            ComPtr<IWICBitmap> & bitmap, 
            PWSTR filename)
{
    ComPtr<IStream> file;
    HR(SHCreateStreamOnFileEx(filename, 
        STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 
        FILE_ATTRIBUTE_NORMAL, 
        TRUE, 
        nullptr, 
        file.GetAddressOf()));

    ComPtr<IWICBitmapEncoder> encoder;
    HR(imageFactory->CreateEncoder(GUID_ContainerFormatPng, 
        nullptr, 
        encoder.GetAddressOf()));
    HR(encoder->Initialize(file.Get(), WICBitmapEncoderNoCache));

    ComPtr<IWICBitmapFrameEncode> frame;
    ComPtr<IPropertyBag2> props;
    HR(encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf()));
    HR(frame->Initialize(props.Get()));

    UINT width, height;
    HR(bitmap->GetSize(&width, &height));
    HR(frame->SetSize(width, height));

    WICPixelFormatGUID pixelFormat;
    HR(bitmap->GetPixelFormat(&pixelFormat));
    HR(frame->SetPixelFormat(&pixelFormat));

    HR(frame->WriteSource(bitmap.Get(), nullptr));
    HR(frame->Commit());
    HR(encoder->Commit());
}

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;

    ComPtr<IWICImagingFactory> imageFactory;
    CreateInstance(CLSID_WICImagingFactory, imageFactory);

    ComPtr<IWICBitmap> bitmap;
    HR(imageFactory->CreateBitmap(600, 400, 
        GUID_WICPixelFormat32bppPBGRA, 
        WICBitmapCacheOnLoad, 
        bitmap.GetAddressOf()));

    ComPtr<ID2D1Factory> factory;
    HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, factory.GetAddressOf()));

    ComPtr<ID2D1RenderTarget> target;
    HR(factory->CreateWicBitmapRenderTarget(bitmap.Get(), 
        RenderTargetProperties(), target.GetAddressOf()));

    ComPtr<ID2D1SolidColorBrush> brush;
    HR(target->CreateSolidColorBrush(COLOR_BLUE, brush.GetAddressOf()));

    target->BeginDraw();
    target->Clear();
    target->DrawEllipse(Ellipse(Point2F(300.0f, 200.0f), 100.0f, 180.0f), brush.Get(), 10.0f);
    HR(target->EndDraw());
    
    PWSTR filename = L"C:\\users\\flysha\\desktop\\cnblogs.png";
    SaveAs(imageFactory, bitmap, filename);
    ShellExecute(nullptr, nullptr, filename, nullptr, nullptr, SW_SHOWDEFAULT);
}

原文地址:https://www.cnblogs.com/sdflysha/p/3031741.html