Created
April 3, 2023 13:18
-
-
Save smourier/5b770d32043121d477a8079ef6be0995 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _AFXDLL | |
#include <WinSock2.h> // MFC... | |
#include <windows.h> | |
#include <afxwin.h> // CBitmap | |
#include <atlbase.h> | |
#include <atlcom.h> // CComPtr | |
#include <d2d1.h> | |
#include <d2d1_3.h> // ID2D1DeviceContext5 | |
#include <wincodec.h> // Wic | |
#pragma comment(lib, "d2d1") | |
void WicSave(HBITMAP bitmap) | |
{ | |
// create a Wic bitmap | |
CComPtr<IWICImagingFactory> wicFactory; | |
auto hr = wicFactory.CoCreateInstance(CLSID_WICImagingFactory); | |
CComPtr<IWICBitmap> wicBitmap; | |
hr = wicFactory->CreateBitmapFromHBITMAP(bitmap, nullptr, WICBitmapUseAlpha, &wicBitmap); | |
// create PNG file | |
CComPtr<IWICStream> wicStream; | |
hr = wicFactory->CreateStream(&wicStream); | |
hr = wicStream->InitializeFromFilename(L"drawing2.png", GENERIC_WRITE); | |
// create PNG encoder | |
CComPtr<IWICBitmapEncoder> encoder; | |
hr = wicFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr, &encoder); | |
hr = encoder->Initialize(wicStream, WICBitmapEncoderNoCache); | |
// create frame | |
CComPtr<IWICBitmapFrameEncode> frame; | |
hr = encoder->CreateNewFrame(&frame, nullptr); | |
hr = frame->Initialize(nullptr); | |
// write bitmap | |
hr = frame->WriteSource(wicBitmap, nullptr); | |
// commit | |
hr = frame->Commit(); | |
hr = encoder->Commit(); | |
} | |
void BuildSvgAsCBitmap(int width, int height) | |
{ | |
// initialize Direct2D | |
D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; // remove this in release | |
CComPtr<ID2D1Factory> factory; | |
auto hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_ID2D1Factory, &options, (void**)&factory); | |
// create an in-memory bitmap | |
BITMAPINFO bitmapInfo = {}; | |
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader); | |
bitmapInfo.bmiHeader.biWidth = width; | |
bitmapInfo.bmiHeader.biHeight = height; | |
bitmapInfo.bmiHeader.biPlanes = 1; | |
bitmapInfo.bmiHeader.biBitCount = 32; | |
bitmapInfo.bmiHeader.biCompression = BI_RGB; | |
CBitmap bitmap; | |
void* bits = 0; | |
auto res = bitmap.Attach(CreateDIBSection(nullptr, &bitmapInfo, DIB_RGB_COLORS, &bits, nullptr, 0)); | |
// create a DC render target | |
CComPtr<ID2D1DCRenderTarget> target; | |
D2D1_RENDER_TARGET_PROPERTIES props = {}; | |
props.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; | |
props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; | |
hr = factory->CreateDCRenderTarget(&props, &target); | |
// create a DC, select bitmap and bind DC | |
CDC cdc; | |
cdc.CreateCompatibleDC(nullptr); | |
auto old = cdc.SelectObject(bitmap); | |
RECT rc = { 0, 0, width, height }; | |
hr = target->BindDC(cdc.GetSafeHdc(), &rc); | |
// requires Windows 10 1703 | |
CComPtr<ID2D1DeviceContext5> dc; | |
hr = target->QueryInterface(&dc); | |
// open a stream in the .SVG file | |
CComPtr<IStream> svgStream; | |
hr = SHCreateStreamOnFileW(L"d:\\downloads\\drawing.svg", 0, &svgStream); | |
// open the SVG as a document | |
CComPtr<ID2D1SvgDocument> svg; | |
D2D1_SIZE_F size = { (float)width, (float)height }; | |
hr = dc->CreateSvgDocument(svgStream, size, &svg); | |
// draw it on the render target | |
target->BeginDraw(); | |
dc->DrawSvgDocument(svg); | |
hr = target->EndDraw(); | |
// TODO: do something with the bitmap | |
WicSave(bitmap); | |
// cleanup, etc. | |
cdc.SelectObject(old); | |
} | |
void SaveSvgAsPng(UINT width, UINT height) | |
{ | |
// initialize Direct2D | |
D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; // remove this in release | |
CComPtr<ID2D1Factory> factory; | |
auto hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_ID2D1Factory, &options, (void**)&factory); | |
// create a Wic bitmap | |
CComPtr<IWICImagingFactory> wicFactory; | |
hr = wicFactory.CoCreateInstance(CLSID_WICImagingFactory); | |
CComPtr<IWICBitmap> bitmap; | |
hr = wicFactory->CreateBitmap(width, height, GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnLoad, &bitmap); | |
// use the Wic bitmap as a Direct2D render target | |
CComPtr<ID2D1RenderTarget> target; | |
D2D1_RENDER_TARGET_PROPERTIES props = {}; | |
hr = factory->CreateWicBitmapRenderTarget(bitmap, &props, &target); | |
// requires Windows 10 1703 | |
CComPtr<ID2D1DeviceContext5> dc; | |
hr = target->QueryInterface(&dc); | |
// open a stream in the .SVG file | |
CComPtr<IStream> svgStream; | |
hr = SHCreateStreamOnFileW(L"d:\\downloads\\drawing.svg", 0, &svgStream); | |
// open the SVG as a document | |
CComPtr<ID2D1SvgDocument> svg; | |
D2D1_SIZE_F size = { (float)width, (float)height }; | |
hr = dc->CreateSvgDocument(svgStream, size, &svg); | |
// draw it on the render target | |
target->BeginDraw(); | |
dc->DrawSvgDocument(svg); | |
hr = target->EndDraw(); | |
// create PNG file | |
CComPtr<IWICStream> wicStream; | |
hr = wicFactory->CreateStream(&wicStream); | |
hr = wicStream->InitializeFromFilename(L"drawing.png", GENERIC_WRITE); | |
// create PNG encoder | |
CComPtr<IWICBitmapEncoder> encoder; | |
hr = wicFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr, &encoder); | |
hr = encoder->Initialize(wicStream, WICBitmapEncoderNoCache); | |
// create frame | |
CComPtr<IWICBitmapFrameEncode> frame; | |
hr = encoder->CreateNewFrame(&frame, nullptr); | |
hr = frame->Initialize(nullptr); | |
// write bitmap | |
hr = frame->WriteSource(bitmap, nullptr); | |
// commit | |
hr = frame->Commit(); | |
hr = encoder->Commit(); | |
} | |
int main() | |
{ | |
CoInitialize(nullptr); | |
SaveSvgAsPng(200, 200); | |
BuildSvgAsCBitmap(200, 200); | |
CoUninitialize(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment