I'm not really sure how to get started with these APIs for Windows 10...
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/nf-windows-data-pdf-interop-pdfcreaterenderer?redirectedfrom=MSDN
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/nf-windows-data-pdf-interop-ipdfrenderernative-renderpagetodevicecontext
I want to convert a PDF into a bitmap image.
How to view PDF with Windows API? (PDF -> bitmap)
Re: How to view PDF with Windows API? (PDF -> bitmap)
Not sure, but it's easy with ImageMagick.
Code: Select all
source = ....pdf ; Adjust this line
SplitPath, source,, dir,, fnBare
target = %dir%\%fnBare%.bmp
FileRecycle, %target%
SplashTextOn, 300, 100, Converting, Please wait....
RunWait, convert.exe "%source%" "%target%",, Hide
SplashTextOff
If ErrorLevel {
MsgBox, 16, Error, An error occurred during the file conversion.
ExitApp
}
If !FileExist(target) {
done := False, n := -1
While !done {
n++, target := Format("{}\{}-{}.bmp", dir, fnbare, n), done := !FileExist(target)
If !done {
Run, %target%
Sleep, 100
}
}
} Else Run, %target%
ExitApp
Re: How to view PDF with Windows API? (PDF -> bitmap)
Next time, try reading the question. Because I am clearly trying to get a pointer to to an IDXGIDevice or ID2D1DeviceContext which I need to figure out how to convert back into a GDI device context using interop functions, or a GDI+ bitmap.
For example, the GDI+ function GdipCreateBitmapFromDirectDrawSurface combined with IPdfRendererNative::RenderPageToSurface seems promising.
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/nf-windows-data-pdf-interop-ipdfrenderernative-renderpagetosurface
The problem is that I am not familiar with the DirectDraw factories
For example, the GDI+ function GdipCreateBitmapFromDirectDrawSurface combined with IPdfRendererNative::RenderPageToSurface seems promising.
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/nf-windows-data-pdf-interop-ipdfrenderernative-renderpagetosurface
which implies that after GdipCreateBitmapFromDirectDrawSurface is called, GdipCloneImage should be called.Creates a Bitmap::Bitmap object based on a DirectDraw surface. The Bitmap::Bitmap object maintains a reference to the DirectDraw surface until the Bitmap::Bitmap object is deleted or goes out of scope.
The problem is that I am not familiar with the DirectDraw factories
Re: How to view PDF with Windows API? (PDF -> bitmap)
No problem at all. I understood that the question was that you wanted to convert a PDF into a bitmap image, but I was wrong.
Re: How to view PDF with Windows API? (PDF -> bitmap)
I think You cannot do it, because this header is used by Windows Runtime C++ reference
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/
But You can do it with UWP help.
https://docs.microsoft.com/en-us/uwp/api/windows.data.pdf.pdfpage.rendertostreamasync?view=winrt-19041
https://docs.microsoft.com/en-us/windows/win32/api/windows.data.pdf.interop/
But You can do it with UWP help.
https://docs.microsoft.com/en-us/uwp/api/windows.data.pdf.pdfpage.rendertostreamasync?view=winrt-19041
Re: How to view PDF with Windows API? (PDF -> bitmap)
I'm not sure how to go about calling RenderToStreamAsync. Do I need to create an instance of the IPdfRendererNative interface first?
https://stackoverflow.com/questions/32582080/undocumented-windows-built-in-pdf-renderer-capabilities/32840651
https://stackoverflow.com/questions/32582080/undocumented-windows-built-in-pdf-renderer-capabilities/32840651
Re: How to view PDF with Windows API? (PDF -> bitmap)
No. You have to
1) ShCore\CreateRandomAccessStreamOnFile
2) PdfDocument.LoadFromStreamAsync
3) PdfDocument.GetPage(UInt32)
4) PdfPage.RenderToStreamAsync
5) ShCore\CreateStreamOverRandomAccessStream
6) GdipCreateBitmapFromStream
Look at example of OCR UWP
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=72674
1) ShCore\CreateRandomAccessStreamOnFile
2) PdfDocument.LoadFromStreamAsync
3) PdfDocument.GetPage(UInt32)
4) PdfPage.RenderToStreamAsync
5) ShCore\CreateStreamOverRandomAccessStream
6) GdipCreateBitmapFromStream
Look at example of OCR UWP
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=72674
-
- Posts: 4309
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to view PDF with Windows API? (PDF -> bitmap)
Yes, I think You are right.
1) ShCore\CreateRandomAccessStreamOnFile
2) PdfDocument.LoadFromStreamAsync
3) PdfDocument.GetPage(UInt32)
4) Ole32\CreateStreamOnHGlobal
5) ShCore\CreateRandomAccessStreamOverStream
6) PdfPage.RenderToStreamAsync
7) GdipCreateBitmapFromStream
1) ShCore\CreateRandomAccessStreamOnFile
2) PdfDocument.LoadFromStreamAsync
3) PdfDocument.GetPage(UInt32)
4) Ole32\CreateStreamOnHGlobal
5) ShCore\CreateRandomAccessStreamOverStream
6) PdfPage.RenderToStreamAsync
7) GdipCreateBitmapFromStream
Re: How to view PDF with Windows API? (PDF -> bitmap)
Curious if anyone ever got this functioning based on the comments by malcev and teadrinker?
Re: How to view PDF with Windows API? (PDF -> bitmap)
Something like this:
Code: Select all
pdfPath := "D:\1064754760.pdf"
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_RandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", &GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", pdfPath, "uint", Read := 0, "ptr", &GUID, "ptr*", IRandomAccessStream)
CreateClass("Windows.Data.Pdf.PdfDocument", IPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}", PdfDocumentStatics)
DllCall(NumGet(NumGet(PdfDocumentStatics+0)+8*A_PtrSize), "ptr", PdfDocumentStatics, "ptr", IRandomAccessStream, "ptr*", PdfDocument) ; LoadFromStreamAsync
WaitForAsync(PdfDocument)
DllCall(NumGet(NumGet(PdfDocument+0)+6*A_PtrSize), "ptr", PdfDocument, "uint", 0, "ptr*", PdfPage) ; GetPage
DllCall("Ole32\CreateStreamOnHGlobal", "ptr", 0, "uint", true, "ptr*", IStream)
DllCall("ShCore\CreateRandomAccessStreamOverStream", "ptr", IStream, "uint", BSOS_DEFAULT := 0, "ptr", &GUID, "ptr*", IRandomAccessStreamOut)
DllCall(NumGet(NumGet(PdfPage+0)+6*A_PtrSize), "ptr", PdfPage, "ptr", IRandomAccessStreamOut, "ptr*", asyncInfo) ; RenderToStreamAsync
WaitForAsync(asyncInfo)
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
DllCall("gdiplus\GdipCreateBitmapFromStream", "ptr", IStream, "ptr*", pBitmap)
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
Gui, Add, Picture, , HBITMAP:%hBitmap%
Gui, Show
DllCall("Gdiplus.dll\GdipDisposeImage", "ptr", pBitmap)
Close := ComObjQuery(IRandomAccessStream, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close) ; Close
ObjRelease(Close)
ObjRelease(IRandomAccessStream)
ObjRelease(PdfDocumentStatics)
ObjRelease(PdfDocument)
ObjRelease(PdfPage)
ObjRelease(IStream)
Close := ComObjQuery(IRandomAccessStreamOut, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close) ; Close
ObjRelease(Close)
ObjRelease(IRandomAccessStreamOut)
CreateClass(string, interface, ByRef Class)
{
CreateHString(string, hString)
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
if (result != 0)
{
if (result = 0x80004002)
msgbox No such interface supported
else if (result = 0x80040154)
msgbox Class not registered
else
msgbox error: %result%
ExitApp
}
DeleteHString(hString)
}
CreateHString(string, ByRef hString)
{
DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}
DeleteHString(hString)
{
DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
WaitForAsync(ByRef Object)
{
AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
loop
{
DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status) ; IAsyncInfo.Status
if (status != 0)
{
if (status != 1)
{
DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode) ; IAsyncInfo.ErrorCode
msgbox AsyncInfo status error: %ErrorCode%
ExitApp
}
ObjRelease(AsyncInfo)
break
}
sleep 10
}
DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult) ; GetResults
ObjRelease(Object)
Object := ObjectResult
}
Re: How to view PDF with Windows API? (PDF -> bitmap)
Interesting. I was on the right track however I was having trouble knowing the proper offsets for each method. It seems like the methods start at 6*A_PtrSize? I’m also using AHKv2 and was try to use ComCall instead of DllCall with NumGets. I’ll take a stab at trying to convert what you’ve posted. Thanks!
Re: How to view PDF with Windows API? (PDF -> bitmap)
You can get info about offsets here
https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/winrt/windows.data.pdf.h#L879
https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/winrt/windows.data.pdf.h#L879
Re: How to view PDF with Windows API? (PDF -> bitmap)
Sweet thanks! I was looking here for things - https://github.com/wmliang/wdk-10/blob/master/Include/10.0.10586.0/winrt/windows.data.pdf.idl
It seems like I am getting back the pdfDocument but ComObjQuery isn't returning the IAsyncInfo it appears.
It seems like I am getting back the pdfDocument but ComObjQuery isn't returning the IAsyncInfo it appears.
Code: Select all
file := A_MyDocuments . "\basement-stuff\mmi-door-interior-price-pages.pdf"
GUID := BufferAlloc(16)
DllCall("ole32\CLSIDFromString", "wstr", IID_IRandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", file, "uint", Read := 0, "ptr", GUID, "ptr*", IRandomAccessStream := 0)
pdfDoc := CreateClass("Windows.Data.Pdf.PdfDocument", iPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}")
ComCall(8, pdfDoc, "Ptr", IRandomAccessStream, "Ptr*", pdfDocument := 0)
WaitForAsync(pdfDocument)
pdfPage := ComCall(6, pdfDocument, "UInt", 0, "UInt")
DllCall("Ole32\CreateStreamOnHGlobal", "Ptr", 0, "UInt", true, "PtrP", pIStream := 0, "UInt")
riid := CLSIDFromString(IID_IRandomAccessStream)
DllCall("ShCore\CreateRandomAccessStreamOverStream", "Ptr", pIStream, "UInt", BSOS_DEFAULT := 0, "Ptr", riid, "Ptr*", pIRandomAccessStream := 0, "UInt")
iAsyncPageRender := ComCall(0, pdfPage, "Ptr", pIRandomAccessStream)
WaitForAsync(iAsyncPageRender)
DllCall( "LoadLibrary", "Str", "gdiplus" )
si := BufferAlloc(16, 0), Numput("Int", 1, si)
DllCall( "gdiplus\GdiplusStartup", "UPtr*", pToken := 0, "Ptr", si, "UInt",0 )
DllCall( "gdiplus\GdipCreateBitmapFromStream", "Ptr", pIRandomAccessStream, "Ptr*", pBitmap := 0 )
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap := 0, "uint", 0xffffffff)
main := gui.new()
main.add("Pic", "HBITMAP:" hBitmap)
main.show()
CLSIDFromString(IID) {
CLSID := BufferAlloc(16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return CLSID
}
CreateClass(string, interface) {
hString := CreateHString(string)
GUID := BufferAlloc(16)
DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", GUID)
result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", GUID, "ptr*", pClass := 0)
if (result != 0) {
if (result = 0x80004002)
msgbox("No such interface supported")
else if (result = 0x80040154)
msgbox("Class not registered")
else
msgbox("error: " . result)
ExitApp()
}
DeleteHString(hString)
return pClass
}
CreateHString(string) {
DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString := 0)
return hString
}
DeleteHString(hString) {
DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
WaitForAsync(ByRef Object) {
AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
MsgBox(AsyncInfo)
loop {
ComCall(7, AsyncInfo, "UInt*", status := 0)
; DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status) ; IAsyncInfo.Status
if (status != 0) {
if (status != 1) {
ComCall(8, AsyncInfo, "UInt*", ErrorCode := 0)
; DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode) ; IAsyncInfo.ErrorCode
msgbox("AsyncInfo status error: " . ErrorCode)
ExitApp()
}
ObjRelease(AsyncInfo)
break
}
sleep(10)
}
ComCall(8, Object, "Ptr*", ObjectResult := 0)
; DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult) ; GetResults
ObjRelease(Object)
Object := ObjectResult
}
Re: How to view PDF with Windows API? (PDF -> bitmap)
Finally got it... This stuff is not my specialty
Code: Select all
file := A_MyDocuments . "\basement-stuff\mmi-door-interior-price-pages.pdf"
GUID := BufferAlloc(16)
DllCall("ole32\CLSIDFromString", "wstr", IID_IRandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", file, "uint", Read := 0, "ptr", GUID, "ptr*", IRandomAccessStream := 0)
pdfDoc := CreateClass("Windows.Data.Pdf.PdfDocument", iPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}")
ComCall(8, pdfDoc, "Ptr", IRandomAccessStream, "Ptr*", pdfDocument := 0)
pdfDocument := WaitForAsync(pdfDocument)
ComCall(6, pdfDocument, "UInt", 0, "Ptr*", pdfPage := 0)
DllCall("Ole32\CreateStreamOnHGlobal", "Ptr", 0, "UInt", 1, "Ptr*", pIStream := 0)
; MsgBox(pIStream)
DllCall("ShCore\CreateRandomAccessStreamOverStream", "Ptr", pIStream, "UInt", BSOS_DEFAULT := 0, "Ptr", GUID, "Ptr*", pIRandomAccessStream := 0)
ComCall(6, pdfPage, "Ptr", pIRandomAccessStream, "Ptr*", iAsyncPageRender := 0)
WaitForAsync(iAsyncPageRender)
; MsgBox(pIRandomAccessStream)
DllCall( "LoadLibrary", "Str", "gdiplus" )
si := BufferAlloc(A_PtrSize == 8 ? 24 : 16, 0), Numput("Int", 1, si)
DllCall( "gdiplus\GdiplusStartup", "Ptr*", pToken := 0, "Ptr", si, "Ptr", 0 )
; MsgBox(pToken)
DllCall( "gdiplus\GdipCreateBitmapFromStream", "Ptr", pIStream, "Ptr*", pBitmap := 0 )
; MsgBox(pBitmap)
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap := 0, "uint", 0xffffffff)
; MsgBox(hBitmap)
main := gui.new()
main.add("Pic", "h600 w-1", "HBITMAP:" hBitmap)
main.show()
CLSIDFromString(IID) {
CLSID := BufferAlloc(16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return CLSID
}
CreateClass(string, interface) {
hString := CreateHString(string)
GUID := BufferAlloc(16)
DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", GUID)
result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", GUID, "ptr*", pClass := 0)
if (result != 0) {
if (result = 0x80004002)
msgbox("No such interface supported")
else if (result = 0x80040154)
msgbox("Class not registered")
else
msgbox("error: " . result)
ExitApp()
}
DeleteHString(hString)
return pClass
}
CreateHString(string) {
DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString := 0)
return hString
}
DeleteHString(hString) {
DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
WaitForAsync(Object) {
AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
; MsgBox(AsyncInfo)
loop {
ComCall(7, AsyncInfo, "UInt*", status := 0)
; DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status) ; IAsyncInfo.Status
if (status != 0) {
if (status != 1) {
ComCall(8, AsyncInfo, "UInt*", ErrorCode := 0)
; DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode) ; IAsyncInfo.ErrorCode
msgbox("AsyncInfo status error: " . ErrorCode)
ExitApp()
}
; ObjRelease(AsyncInfo.ptr)
break
}
sleep(10)
}
ComCall(8, Object, "Ptr*", ObjectResult := 0)
; DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult) ; GetResults
Object := AsyncInfo := ""
return ObjectResult
}
Re: How to view PDF with Windows API? (PDF -> bitmap)
Doesn't seem like the memory is being released. Is there a Close/Dispose call we're missing? I see that pdfPage has a Close/Dispose but querying for IClosable and calling Close doesn't seem to help.
Re: How to view PDF with Windows API? (PDF -> bitmap)
I didnot find any variant, only like this
Code: Select all
DllCall("psapi.dll\EmptyWorkingSet", "ptr", -1)
Re: How to view PDF with Windows API? (PDF -> bitmap)
Interesting. That seems a bit extreme.
Re: How to view PDF with Windows API? (PDF -> bitmap)
@malcev What is the purpose of IClosable?
Who is online
Users browsing this forum: yabab33299 and 145 guests