mjolnirmarkiv

Using .NET libary with AutoIt, possible?

388 posts in this topic

#1 ·  Posted

Hi!

Is there any way to use .NET DLL libraries with AutoIt? I happen to have one that'd have made my life easier, but DLLCall() returns an error: no functions with such name found. Searching and reading forums made me think that's not a fault of a library. I've used yashied's DLL Helper, but it didn't return any function names as well.

Thanks!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I don't believe c# libraries have classic entry points like unmanaged dlls, so dllcall will not work.

I think I recall you have to make your dll com visible and use as an object, you should search it, there is something on the forum about it.

EDIT: .NET CLR is nowadays possible.

 

Edited by JohnOne
1 person likes this

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

At the moment there is no way to access .NET libraries natively... 

2 Options left :

1. If this is a custom developed .NET libr. make it COM Visible as JohnOne indicated.

2. If you are looking for accessing .NET Class Libraries, you can use the PowerShell COM library as middleware...

    See my signature.

I am looking into how we could still achieve this to access it natively. But some highly skilled forum members has already let me know that this will not be an easy task....

It could be achieved by using the ObjCreateInterface and reading a lot on MSDN ...

It is NOW POSSIBLE TO ACCESS .NET Classes / THIRD PARTY ASSEMBLIES / POWERSHELL Cmdlets and MODULES

See here on 'how to' Examples

 

All members are welcome to contribute and help in any way they can ...

Rgds

ptrex

 

Edited by ptrex
1 person likes this

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

23-april-2017 initial au3 library posted in examples section over here

https://www.autoitscript.com/forum/topic/188158-net-common-language-runtime-clr-framework/

Introduction

In this whole tread posts 1-180 a lot of learning material which I try to summarize in this post 4. Around post 180 we had a working version ready for examples section to ask more help from others to enhance the UDF

a. Make use / enhance for more examples (the enduser of the udf --> see examples section in forum)

b. Host the CLR runtime in a better more documented way  (the technical side of the udf in this thread)

Reflection and related concepts
Important area in integrating interfaces, types, dynamic and related concepts all relate to reflection 

For starters

Summary post 1-180

Technical background

Some other relevant articles related to AutoIt and this CLR stuff

  • MSCorEE.DLL  and MSCORLIB.DLL by googling the internet

Books to read

Lengthy list of references used in the thread (clean / sort later in a logical order)

 

Edited by junkew
Overview of this thread till post 180
1 person likes this

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

For starters in COM

  1. https://www.codeproject.com/Articles/13601/COM-in-plain-C
  2. https://www.codeproject.com/Articles/13862/COM-in-plain-C-Part
  3. https://www.codeproject.com/Articles/14037/COM-in-plain-C-Part
  4. https://www.codeproject.com/Articles/14117/COM-in-plain-C-Part
  5. https://www.codeproject.com/Articles/14183/COM-in-plain-C-Part
  6. https://www.codeproject.com/Articles/14905/COM-in-plain-C-Part
  7. https://www.codeproject.com/Articles/15037/COM-in-plain-C-Part
  8. https://www.codeproject.com/Articles/17038/COM-in-plain-C-part
  •  

Studying this udf gives more understanding for defining and getting the interfaces and reflection / metadata from AutoIt

  1. https://www.autoitscript.com/forum/topic/114498-typelibinspector-oleview-was-yesterday/?page=2#comment-1048903
  2. https://www.autoitscript.com/forum/topic/112992-tliau3-type-information-on-com-objects-tlbinf-emulation/#comment-791089

AutoIt Object udf (AIO)

Excellent resource for studying on how to do more complex thing that AutoIt did not offer out of the box for creating objects. When learning a lot in this thread this AIO udf was also excellent area to see how Variant/COM  stuff is implemented in AutoIt by using oleaut32.dll 

https://www.autoitscript.com/forum/topic/110379-autoitobject-udf/#comment-775262
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221673(v=vs.85).aspx

For me its a little unclear how AIO relates nowadays to objCreateInterface
 

; Declare the CLSID, IID and interface description for ITaskbarList.
    ; It is not necessary to describe the members of IUnknown.
    Local Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
    Local Const $sIID_ITaskbarList = "{56FDF342-FD6D-11D0-958A-006097C9A090}"
    Local Const $sTagITaskbarList = "HrInit hresult(); AddTab hresult(hwnd); DeleteTab hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);"

    ; Create the object.
    Local $oTaskbarList = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList)

    ; Initialize the iTaskbarList object.
    $oTaskbarList.HrInit()

 

SafeArray udf

https://www.autoitscript.com/forum/topic/185883-accessing-autoit-variables/#comment-1335030

 

Edited by junkew
1 person likes this

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

headerFiles.7z:
  metahost.h
  mscoree-2.h (.NET v2)
  mscoree-4.h (.NET v4)
  mscorlib.tlh (_AppDomain interface)

 

Edited by LarsJ
Zip file removed

Share this post


Link to post
Share on other sites

#10 ·  Posted

Share this post


Link to post
Share on other sites

#12 ·  Posted

Not sure what the definition will be of using .NET in AutoIt

Maybe some examples on what people want to see working from AutoIt and how?

There are solutions like

Small dll's so you can use it without registering .NET classed as com

Register the .NET classes with regasm

but probably the requirement is to host the CLR

attention points

  • I remember something on passing byref and byvalue leads to issues in AutoIt and reading on .NET / COM interop thats frequently needed.

  • MSCorEE.DLL  (and related tlb) is unmanaged and should be possible to deal with from AutoIt (complexity similar to AIO)

  • MSCorLibl.DLL is managed code and contains all the classed people probably want to call directly/instantiate from ObjCreateInterface which I doubt is possible.

Probably smart to ask some of the AIO programmers their perspective on this if its possible at all.

My bet would be on building stuff in a .NET language and expose it with a REST JSON API interface.
asier and probably better nowadays to make API's in JSON or SOAP XML.

Share this post


Link to post
Share on other sites

#13 ·  Posted

Hi Junkew,

2 main reasons why to get this going :

1. Access to the .NET Class Libraries opens up a new world !

  • System
  • System.Collections
  • System.Data
  • System.Drawing
  • System.IO
  • System.Text
  • System.Threading
  • System.Timers
  • System.Web
  • System.Web.Services
  • System.Windows.Forms
  • System.Xml

2. Accessing custom build .Net libraries will be and extension to the current au3 functionality,

Some Examples (but there are a ton out there)

  • - JSonToXML libr.
  •  - XMLRPC Libr.
  • - .NETPDF libr.
  • - .NETOCR Libr
  • - WInSCP Libr.
  • - ...

Something like this are practical examples :

http://www.learnqtp.com/dotnetfactory-qtp-part1-basics/

 

 

