Jump to content
SaschaMan

Webcam Datamatrix Decoding .NET dll Bitmap parameter

Recommended Posts

SaschaMan

Hi, all,

 

I am trying to make a datamatrix decoding program for a usb webcam. I am using the Datamatrix.net 0.4.4 dll (in C#). This dll has the following exported function:

I just don't know how to pass the HBITMAP or a BITMAP to the .net dll.

 namespace DataMatrix.net
{
    [ComVisible(true)]
    public class DmtxImageDecoder
    {
        /// <summary>
        /// returns a list of all decoded DataMatrix codes in the image provided
        /// </summary>
 public List<string> DecodeImage(Bitmap image)
        {
            return DecodeImage(image, int.MaxValue, TimeSpan.MaxValue);
        }

 

In Autoitv3 i used Dot-NET_AutoIt.au3, and loaded the dll without errors. Then I use _ScreenCapture_CaptureWnd to capture the Handle of the Webcam image window, which also works.

But when I try to call the dll DecodeImage function, AutoIt crashes:

;(...) Load of .net dll - works
;(...)


Func Snapper()
   Local $hBMP, $hBitmap, $hGraphic, ReturnS
   $hBMP = _ScreenCapture_CaptureWnd("", $hGUI, 0, 0, -1, -1, False); we take a picture of the gui with the video stream    
   ; The Following works: (just for testing purposes)
   _WinAPI_SaveHBITMAPToFile("Test2.bmp",$hBMP)
   ;now create Bitmap from HBITMAP:
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
    ; Now Call to the dll, which crashes:
    $ReturnS = $oPerson.DecodeImage($hBitmap)
 
 ;(...)

I also tried to pass a HBITMAP:

        /// <summary>
        /// returns a list of all decoded DataMatrix codes in the image provided
        /// </summary>
        public String DecodeImage4(IntPtr HbitmapHandle)
        {



            Bitmap bild = Bitmap.FromHbitmap(hbitmapHandle);
            String ReturnS;
            List<string> ListS;
            ListS = DecodeImage(bild, int.MaxValue, TimeSpan.MaxValue);
            //Return only the first Datamatrix
            ReturnS = ListS[0];
            return ReturnS;
            
          }

Like This:

;(...) Load of .net dll - works
;(...)


Func Snapper()
   Local $hBMP, $hBitmap, $hGraphic, ReturnS
   
   $hBMP = _ScreenCapture_CaptureWnd("", $hGUI, 0, 0, -1, -1, False); we take a picture of the gui with the video stream    
   ; The Following works:
   _WinAPI_SaveHBITMAPToFile("Test2.bmp",$hBMP)
   
    ; Now Call to the dll, which crashes:
    $ReturnS = $oPerson.DecodeImage($hBMP)
 
 ;(...)

Always the same error message:

 ==> The requested action with this object has failed.:
$ReturnS = $oPerson.DecodeImage($hBMP)
$ReturnS = $oPerson^ ERROR

I tried to call another function in the dll, which worked ok.

I just don't know how to pass the HBITMAP or a BITMAP to the .net dll.

Any idea anyone? Thank you :)

 

Share this post


Link to post
Share on other sites
LarsJ
Posted (edited)

The image input parameter can be a problem. Another problem is that the DecodeImage method seems to be returning a list. There is no way to return a list from C# to AutoIt. Only an array.

The solution is to create a small wrapper object in C#/VB code to handle the communication between AutoIt and the methods in the C# dll-file. Then you load the C# dll-file in C#/VB code instead of AutoIt code. The wrapper method can be executed in AutoIt with the techniques in Using C# and VB Code in AutoIt or .NET Common Language Runtime.

In the wrapper method you can

  1. Validate the input parameters from AutoIt before they are passed to the method in the C# dll-file
  2. Validate the output from the method in the C# dll-file before it's returned to AutoIt
  3. In case the output is a list, convert it to an array before it's returned to AutoIt
Edited by LarsJ
  • Like 1

Share this post


Link to post
Share on other sites
SaschaMan

Thank you for the replies and your time.

@Earthshine: Sorry, no that does not help.

@LarsJ:

I have the C# source code of the Datamatrix.net.dll (its on Sourceforge). I can compile it and write my own functions to the dll. I changed the function to return a string.  The function in C# is:
 

        public String DecodeImage2(Bitmap image)
        {
            String ReturnS;
            List<string> ListS;
            ListS = DecodeImage(image, int.MaxValue, TimeSpan.MaxValue);
            if (ListS.Count == 0) // There is no Match
            {
                ListS.Add("");
            }
            //Return only the first Datamatrix Found (or Empty String if not found)
            ReturnS = ListS[0];
            return ReturnS;
        }

 

There is no problem in generally calling the C# dll Functions from AutoIt.

There is only the problem, how to pass the Bitmap from AutoIt to C# in the function argument:

 

This AutoIt function returns "a handle to an HBITMAP if $sFileName is empty":

$HBitmap = _ScreenCapture_CaptureWnd("", $hGUI, 0, 0, -1, -1, False)

 

I tried out two options:

1) I create a Bitmap from Hbitmap with the following code:

$xBitmap=_GDIPlus_BitmapCreateFromHBITMAP($HBitmap)

Then I pass this Bitmap to the C# dll function object $oPerson

$ReturnS = $oPerson.DecodeImage2($xBitmap)


But this crashes.

 

2) I also tried to pass the Hbitmap as Inptr to the C# dll:

