svgToHBITMAP.ah2
Code: Select all
#SingleInstance force
ListLines 0
KeyHistory 0
SendMode "Input" ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir A_ScriptDir ; Ensures a consistent starting directory.
svgToHBITMAP(svgPath,width,height) {
;https://gist.github.com/smourier/5b770d32043121d477a8079ef6be0995
;https://stackoverflow.com/questions/75917247/convert-svg-files-to-bitmap-using-direct2d-in-mfc#75935717
; ID2D1DeviceContext5::CreateSvgDocument is the carrying api
hModule:=DllCall("GetModuleHandleA","AStr","WindowsCodecs.dll","Ptr")||DllCall("LoadLibraryA","AStr","WindowsCodecs.dll","Ptr")
CLSID_WICImagingFactory:=Buffer(0x10)
NumPut("UInt64",0x433D5F24317D06E8,CLSID_WICImagingFactory,0x0)
NumPut("UInt64",0xC2ABD868CE79F7BD,CLSID_WICImagingFactory,0x8)
IID_IClassFactory:=Buffer(0x10)
NumPut("UInt64",0x0000000000000001,IID_IClassFactory,0x0)
NumPut("UInt64",0x46000000000000C0,IID_IClassFactory,0x8)
DllGetClassObject:=DllCall("GetProcAddress","Ptr",hModule,"AStr","DllGetClassObject","Ptr")
DllCall(DllGetClassObject,"Ptr",CLSID_WICImagingFactory,"Ptr",IID_IClassFactory,"Ptr*",&IClassFactory:=0)
IID_IWICImagingFactory:=Buffer(0x10)
NumPut("UInt64",0x4314C395EC5EC8A9,IID_IWICImagingFactory,0x0)
NumPut("UInt64",0x70FF35A9D754779C,IID_IWICImagingFactory,0x8)
ComCall(3,IClassFactory,"Ptr",0,"Ptr",IID_IWICImagingFactory,"Ptr*",&IWICImagingFactory:=0) ;HRESULT IClassFactory::CreateInstance(IUnknown *pUnkOuter,REFIID riid,void **ppvObject)
GUID_WICPixelFormat32bppPBGRA:=Buffer(0x10)
NumPut("UInt64",0x4BFE4E036FDDC324,GUID_WICPixelFormat32bppPBGRA,0x0)
NumPut("UInt64",0x10C98D76773D85B1,GUID_WICPixelFormat32bppPBGRA,0x8)
ComCall(17,IWICImagingFactory,"Uint",width,"Uint",height,"Ptr",GUID_WICPixelFormat32bppPBGRA,"Int",0x2,"Ptr*",&IWICBitmap:=0) ;HRESULT IWICImagingFactory::CreateBitmap(UINT uiWidth,UINT uiHeight,REFWICPixelFormatGUID pixelFormat,WICBitmapCreateCacheOption option,IWICBitmap **ppIBitmap); 0x2=WICBitmapCacheOnLoad
IID_ID2D1Factory:=Buffer(0x10)
NumPut("UInt64",0x465A6F5006152247,IID_ID2D1Factory,0x0)
NumPut("UInt64",0x07603BFD8B114592,IID_ID2D1Factory,0x8)
DllCall("GetModuleHandleA", "AStr", "d2d1") || DllCall("LoadLibraryA", "AStr", "d2d1") ;this is needed to avoid "Critical Error: Invalid memory read/write"
DllCall("d2d1\D2D1CreateFactory","Int",0,"Ptr",IID_ID2D1Factory,"Ptr",0,"Ptr*",&ID2D1Factory:=0) ;Int 0=D2D1_FACTORY_TYPE_SINGLE_THREADED
D2D1_RENDER_TARGET_PROPERTIES:=Buffer(0x1c,0)
ComCall(13,ID2D1Factory,"Ptr",IWICBitmap,"Ptr",D2D1_RENDER_TARGET_PROPERTIES,"Ptr*",&ID2D1RenderTarget:=0) ;HRESULT ID2D1Factory::CreateWicBitmapRenderTarget(IWICBitmap *target,D2D1_RENDER_TARGET_PROPERTIES &renderTargetProperties,ID2D1RenderTarget **renderTarget)
; IID_ID2D1DeviceContext5:=Buffer(0x10)
; NumPut("UInt64",0x4DF668CC7836D248,IID_ID2D1DeviceContext5,0x0)
; NumPut("UInt64",0xB72EF61B99DEE8B9,IID_ID2D1DeviceContext5,0x8)
; ComCall(0,ID2D1RenderTarget,"Ptr",IID_ID2D1DeviceContext5,"Ptr*",&ID2D1DeviceContext5:=0) ;HRESULT ID2D1RenderTarget::QueryInterface(REFIID riid,void **ppvObject)
DllCall("shlwapi\SHCreateStreamOnFileW","WStr",svgPath,"Uint",0,"Ptr*",&IStream:=0)
D2D1_SIZE_F:=Buffer(8)
NumPut("float",width,D2D1_SIZE_F,0x0)
NumPut("float",height,D2D1_SIZE_F,0x4)
ComCall(115,ID2D1RenderTarget,"Ptr",IStream,"Uint64",NumGet(D2D1_SIZE_F,"Uint64"),"Ptr*",&ID2D1SvgDocument:=0) ;HRESULT ID2D1DeviceContext5::CreateSvgDocument(IStream *inputXmlStream,D2D1_SIZE_F viewportSize,ID2D1SvgDocument **svgDocument)
ComCall(48,ID2D1RenderTarget,"int") ;void ID2D1RenderTarget::BeginDraw()
ComCall(116,ID2D1RenderTarget,"Ptr",ID2D1SvgDocument,"int") ;void ID2D1DeviceContext5::DrawSvgDocument(ID2D1SvgDocument *svgDocument)
ComCall(49,ID2D1RenderTarget,"Ptr",0,"Ptr",0) ;HRESULT ID2D1RenderTarget::EndDraw(D2D1_TAG *tag1,D2D1_TAG *tag2)
cbStride:=4*width ;stride=bpp*width
pData:=Buffer(cbStride * height) ;bpp*width*height
ComCall(7,IWICBitmap,"Ptr",0,"Uint",cbStride,"Uint",pData.Size,"Ptr",pData) ;HRESULT IWICBitmapSource::CopyPixels(WICRect *prc,UINT cbStride,UINT cbBufferSize,BYTE *pbBuffer)
HBITMAP := DllCall("gdi32\CreateBitmap","Int",width,"Int",height,"Uint",1,"Uint",32,"Ptr",pData,"Ptr")
return HBITMAP
}
myGui:=Gui()
myGui.AddPicture(,"HBITMAP:" svgToHBITMAP("C:\windows.refresh.svg",800,800))
myGui.Show()
return
f3::Exitapp
SaveWicSvgToPng.c
Code: Select all
#include <windows.h>
#include "shlwapi.h"
#include "d2d1.h"
#include "d2d1_3.h" // ID2D1DeviceContext5
#include "wincodec.h" // Wic
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "ole32")
#pragma comment(lib, "d2d1")
typedef struct ID2D1FactoryVtbl
{
void * lol[13];
STDMETHOD(CreateWicBitmapRenderTarget)(
__RPC__in ID2D1Factory * This,
_In_ IWICBitmap *target,
_In_ CONST D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties,
_COM_Outptr_ ID2D1RenderTarget **renderTarget
) PURE;
} ID2D1FactoryVtbl;
interface ID2D1Factory
{
CONST_VTBL struct ID2D1FactoryVtbl *lpVtbl;
};
typedef interface ID2D1DeviceContext5 ID2D1DeviceContext5;
typedef struct ID2D1DeviceContext5Vtbl
{
void * lol0[48];
STDMETHOD_(void, BeginDraw)(
__RPC__in ID2D1DeviceContext5 * This
) PURE;
STDMETHOD(EndDraw)(
__RPC__in ID2D1DeviceContext5 * This,
_Out_opt_ D2D1_TAG *tag1 = NULL,
_Out_opt_ D2D1_TAG *tag2 = NULL
) PURE;
void * lol1[65];
STDMETHOD(CreateSvgDocument)(
__RPC__in ID2D1DeviceContext5 * This,
_In_opt_ IStream *inputXmlStream,
D2D1_SIZE_F viewportSize,
_COM_Outptr_ ID2D1SvgDocument **svgDocument
) PURE;
STDMETHOD_(void, DrawSvgDocument)(
__RPC__in ID2D1DeviceContext5 * This,
_In_ ID2D1SvgDocument *svgDocument
) PURE;
} ID2D1DeviceContext5Vtbl;
interface ID2D1DeviceContext5
{
CONST_VTBL struct ID2D1DeviceContext5Vtbl *lpVtbl;
};
void SaveSvgAsPng(LPCWSTR input_SVG, LPCWSTR output_PNG, UINT width, UINT height)
{
//https://gist.github.com/smourier/5b770d32043121d477a8079ef6be0995
//https://stackoverflow.com/questions/75917247/convert-svg-files-to-bitmap-using-direct2d-in-mfc#75935717
// ID2D1DeviceContext5::CreateSvgDocument is the carrying api
HMODULE hModule = LoadLibraryA("WindowsCodecs.dll");
typeof(DllGetClassObject) *proc_DllGetClassObject = (typeof(DllGetClassObject)*)GetProcAddress(hModule,"DllGetClassObject");
IClassFactory *pIClassFactory;
proc_DllGetClassObject(&CLSID_WICImagingFactory,&IID_IClassFactory,(void**)&pIClassFactory);
GUID IID_IWICImagingFactory = {0xec5ec8a9,0xc395, 0x4314, 0x9c, 0x77, 0x54, 0xd7, 0xa9, 0x35, 0xff, 0x70};
IWICImagingFactory *pIWICImagingFactory;
pIClassFactory->lpVtbl->CreateInstance(pIClassFactory,0,&IID_IWICImagingFactory,(void**)&pIWICImagingFactory);
IWICBitmap *pIWICBitmap;
pIWICImagingFactory->lpVtbl->CreateBitmap(pIWICImagingFactory,width,height,&GUID_WICPixelFormat32bppPBGRA,WICBitmapCacheOnLoad,&pIWICBitmap);
// initialize Direct2D
ID2D1Factory *pID2D1Factory;
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, 0, (void**)&pID2D1Factory);
D2D1_RENDER_TARGET_PROPERTIES pD2D1_RENDER_TARGET_PROPERTIES = {0,0,0,0,0,0};
//skipping ID2D1RenderTarget::QueryInterface to ID2D1DeviceContext5
ID2D1DeviceContext5 *pID2D1DeviceContext5;
pID2D1Factory->lpVtbl->CreateWicBitmapRenderTarget(pID2D1Factory,pIWICBitmap,&pD2D1_RENDER_TARGET_PROPERTIES,(ID2D1RenderTarget**)&pID2D1DeviceContext5);
IStream *pIStream;
SHCreateStreamOnFileW(input_SVG,0,&pIStream);
D2D1_SIZE_F pD2D1_SIZE_F = { (float)width, (float)height };
ID2D1SvgDocument *pID2D1SvgDocument;
pID2D1DeviceContext5->lpVtbl->CreateSvgDocument(pID2D1DeviceContext5,pIStream,pD2D1_SIZE_F,&pID2D1SvgDocument); //ID2D1DeviceContext5::CreateSvgDocument
pID2D1DeviceContext5->lpVtbl->BeginDraw(pID2D1DeviceContext5); //ID2D1RenderTarget::BeginDraw
pID2D1DeviceContext5->lpVtbl->DrawSvgDocument(pID2D1DeviceContext5,pID2D1SvgDocument); //ID2D1DeviceContext5::DrawSvgDocument
pID2D1DeviceContext5->lpVtbl->EndDraw(pID2D1DeviceContext5,0,0); //ID2D1RenderTarget::EndDraw
// create PNG file
IWICStream *pIWICStream;
pIWICImagingFactory->lpVtbl->CreateStream(pIWICImagingFactory,&pIWICStream);
pIWICStream->lpVtbl->InitializeFromFilename(pIWICStream,output_PNG,GENERIC_WRITE);
// create PNG encoder
IWICBitmapEncoder *pIWICBitmapEncoder;
pIWICImagingFactory->lpVtbl->CreateEncoder(pIWICImagingFactory,&GUID_ContainerFormatPng,0,&pIWICBitmapEncoder);
pIWICBitmapEncoder->lpVtbl->Initialize(pIWICBitmapEncoder,(IStream*)pIWICStream,WICBitmapEncoderNoCache);
// create frame
IWICBitmapFrameEncode *pIWICBitmapFrameEncode;
pIWICBitmapEncoder->lpVtbl->CreateNewFrame(pIWICBitmapEncoder,&pIWICBitmapFrameEncode,0);
pIWICBitmapFrameEncode->lpVtbl->Initialize(pIWICBitmapFrameEncode,0);
// write bitmap
pIWICBitmapFrameEncode->lpVtbl->WriteSource(pIWICBitmapFrameEncode,(IWICBitmapSource*)pIWICBitmap,0);
// commit
pIWICBitmapFrameEncode->lpVtbl->Commit(pIWICBitmapFrameEncode);
pIWICBitmapEncoder->lpVtbl->Commit(pIWICBitmapEncoder);
}
int main()
{
CoInitialize(0);
SaveSvgAsPng(L"C:\\windows.refresh.svg",L"drawing.png",800, 800);
CoUninitialize();
return 0;
}