Share this post


Link to post
Share on other sites

#14 ·  Posted

So far this is the status:When using the ObjCreateInterface :

$CLSID_CLRMetaHost = "{9280188D-0E8E-4867-B30C-7FA83884E8DE}"
$IID_ICLRDebugging = "{D28F3C5A-9634-4206-A509-477552EEFB10}"
$IID_ICLRDebuggingLibraryProvider = "{3151C08D-4D09-4F9B-8838-2880BF18FE51}"
$IID_ICLRMetaHost = "{D332DB9E-B9B3-4125-8207-A14884F53216}"
$IID_ICLRMetaHostPolicy = "{E2190695-77B2-492E-8E14-C4B3A7FDD593}"
$IID_ICLRProfiling = "{B349ABE3-B56F-4689-BFCD-76BF39D888EA}"
$IID_ICLRRuntimeInfo = "{BD39D1D2-BA2F-486A-89B0-B4B0CB466891}"
$IID_ICLRStrongName = "{9FD93CCF-3280-4391-B3A9-96E1CDE77C8D}"
$IID_IEnumUnknown = "{00000100-0000-0000-C000-000000000046}"
$IID_ISequentialStream = "{0C733A30-2A1C-11CE-ADE5-00AA0044773D}"
$IID_IStream = "{0000000C-0000-0000-C000-000000000046}"

$dtag = ""

$hRet = ObjCreateInterface($CLSID_CLRMetaHost, $IID_ICLRMetaHost , $dtag)

ConsoleWrite(IsObj($hRet) & @CRLF) 

No result it does not create an Object, because the mscoree.dll is not a COM object that is registered.

Using the Create Object direct access method  :

#AutoIt3Wrapper_UseX64=y

Global $CLSID_CLRMetaHost = "{9280188D-0E8E-4867-B30C-7FA83884E8DE}"
Global $IID_ICLRDebugging = "{D28F3C5A-9634-4206-A509-477552EEFB10}"
Global $IID_ICLRDebuggingLibraryProvider = "{3151C08D-4D09-4F9B-8838-2880BF18FE51}"
Global $IID_ICLRMetaHost = "{D332DB9E-B9B3-4125-8207-A14884F53216}"
Global $IID_ICLRMetaHostPolicy = "{E2190695-77B2-492E-8E14-C4B3A7FDD593}"
Global $IID_ICLRProfiling = "{B349ABE3-B56F-4689-BFCD-76BF39D888EA}"
Global $IID_ICLRRuntimeInfo = "{BD39D1D2-BA2F-486A-89B0-B4B0CB466891}"
Global $IID_ICLRStrongName = "{9FD93CCF-3280-4391-B3A9-96E1CDE77C8D}"
Global $IID_IEnumUnknown = "{00000100-0000-0000-C000-000000000046}"
Global $IID_ISequentialStream = "{0C733A30-2A1C-11CE-ADE5-00AA0044773D}"
Global $IID_IStream = "{0000000C-0000-0000-C000-000000000046}"

Global $hActiveX

; Load the server module
If @AutoItX64 Then
    $hActiveX  = DllOpen("C:\Windows\system32\mscoree.dll")
Else
    $hActiveX  = DllOpen("C:\Windows\system32\mscoree.dll")
EndIf
;MsgBox(0,"x64",@AutoItX64)

; Object identifiers
Global Const $sCLSID = "{9280188D-0E8E-4867-B30C-7FA83884E8DE}"
Global Const $sIID = "{D332DB9E-B9B3-4125-8207-A14884F53216}"
;Global Const $sIID = Default ; Or use keyword Default if you want to use the Default interface ID

; Error monitoring
Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error ! Number: 0x" & Hex($oError.number, 8) & " ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc    ;==>_ErrFunc

; Create the hActiveX
Local $oNET = ObjCreate($sCLSID, $sIID, $hActiveX)

If $oNET = 0 Then MsgBox(16,"Error", "Could not create the object, Common problem ActiveX not registered.")

$oNET = ""
DllClose($hActiveX)

 No result either because the mscoree.dll is not an COM visible library...

In the C:\Windows\Microsoft.NET Framework folders you can find the mscoree.tlb type libr. file as well as the mscorlib.tlb one

If you open it using the trancexx TypeLib Viewer 

You can see all the CLSID / IID's

See file encloed : mscoree; // Common Language Runtime Execution Engine 2.4 Library

Some more developers expertise is needed here to point on...

rgds

ptrex

Common Language Runtime Execution Engine 2.4 Library.txt

Share this post


Link to post
Share on other sites

#15 ·  Posted

Using a wrapper around a wrapper of a wrapper:( .... I was able to get the CLRHost running ;)

Quote

FriendlyName           : DefaultDomain
Id                     : 1
ApplicationDescription : 
BaseDirectory          : C:\Program Files (x86)\AutoIt3\beta\
DynamicDirectory       : 
RelativeSearchPath     : 
SetupInformation       : System.AppDomainSetup
ShadowCopyFiles        : False

But this is not the way to go !

I hope that some of the devolopers reach out to give us a hand...

rgds

ptrex

1 person likes this

Share this post


Link to post
Share on other sites

#16 ·  Posted

ptrex, A little comment to post 14. You must use CLRCreateInstance to get a pointer to ICLRMetaHost. And then use this pointer in ObjCreateInterface. But still a long way to go.

Share this post


Link to post
Share on other sites

#19 ·  Posted

 

#AutoIt3Wrapper_UseX64 = y

#include <WinAPI.au3>

; Get handle of the loaded module
Local $hModule =  _WinAPI_LoadLibraryEx("C:\Windows\System32\mscoree.dll")

ConsoleWrite($hModule & @CRLF)

If $hModule Then
    Local $pFunction = _WinAPI_GetProcAddress($hModule, "CLRCreateInstance")
    ConsoleWrite("The address of the function is " & $pFunction & @CRLF & @CRLF)

    ; Do whatever here

EndIf

_WinAPI_FreeLibrary($hModule))

These are the functions in mscoree.dll

 