in C# Definiton:

public String DecodeImage3(IntPtr image)

In Autohotkey:
 

$HBitmap = _ScreenCapture_CaptureWnd("", $hGUI, 0, 0, -1, -1, False)

$ReturnS = $oPerson.DecodeImage3($HBitmap)

ALso a crash.

Any idea how to pass the AutoIt Bitmap to the C# dll Bitmap?

Thank you again for looking at this.

Share this post


Link to post
Share on other sites
LarsJ

The easy way is to save the bitmap as an image file on disk in the AutoIt code and then load the image file in the C# code. That's maybe the only easy way.

Share this post


Link to post
Share on other sites
SaschaMan

Well, this was actually the original idea, but since the Datamatrix Reading Function is called two times a second and the AutoIt Software will run 24 hours a day, my Idea was to avoid Hard Disk activities. Ok, I can create a RAM-Disk, but thats also not so very nice, since I need to install it, and I want to use it on several Computers.

However, if there is no (easy) way to pass the bitmap to the .NET DLL, I am now thinking of writing an AutoIt function to convert the Bitmap to some type of string, pass the string to the .NET dll and program a conversion from string to bitmap. But thats not very elegant, but may work.

Thank you for your input :)

Share this post


Link to post
Share on other sites
LarsJ
Earthshine

yes. why not just use c#


My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
SaschaMan
Posted (edited)

The reason for using AutoIt was that I had the code for AutoIt from Qwerty212 from here https://www.autoitscript.com/forum/topic/151800-webcam-barcode-reader-using-zxing/ and I use AutoIt quite frequent.

There were only two things that I wanted to change: I did not want to use Java, so I wanted to switch from zxing to Datamatrix.net.

And I wanted to get rid of the saving of the image to harddisk, like Larsj said, 172800 times a day.

I thougt only minor changes were needed for this, which is true besides the one problem I described.

OK, you convinced me, I will code everything in VB.NET. I dont like C# so much, but the use of the .NET dll will be indepent from using C# or VB.NET.

 

Thank you for your support and your time.

 

Edited by SaschaMan

Share this post


Link to post
Share on other sites
SaschaMan

@boomingranny, thank you for the link 

Share this post


Link to post
Share on other sites
SaschaMan

Just wanted to tell you that I have found the (or a possible) solution.

I need to pass the Bitmap handle as int64 and convert it to IntPtr in C#:

In Autoit:

;get Handle to hBitmap (? according to help file)from GUI ($hGUI is Handle of GUI Window)
$hBMP = _ScreenCapture_CaptureWnd("", $hGUI, 0, 0, -1, -1, False); we take a picture of the gui with the video stream only. It increases the performance
  ;Convert to Pointer -> $haha
$haha = Ptr($hBMP)
   ;$ReturnS = Datamatrix reader return String
$ReturnS = $oPerson.DecodeImage3(dec(hex($haha)))

 

in C#

public String DecodeImage3(Int64 PtrFromAutoit)
        {

            IntPtr CSPointer = new IntPtr(PtrFromAutoit);
            Bitmap iBitmap = Image.FromHbitmap(CSPointer);
            
            (...)

And then I have my Bitmap from Autoit in C# dll...

Its also quite fast....

 

Thank you for your suggestions...

 

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

×