Quote

  Section contains the following exports for mscoree.dll

    00000000 characteristics
    57899178 time date stamp Sat Jul 16 03:44:24 2016
        0.00 version
          17 ordinal base
         126 number of functions
         123 number of names

    ordinal hint RVA      name

         38    0 000040C0 CLRCreateInstance
         39    1 0001B320 CallFunctionShim
         21    2 0001A600 CloseCtrs
         40    3 0001B490 ClrCreateManagedInstance
         41    4 0001B5A0 CoEEShutDownCOM
         42    5 0001B670 CoInitializeCor
         43    6 0001B760 CoInitializeEE
         44    7 0001B850 CoUninitializeCor
         45    8 0001B920 CoUninitializeEE
         25    9 0001A700 CollectCtrs
         46    A 0001BA00 CorBindToCurrentRuntime
         47    B 0001BB30 CorBindToRuntime
         48    C 0001BCA0 CorBindToRuntimeByCfg
         49    D 0001BE10 CorBindToRuntimeByPath
         50    E 0001BF10 CorBindToRuntimeByPathEx
         51    F 00003E50 CorBindToRuntimeEx
         52   10 0001C020 CorBindToRuntimeHost
         26   11 0001A820 CorDllMainWorker
         53   12 000042E0 CorExitProcess
         54   13 0001C1F0 CorGetSvc
         55   14 0001C2E0 CorIsLatestSvc
         56   15 0001C3E0 CorMarkThreadInThreadPool
         57   16 0001C4A0 CorTickleSvc
         58   17 00003640 CreateConfigStream
         59   18 0001C580 CreateDebuggingInterfaceFromVersion
         60   19 00021C50 CreateInterface
         61   1A 00004200 DllCanUnloadNow
         62   1B 00003FA0 DllGetClassObject
         63   1C 0001C690 DllRegisterServer
         64   1D 0001C770 DllUnregisterServer
         27   1E 0001AA10 EEDllGetClassObjectFromClass
         65   1F 0001C850 EEDllRegisterServer
         66   20 0001C940 EEDllUnregisterServer
         67   21 0001CA30 GetAssemblyMDImport
         68   22 00021CF0 GetCLRMetaHost
         69   23 0001CB40 GetCORRequiredVersion
         70   24 0001CC50 GetCORRootDirectory
         71   25 0001CD60 GetCORSystemDirectory
         72   26 0001CE70 GetCORVersion
         73   27 0001CF80 GetCompileInfo
         74   28 0001D060 GetFileVersion
         75   29 0001D190 GetHashFromAssemblyFile
         76   2A 0001D2E0 GetHashFromAssemblyFileW
         77   2B 0001D430 GetHashFromBlob
         78   2C 0001D5A0 GetHashFromFile
         79   2D 0001D6F0 GetHashFromFileW
         80   2E 0001D840 GetHashFromHandle
         81   2F 0001D990 GetHostConfigurationFile
         82   30 0001DA90 GetMetaDataInternalInterface
         83   31 0001DBE0 GetMetaDataInternalInterfaceFromPublic
         84   32 0001DCF0 GetMetaDataPublicInterfaceFromInternal
         85   33 0001DE00 GetPermissionRequests
         28   34 0001AB30 GetPrivateContextsPerfCounters
         29   35 000037F0 GetProcessExecutableHeap
         86   36 0001DFA0 GetRealProcAddress
         87   37 0001E0A0 GetRequestedRuntimeInfo
         88   38 0001E2E0 GetRequestedRuntimeVersion
         89   39 0001E410 GetRequestedRuntimeVersionForCLSID
         30   3A 0001AC10 GetStartupFlags
         31   3B 00003CD0 GetTargetForVTableEntry
         32   3C 00003BA0 GetTokenForVTableEntry
         90   3D 0001E560 GetVersionFromProcess
         91   3E 0001E690 GetXMLElement
         92   3F 0001E780 GetXMLElementAttribute
         93   40 0001E8A0 GetXMLObject
         94   41 0001E990 IEE
         17   42 0001ACF0 InitErrors
         19   43 0001ADD0 InitSSAutoEnterThread
         95   44 0001EA70 LoadLibraryShim
         96   45 0001EBA0 LoadLibraryWithPolicyShim
         22   46 0001ECD0 LoadStringRC
         97   47 0001EDF0 LoadStringRCEx
         98   48 0002A000 LockClrVersion
         33   49 0001AEB0 LogHelp_LogAssert
         34   4A 0001AFB0 LogHelp_NoGuiOnAssert
         35   4B 0001B090 LogHelp_TerminateOnAssert
         99   4C 0001F060 MetaDataGetDispenser
        100   4D 0001F170 ND_CopyObjDst
        101   4E 0001F290 ND_CopyObjSrc
        102   4F 0001F3B0 ND_RI2
        103   50 0001F4A0 ND_RI4
        104   51 0001F590 ND_RI8
        105   52 0001F680 ND_RU1
        106   53 0001F770 ND_WI2
        107   54 0001F870 ND_WI4
        108   55 0001F970 ND_WI8
        109   56 0001FA70 ND_WU1
         36   57 0001B160 OpenCtrs
         18   58 0001A5D0 PostError
         23   59 0001FC60 ReOpenMetaDataWithMemory
        110   5A 0001FD70 ReOpenMetaDataWithMemoryEx
        111   5B 0001FEA0 RunDll32ShimW
        112   5C 0001FFD0 RuntimeOSHandle
        113   5D 000200D0 RuntimeOpenImage
        114   5E 000201D0 RuntimeReleaseHandle
         37   5F 00003A70 SetTargetForVTableEntry
        115   60 000202C0 StrongNameCompareAssemblies
        116   61 000203D0 StrongNameErrorInfo
        117   62 000204B0 StrongNameFreeBuffer
        118   63 00020590 StrongNameGetBlob
        119   64 000206A0 StrongNameGetBlobFromImage
        120   65 000207C0 StrongNameGetPublicKey
        121   66 00020910 StrongNameHashSize
        122   67 00020A00 StrongNameKeyDelete
        123   68 00020AF0 StrongNameKeyGen
        124   69 00020C10 StrongNameKeyGenEx
        125   6A 00020D60 StrongNameKeyInstall
        126   6B 00020E70 StrongNameSignatureGeneration
        127   6C 00020FE0 StrongNameSignatureGenerationEx
        128   6D 00021180 StrongNameSignatureSize
        129   6E 00021290 StrongNameSignatureVerification
        130   6F 000213A0 StrongNameSignatureVerificationEx
        131   70 000214B0 StrongNameSignatureVerificationFromImage
        132   71 000215D0 StrongNameTokenFromAssembly
        133   72 000216E0 StrongNameTokenFromAssemblyEx
        134   73 00021830 StrongNameTokenFromPublicKey
        135   74 00021950 TranslateSecurityAttributes
         20   75 0001B250 UpdateError
        136   76 00003940 _CorDllMain
        137   77 000010A0 _CorExeMain
        138   78 00021C10 _CorExeMain2
        139   79 0000D1F0 _CorImageUnloading
        140   7A 0002B410 _CorValidateImage
         24      00003740 [NONAME]
        142      00003920 [NONAME]

Now what's next ...

Share this post


Link to post
Share on other sites

#20 ·  Posted

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • Luigi
      By Luigi
      Greetings, someone can give a exemple, how send a error from a C#'s dll to AutoIt?
      I use this line, to send an error... but, I want get a error code In AutoIt with macro @error, it's possible?
       
      throw new ArgumentException("arquivo map não existe", "value" ); In this way, work, I know ther are error, but, @errror always is zero.
      I don't want this, I want a number as error code.
      Can you help me?
       
      Best regards
    • nss
      By nss
      Hi all,
       
      I am making a program in which I use Bass audio library (with the wrapper for autoit that I found here on forums I think) because of its support for dx effects.
      My problem, though, is that when effects as reverb or echo/delay are added, the channel length is not extended as to fit the tail of the effect, so if the file was really short, you wouldn't even hear the reverb at all.
      I've tried setting the  buffer parameter even to 60k ms, updating the channel length to 60k ms, but nothing makes it so that the effects aren't being cut off.
      I've heard that I could add silence manually to wave files by adding the chr(0) characters, but haven't had any luck doing that, either.
      What I'm doing:
      initialize bass use streamCreateFile to load the wave file with the fx flag and length parameter set to 60000 set the config buffer to 60000 use channel set fx to add dx8 reverb use channel play to play the sound use bass update to update the length to 60000  
      I even tried having only silence in one wave file and tried joining two wave files together, but that didn't work either.
       
      Any help would be very much appreciated.
    • junkew
      By junkew
      Since W8.1 (actually IE 11 with W7 will work also) microsoft has a Javascript runtime that can be called from scripting languages
      As shown in this example from C++: https://iobservable.net/blog/2013/11/12/introduction-to-jsrt/
      By loading either JSCRIPT9.DLL or CHAKRA.DLL you can embed ECMA JavaScript in your application
      And implemented here in AutoHotKey https://autohotkey.com/boards/viewtopic.php?f=6&t=5739
      Triggered by other threads: 
      https://www.autoitscript.com/forum/topic/185883-accessing-autoit-variables/ https://iobservable.net/blog/2013/11/12/introduction-to-jsrt/ https://www.autoitscript.com/forum/topic/184824-chakracore-udf-executing-javascript-in-autoit/ http://eclipsesource.com/blogs/2016/04/06/getting-started-with-microsoft-chakracore/
        This code is almost working but unfortunately not with the expected output. Someone seeing what is wrong? 
      It runs completely after fixes of DanyFirex 
       
      ;~ https://iobservable.net/blog/2013/11/ ;~ Should work on all windows versions with IE11 #AutoIt3Wrapper_UseX64=N #Region enum JsErrorCode : unsigned int Enum $JsNoError = 0, _ $JsErrorCategoryUsage = 0x10000, _ $JsErrorInvalidArgument, _ $JsErrorNullArgument, _ $JsErrorNoCurrentContext, _ $JsErrorInExceptionState, _ $JsErrorNotImplemented, _ $JsErrorWrongThread, _ $JsErrorRuntimeInUse, _ $JsErrorBadSerializedScript, _ $JsErrorInDisabledState, _ $JsErrorCannotDisableExecution, _ $JsErrorHeapEnumInProgress, _ $JsErrorArgumentNotObject, _ $JsErrorInProfileCallback, _ $JsErrorInThreadServiceCallback, _ $JsErrorCannotSerializeDebugScript, _ $JsErrorAlreadyDebuggingContext, _ $JsErrorAlreadyProfilingContext, _ $JsErrorIdleNotEnabled, _ $JsErrorCategoryEngine = 0x20000, _ $JsErrorOutOfMemory, _ $JsErrorCategoryScript = 0x30000, _ $JsErrorScriptException, _ $JsErrorScriptCompile, _ $JsErrorScriptTerminated, _ $JsErrorScriptEvalDisabled, _ $JsErrorCategoryFatal = 0x40000, _ $JsErrorFatal ;~ }JsErrorCode; #EndRegion enum JsErrorCode : unsigned int #Region typedef enum JsRuntimeVersion Enum $JsRuntimeVersion10 = 0, $JsRuntimeVersion11 = 1 #EndRegion typedef enum JsRuntimeVersion ; Create callback function. Local $hPrintf = DllCallbackRegister("_printf", "long", "ptr;bool;ptr;ushort;ptr") Local $hJSRuntime = DllOpen("c:\windows\system32\jscript9.dll") $JsRuntimeAttributeNone = 0x00000000 ;~ #RequireAdmin Example() Func Example() Local $script = "native.printf('hello world')" ;~ Local $script = "native.printf('number=%#x string=%s\n', 255, 'test')" ;~ Local $script = "(()=>{return 'Hello world!';})()" ;~ Local $script = "var x='helloworld'; return x;" ;~ Local $script = "var x=10;" & @CRLF & "var y=11;" ;~ Local $script = "(42);" ;~ Local $script = "(" & @CRLF ;~ $script=$script & "host.echo(JSON.stringify({foo:'bar'}));)" & @CRLF ;~ $script=$script & "42 // The script's result :) "& @CRLF ;~ $script=$script & ")"& @CRLF ;~ $script=$script & "class Host {"& @CRLF ;~ $script=$script & " echo(s) {"& @CRLF ;~ $script=$script & " MsgBox %s%"& @CRLF ;~ $script=$script & " }"& @CRLF ;~ $script=$script & "}"& @CRLF Local $aResult Local $runtime Local $context ;~ // Create a runtime ;~ JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime); $runtime = _JsCreateRuntime($JsRuntimeAttributeNone, 0, $runtime) ; ;~ // Create an execution context. ;~ JsCreateContext(runtime, &context); $context = _JsCreateContext($runtime, $context) ;~ // Now set the current execution context. ;~ JsSetCurrentContext(context); _JsSetCurrentContext($context) ; ; Get the Global object for adding stuff ;~ JsGetGlobalObject(&global); Local $global $global = _JsGetGlobalObject($global) ;~ JsPropertyIdRef nativeProp; ;~ JsGetPropertyIdFromName(L"native", &nativeProp); Local $nativeProp $nativeProp = _JsGetPropertyIdFromName("native", $nativeProp) ;~ JsValueRef nativeObj; ;~ JsCreateObject(&nativeObj); Local $nativeObj $nativeObj = _JsCreateObject($nativeObj) ;~ JsPropertyIdRef printfProp; ;~ JsGetPropertyIdFromName(L"printf", &printfProp); Local $printfProp $printfProp = _JsGetPropertyIdFromName("printf", $printfProp) ;~ JsValueRef printfFunc; ;~ JsCreateFunction(PrintFormat, nullptr, &printfFunc); Local $printfFunc $printfFunc = _JsCreateFunction(DllCallbackGetPtr($hPrintf), 0, $printfFunc) ;~ JsSetProperty(nativeObj, printfProp, printfFunc, true); _JsSetProperty($nativeObj, $printfProp, $printfFunc, True) ;~ JsSetProperty(global, nativeProp, nativeObj, true); _JsSetProperty($global, $nativeProp, $nativeObj, True) ;~ STDAPI_(JsErrorCode) JsCreateFunction( ;~ _In_ JsNativeFunction nativeFunction, ;~ _In_opt_ void *callbackState, ;~ _Out_ JsValueRef *function ;~ ); ; Get a JsValueRef for our Host object ;~ hostRef := ToJsValue(Host) ;~ $aResult=DllCall($hJSRuntime, "int","JsVariantToValue", "ptr", &variant, "ptr*", valref) ; Pass our Host object to the script engine ;~ DllCall("jscript9\JsSetProperty", "ptr", globalObject, "ptr", hostPropertyId, "ptr", hostRef, "int", true) ;~ // Run the script. ;~ STDAPI_(JsErrorCode) JsRunScript( ;~ _In_z_ const wchar_t *script, ;~ _In_ JsSourceContext sourceContext, ;~ _In_z_ const wchar_t *sourceUrl, ;~ _Out_ JsValueRef *result ;~ ); Local $currentSourceContext = 1 ;~ JsRunScript(script.c_str(), currentSourceContext++, L"", &result); Local $result = "" Local $sourceURL = "" $aResult = DllCall($hJSRuntime, "int", "JsRunScript", "WSTR", $script, "UINT*", $currentSourceContext, "wstr", "dummysource.js", "WSTR*", $result) ConsoleWrite("Error 11: " & @error & @CRLF) If @error = 0 Then ConsoleWrite($aResult[0] & ";" & $aResult[1] & ";" & $aResult[2] & ";" & $aResult[3] & ";" & $aResult[4] & @CRLF) EndIf ;~ // Convert your script result to String in JavaScript redundant if your script returns a String ;~ JsValueRef resultJSString; ;~ STDAPI_(JsErrorCode) JsConvertValueToString( ;~ _In_ JsValueRef value, ;~ _Out_ JsValueRef *stringValue ;~ ); ;~ JsConvertValueToString(result, &resultJSString); ;~ $aResult=DllCall($hJSRuntime, "int", "JsConvertValueToString", "WSTR", $script, "long", 1, "WSTR*",0, "WSTR*", $result) ;~ consolewrite("Error 4: " & @error & @CRLF) ;~ if @error=0 Then ;~ consolewrite($aResult[0] & ";" & $aResult[1] & ";" & $aResult[2] & ";" & $aResult[3] & ";" & $aResult[4] & @CRLF) ;~ EndIf ;~ ;~ // Project script result back to C++. ;~ const wchar_t *resultWC; ;~ size_t stringLength; ;~ JsStringToPointer(resultJSString, &resultWC, &stringLength); ;~ wstring resultW(resultWC); ;~ cout << string(resultW.begin(), resultW.end()) << endl; ;~ system("pause"); ;~ // Dispose runtime ;~ JsSetCurrentContext(JS_INVALID_REFERENCE); ;~ JsDisposeRuntime(runtime); Return 0 ; EndFunc ;==>Example ; Create callback function. ;~ JsValueRef CALLBACK PrintFormat(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState) ;~ { ;~ const wchar_t *format; ;~ size_t length; ;~ JsStringToPointer(arguments[1], &format, &length); ;~ VARIANT variant; ;~ JsValueToVariant(arguments[2], &variant); ;~ const wchar_t *str; ;~ JsStringToPointer(arguments[3], &str, &length); ;~ wprintf(format, variant.intVal, str); ;~ return JS_INVALID_REFERENCE; ;~ } ;~ typedef _Ret_maybenull_ JsValueRef (CALLBACK * JsNativeFunction)( ;~ _In_ JsValueRef callee, ;~ _In_ bool isConstructCall, ;~ _In_ JsValueRef *arguments, ;~ _In_ unsigned short argumentCount ;~ ); Func _printf($callee, $isConstructCall, $arguments, $argumentCount, $callbackState) ConsoleWrite("there we are with " & $argumentCount & " arguments" & @CRLF) Local $tArgs = DllStructCreate("ptr JsValues[" & $argumentCount & "]", $arguments) ;~ STDAPI_(JsErrorCode) JsConvertValueToString( ;~ _In_ JsValueRef value, ;~ _Out_ JsValueRef *stringValue ;~ ); ;~ JsConvertValueToString(result, &resultJSString); local $tresult $aResult=DllCall($hJSRuntime, "int", "JsConvertValueToString", "ptr", DllStructGetData($tArgs,1,2), "ptr*", $tresult) consolewrite("Error 4: " & @error & @CRLF) if @error=0 Then consolewrite( $aResult[0] & ";" & $aResult[1] & ";" & $aResult[2] & @CRLF) $tresult=$aresult[2] EndIf ;~ STDAPI_(JsErrorCode) JsValueToVariant( ;~ _In_ JsValueRef object, ;~ _Out_ VARIANT *variant ;~ ); ;~ Local $aResult = DllCall($hJSRuntime, "dword", "JsValueToVariant", "ptr", $arguments[0], "ptr*", 0) ;~ If @error Then Return SetError(3, 0, @error) ;~ If $aResult[0] <> 0 Then Return SetError(4, 0, $aResult[0]) ;~ consolewrite($aResult[2]) Local $aResult = DllCall($hJSRuntime, "dword", "JsStringToPointer", "ptr", $tResult, "ptr*", 0, "int*", 0) If @error Then Return SetError(3, 0, @error) If $aResult[0] <> 0 Then Return SetError(4, 0, $aResult[0]) Local $tString = DllStructCreate("wchar string["&$aResult[3]&"]", $aResult[2]) consolewrite("+Parameter: " & $tString.string & @CRLF) Return 0 EndFunc ;==>_printf ;~ typedef void *JsRuntimeHandle; ;~ // Create a runtime. ;~ Edge mode signature STDAPI_(JsErrorCode) JsCreateRuntime( ;~ _In_ JsRuntimeAttributes attributes, ;~ _In_opt_ JsThreadServiceCallback threadService, ;~ _Out_ JsRuntimeHandle *runtime); ;~ Legacy mode signature ;~ STDAPI_(JsErrorCode) JsCreateRuntime( ;~ _In_ JsRuntimeAttributes attributes, ;~ _In_ JsRuntimeVersion version, ;~ _In_opt_ JsThreadServiceCallback threadService, ;~ _Out_ JsRuntimeHandle *runtime ;~ ); ;~ $runtime=_JsCreateRuntime(JsRuntimeAttributeNone, 0, $runtime); Func _JsCreateRuntime($JsRuntimeAttributeNone, $JSRuntimeVersion, $runtime) $aResult = DllCall($hJSRuntime, "int", "JsCreateRuntime", "int", $JsRuntimeAttributeNone, "int", $JSRuntimeVersion, "ptr", 0, "ptr*", $runtime) If @error Then Return SetError(1, @error, 0) Return $aResult[4] EndFunc ;==>_JsCreateRuntime ;~ // Edge mode signature ;~ STDAPI_(JsErrorCode) JsCreateContext( ;~ _In_ JsRuntimeHandle runtime, ;~ _Out_ JsContextRef *newContext); ;~ // Legacy mode signature ;~ STDAPI_(JsErrorCode) JsCreateContext( ;~ _In_ JsRuntimeHandle runtime, ;~ _In_ IDebugApplication *debugApplication, ;~ _Out_ JsContextRef *newContext ;~ ); ;~ JsCreateContext(runtime, &context); Func _JsCreateContext($runtime, $context) $aResult = DllCall($hJSRuntime, "int", "JsCreateContext", "ptr", $runtime, "ptr", 0, "ptr*", $context) If @error Then Return SetError(1, @error, 0) Return $aResult[3] EndFunc ;==>_JsCreateContext ;~ STDAPI_(JsErrorCode) JsSetCurrentContext( ;~ _In_ JsContextRef context ;~ ); ;~ JsSetCurrentContext(context); Func _JsSetCurrentContext($context) $aResult = DllCall($hJSRuntime, "int", "JsSetCurrentContext", "ptr", $context) If @error Then Return SetError(1, @error, 0) Return $JsNoError EndFunc ;==>_JsSetCurrentContext ; Get the Global object for adding stuff ;~ STDAPI_(JsErrorCode) JsGetGlobalObject( ;~ _Out_ JsValueRef *globalObject ;~ ); ;~ JsValueRef global; ;~ JsGetGlobalObject(&global); Func _JsGetGlobalObject($global) $aResult = DllCall($hJSRuntime, "int", "JsGetGlobalObject", "ptr*", $global) If @error Then Return SetError(1, @error, 0) Return $aResult[1] EndFunc ;==>_JsGetGlobalObject ; Get a property ID for the name "host" ;~ STDAPI_(JsErrorCode) JsGetPropertyIdFromName( ;~ _In_z_ const wchar_t *name, ;~ _Out_ JsPropertyIdRef *propertyId ;~ ); ;~ DllCall("jscript9\JsGetPropertyIdFromName", "wstr", "host", "ptr*", hostPropertyId) ;~ local $hostPropertyID ;~ $aResult=DllCall($hJSRuntime, "int","JsGetPropertyIdFromName", "wstr", "host", "ptr*", $hostPropertyId) ;~ consolewrite("Error 5: " & @error & @CRLF) ;~ if @error=0 Then ;~ consolewrite($aResult[0] & ";" & $aResult[1] & ";" & $aResult[2] & @CRLF) ;~ EndIf ;~ JsPropertyIdRef nativeProp; ;~ JsGetPropertyIdFromName(L"native", &nativeProp); Func _JsGetPropertyIdFromName($propname, $nativeProp) $aResult = DllCall($hJSRuntime, "int", "JsGetPropertyIdFromName", "wstr", $propname, "ptr*", $nativeProp) If @error Then Return SetError(1, @error, 0) Return $aResult[2] EndFunc ;==>_JsGetPropertyIdFromName ;~ STDAPI_(JsErrorCode) JsCreateObject( ;~ _Out_ JsValueRef *object ;~ ); ;~ JsValueRef nativeObj; ;~ JsCreateObject(&nativeObj); Local $nativeObj Func _JsCreateObject($JSRTobject) $aResult = DllCall($hJSRuntime, "int", "JsCreateObject", "ptr*", $JSRTobject) If @error Then Return SetError(1, @error, 0) Return $aResult[1] EndFunc ;==>_JsCreateObject ;~ STDAPI_(JsErrorCode) JsCreateFunction( ;~ _In_ JsNativeFunction nativeFunction, ;~ _In_opt_ void *callbackState, ;~ _Out_ JsValueRef *function ;~ ); Func _JsCreateFunction($fncCallBackPtr, $callbackState, $fncVar) $aResult = DllCall($hJSRuntime, "int", "JsCreateFunction", "ptr", $fncCallBackPtr, "ptr*", $callbackState, "ptr*", $fncVar) If @error Then Return SetError(1, @error, 0) Return $aResult[3] EndFunc ;==>_JsCreateFunction ;~ JsSetProperty(nativeObj, printfProp, printfFunc, true); ;~ STDAPI_(JsErrorCode) JsSetProperty( ;~ _In_ JsValueRef object, ;~ _In_ JsPropertyIdRef propertyId, ;~ _In_ JsValueRef value, ;~ _In_ bool useStrictRules ;~ ); Func _JsSetProperty($Obj, $Prop, $Func, $val) ; $aResult = DllCall($hJSRuntime, "int", "JsSetProperty", "ptr", $Obj, "ptr", $Prop, "ptr", $Func, "int", $val) If @error Then Return SetError(1, @error, 0) EndFunc ;==>_JsSetProperty  
    • ur
      By ur
      Is there anyway to create an assembly for AutoIT so that I can use that in Powershell or Dotnet supported languages like c#.
      Like I want to use the functionality of _ArrayDisplay of AutoIT in C# by creating a assmbly/library and using that in the target language.
    • UEZ
      By UEZ
      Since I disovered FreeBasic I decided to create a DLL to implement much faster image processing functionality to AutoIt.
      Following functions are implemented yet:
      _GDIPlus_BitmapApplyFilter_BWJJNDithering _GDIPlus_BitmapApplyFilter_Cartoon1 _GDIPlus_BitmapApplyFilter_ColorAccent _GDIPlus_BitmapApplyFilter_Convolution_AnotherBlur _GDIPlus_BitmapApplyFilter_Convolution_BoxBlur _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection1 _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection2 _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection3 _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection4 _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection5 _GDIPlus_BitmapApplyFilter_Convolution_EdgeDetection6 _GDIPlus_BitmapApplyFilter_Convolution_Emboss1 _GDIPlus_BitmapApplyFilter_Convolution_Emboss45Degree _GDIPlus_BitmapApplyFilter_Convolution_EmbossTopLeftBottomRight _GDIPlus_BitmapApplyFilter_Convolution_Gaussian3x3 _GDIPlus_BitmapApplyFilter_Convolution_Gaussian5x5_1 _GDIPlus_BitmapApplyFilter_Convolution_Gaussian5x5_2 _GDIPlus_BitmapApplyFilter_Convolution_GaussianBlur _GDIPlus_BitmapApplyFilter_Convolution_IntenseEmboss _GDIPlus_BitmapApplyFilter_Convolution_Kirsch _GDIPlus_BitmapApplyFilter_Convolution_Laplace1 _GDIPlus_BitmapApplyFilter_Convolution_Laplace2 _GDIPlus_BitmapApplyFilter_Convolution_Laplace3 _GDIPlus_BitmapApplyFilter_Convolution_LaplacianOfGaussian _GDIPlus_BitmapApplyFilter_Convolution_ManualMatrix _GDIPlus_BitmapApplyFilter_Convolution_MotionBlur _GDIPlus_BitmapApplyFilter_Convolution_Outline3x3 _GDIPlus_BitmapApplyFilter_Convolution_Prewitt _GDIPlus_BitmapApplyFilter_Convolution_Sharpen1 _GDIPlus_BitmapApplyFilter_Convolution_Sharpen2 _GDIPlus_BitmapApplyFilter_Convolution_Sobel _GDIPlus_BitmapApplyFilter_Convolution_SovelVsPrewitt _GDIPlus_BitmapApplyFilter_Convolution_TriangleBlur _GDIPlus_BitmapApplyFilter_Convolution_Unsharp _GDIPlus_BitmapApplyFilter_Convolution_Unsharp5x5 _GDIPlus_BitmapApplyFilter_Dilatation _GDIPlus_BitmapApplyFilter_DistortionBlur _GDIPlus_BitmapApplyFilter_Edges _GDIPlus_BitmapApplyFilter_Erosion _GDIPlus_BitmapApplyFilter_FishEye _GDIPlus_BitmapApplyFilter_Indexed _GDIPlus_BitmapApplyFilter_Jitter _GDIPlus_BitmapApplyFilter_Kuwahara _GDIPlus_BitmapApplyFilter_Linellism _GDIPlus_BitmapApplyFilter_Median _GDIPlus_BitmapApplyFilter_Median2 _GDIPlus_BitmapApplyFilter_OilPainting _GDIPlus_BitmapApplyFilter_PenSketch _GDIPlus_BitmapApplyFilter_PenSketch2 _GDIPlus_BitmapApplyFilter_Pixelate _GDIPlus_BitmapApplyFilter_Pointillism _GDIPlus_BitmapApplyFilter_RadialBlur _GDIPlus_BitmapApplyFilter_Raster _GDIPlus_BitmapApplyFilter_Swirl _GDIPlus_BitmapApplyFilter_SymmetricNearestNeighbour _GDIPlus_BitmapApplyFilter_TiltShift _GDIPlus_BitmapApplyFilter_TimeWarp _GDIPlus_BitmapApplyFilter_Wave _GDIPlus_BitmapApplyFilter_XRay  
      Since I am absolutely a newbie in FreeBasic, the DLL may contain errors.  Please report any bug.
       
      FreeBasic source code can be found here: https://pastebin.com/Lugp6rCR
       
      To do:
      add function headers with descriptions speed-up FB code -> partly done add more filters -> ongoing  
      Credits to:
      Jakub Szymanowski rdc Dewald Esterhuizen Santhosh G_  Christian Graus www.gutgames.com  
      Have fun.
       
      Download link: 
       
      You can compare the speed with AutoIt version:
      #AutoIt3Wrapper_Version=b #include <Array.au3> #include <GDIPlus.au3> Global $sFile = FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.gif;*.bmp)") If @error Then Exit _GDIPlus_Startup() Global Const $STM_SETIMAGE = 0x0172 Global Const $hImage = _GDIPlus_ImageLoadFromFile($sFile) Global Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Global Const $hGUI = GUICreate("GDI+ Image Filters", $iW * 2, $iH) Global $fProg = 0, $iEnd = $iW * $iH - 1 AdlibRegister("Progress", 490) Global $t = TimerInit() Global Const $hGDIBitmap = _GDIPlus_BitmapApplyFilter_Median($hImage, 4) ConsoleWrite(Round(TimerDiff($t) / 1000, 2) & " s / " & Round(TimerDiff($t) / 60000, 2) & " min" & @CRLF) Global Const $iPic = GUICtrlCreatePic("", 0, 0, $iW - 1, $iH - 1) Global Const $iPic_o = GUICtrlCreatePic("", $iW, 0, $iW - 1, $iH - 1) _WinAPI_DeleteObject(GUICtrlSendMsg($iPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hGDIBitmap)) Global Const $hGDIBitmap2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _WinAPI_DeleteObject(GUICtrlSendMsg($iPic_o, $STM_SETIMAGE, $IMAGE_BITMAP, $hGDIBitmap2)) GUISetState() AdlibUnRegister("Progress") ToolTip("") Do Until GUIGetMsg() = -3 _GDIPlus_ImageDispose($hImage) _WinAPI_DeleteObject($hGDIBitmap) _WinAPI_DeleteObject($hGDIBitmap2) _GDIPlus_Shutdown() Exit Func Progress() ToolTip(Int($fProg / $iEnd * 100) & " % / " & Round(TimerDiff($t) / 60000, 2) & " min", MouseGetPos(0) + 30, MouseGetPos(1) + 30) EndFunc #Region Symmetric Nearest Neighbour Func _GDIPlus_BitmapApplyFilter_SymmetricNearestNeighbour($hImage, $fRadius = 2, $bGDI = True) ;no alpha channel implemented yet Local Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Local Const $hBitmap_Dest = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local Const $tBitmapData_Dest = _GDIPlus_BitmapLockBits($hBitmap_Dest, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) Local Const $iScan0_Dest = DllStructGetData($tBitmapData_Dest, "Scan0") Local Const $tPixel_Dest = DllStructCreate("int[" & $iW * $iH & "];", $iScan0_Dest) Local Const $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local Const $iScan0 = DllStructGetData($tBitmapData, "Scan0") Local Const $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0) Local $iRowOffset, $iX, $iY, $c, $k, $sumR, $sumG, $sumB, $iCount, $xx, $yy, $iR, $iG, $iB, $iR1, $iG1, $iB1, $iR2, $iG2, $iB2, $x, $y For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW For $iX = 0 To $iW - 1 $sumR = 0 $sumG = 0 $sumB = 0 $iCount = 0 $c = DllStructGetData($tPixel, 1, $iRowOffset + $iX) $iR = BitShift(BitAND(0x00FF0000, $c), 16) $iG = BitShift(BitAND(0x0000FF00, $c), 8) $iB = BitAND(0x000000FF, $c) For $yy = -$fRadius To $fRadius For $xx = -$fRadius To $fRadius $k = $iX + $xx $x = $k < 0 ? 0 : $k > $iW - 1 ? $iW - 1 : $k $k = $iY + $yy $y = $k < 0 ? 0 : $k > $iH - 1 ? $iH - 1 : $k $c = DllStructGetData($tPixel, 1, $y * $iW + $x) $iR1 = BitShift(BitAND(0x00FF0000, $c), 16) $iG1 = BitShift(BitAND(0x0000FF00, $c), 8) $iB1 = BitAND(0x000000FF, $c) $k = $iX - $xx $x = $k < 0 ? 0 : $k > $iW - 1 ? $iW - 1 : $k $k = ($iY - $yy) $y = $k < 0 ? 0 : $k > $iH - 1 ? $iH - 1 : $k $c = DllStructGetData($tPixel, 1, $y * $iW + $x) $iR2 = BitShift(BitAND(0x00FF0000, $c), 16) $iG2 = BitShift(BitAND(0x0000FF00, $c), 8) $iB2 = BitAND(0x000000FF, $c) If __DeltaE($iR, $iG, $iB, $iR1, $iG1, $iB1) < __DeltaE($iR, $iG, $iB, $iR2, $iG2, $iB2) Then $sumR += $iR1 $sumG += $iG1 $sumB += $iB1 Else $sumR += $iR2 $sumG += $iG2 $sumB += $iB2 EndIf $iCount += 1 Next Next DllStructSetData($tPixel_Dest, 1, 0xFF000000 + Int($sumR / $iCount) * 0x10000 + Int($sumG / $iCount) * 0x100 + Int($sumB / $iCount), $iRowOffset + $iX) $fProg += 1 Next Next _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_BitmapUnlockBits($hBitmap_Dest, $tBitmapData_Dest) _GDIPlus_ImageSaveToFile($hBitmap_Dest, @ScriptDir & "\Filter_SNN" & $fRadius & "_" & @YEAR & @MON & @MDAY & @MIN & @SEC & ".png") If $bGDI Then Local $hGDIBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Dest) _GDIPlus_BitmapDispose($hBitmap_Dest) Return $hGDIBitmap EndIf Return $hBitmap_Dest EndFunc Func __DeltaE($iR1, $iG1, $iB1, $iR2, $iG2, $iB2) Return Sqrt(($iR1 - $iR2) * ($iR1 - $iR2) + ($iG1 - $iG2) * ($iG1 - $iG2) + ($iB1 - $iB2) * ($iB1 - $iB2)) EndFunc #EndRegion #Region Jitter Func _GDIPlus_BitmapApplyFilter_Jitter($hImage, $iAmount = 20, $bGDI = True) Local Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Local Const $hBitmap_Dest = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local Const $tBitmapData_Dest = _GDIPlus_BitmapLockBits($hBitmap_Dest, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) Local Const $iScan0_Dest = DllStructGetData($tBitmapData_Dest, "Scan0") Local Const $tPixel_Dest = DllStructCreate("int[" & $iW * $iH & "];", $iScan0_Dest) Local Const $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local Const $iScan0 = DllStructGetData($tBitmapData, "Scan0") Local Const $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0) Local $iX, $iY, $iRowOffset, $fNX, $fNY For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 $fNX = $iX + Int((Random() - 0.5) * $iAmount) $fNX = $fNX < 1 ? 1 : $fNX > $iW - 1 ? $iW - 1 : $fNX $fNY = ($iY + Int((Random() - 0.5) * $iAmount)) $fNY = $fNY < 1 ? 1 : $fNY > $iH - 1 ? $iH - 1 : $fNY $fNY *= $iW DllStructSetData($tPixel_Dest, 1, DllStructGetData($tPixel, 1, $fNY + $fNX), $iRowOffset + $iX) $fProg += 1 Next Next _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_BitmapUnlockBits($hBitmap_Dest, $tBitmapData_Dest) _GDIPlus_ImageSaveToFile($hBitmap_Dest, @ScriptDir & "\Filter_Jitter" & $iAmount & "_" & @YEAR & @MON & @MDAY & @MIN & @SEC & ".png") If $bGDI Then Local $hGDIBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Dest) _GDIPlus_BitmapDispose($hBitmap_Dest) Return $hGDIBitmap EndIf Return $hBitmap_Dest EndFunc #EndRegion #Region Median Func _GDIPlus_BitmapApplyFilter_Median($hImage, $fRadius = 3, $bGDI = True) Local Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Local Const $hBitmap_Dest = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local Const $tBitmapData_Dest = _GDIPlus_BitmapLockBits($hBitmap_Dest, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMWRITE, $GDIP_PXF32ARGB) Local Const $iScan0_Dest = DllStructGetData($tBitmapData_Dest, "Scan0") Local Const $tPixel_Dest = DllStructCreate("int[" & $iW * $iH & "];", $iScan0_Dest) Local Const $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW - 1, $iH - 1, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local Const $iScan0 = DllStructGetData($tBitmapData, "Scan0") Local Const $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0) Local $iX, $iY, $iRowOffset For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 DllStructSetData($tPixel_Dest, 1, __Median_Value($iX, $iY, $fRadius, $tPixel, $iW, $iH), $iRowOffset + $iX) $fProg += 1 Next Next _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData) _GDIPlus_BitmapUnlockBits($hBitmap_Dest, $tBitmapData_Dest) _GDIPlus_ImageSaveToFile($hBitmap_Dest, @ScriptDir & "\Filter_Median" & $fRadius & "_" & @YEAR & @MON & @MDAY & @MIN & @SEC & ".png") If $bGDI Then Local $hGDIBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Dest) _GDIPlus_BitmapDispose($hBitmap_Dest) Return $hGDIBitmap EndIf Return $hBitmap_Dest EndFunc Func __Median_Value($iPosX, $iPosY, $fRadius, $tPixel, $iW, $iH) Local $iX, $iY, $aColors[1000], $iColors = 0, $iSize = $iW * $iH - 1, $iOff, $e For $iX = $iPosX - $fRadius To $iPosX + $fRadius For $iY = $iPosY - $fRadius To $iPosY + $fRadius $iOff = 1 + $iY * $iW + $iX $aColors[$iColors] = DllStructGetData($tPixel, 1, $iOff < 1 ? 1 : $iOff > $iSize ? $iSize : $iOff) $iColors += 1 Next Next ReDim $aColors[$iColors] ;~ _ArraySort($aColors, 0) $e = $iColors - 1 __ArrayQuickSort1D($aColors, 0, $e) Local $iMid = Floor($iColors / 2), $iMedian If BitAND($iColors, 1) Then $iMedian = Int($aColors[$iMid + 1]) Else $iMedian = Int(($aColors[$iMid] + $aColors[$iMid + 1]) / 2) EndIf Return $iMedian EndFunc #EndRegion