Answered Problem with RetrieveImage

  • Thursday, October 01, 2009 2:26 PM
     
     
    Hi, i have successfully got code working to read a cheque image from a Magtek MicrImage reader.  However, the RetrieveImage method is causing me problems as when i attempt to read the ImageData property, i get corrupted or half an image - which i'm guessing is due to me trying to read the imagedata before RetrieveImage has completed (the device is using serial over USB). 

    I stuck a thread sleep in and waiting for a few seconds before saving and all the data seems to be there but obviously i dont want to put a "finger in the air" guess-bit-of-code around this waiting for the data to complete. Is there any way i can be signalled when the image data has been downloaded in full?

    Steve

Answers

  • Friday, October 02, 2009 11:04 AM
    Answerer
     
     Answered
    Hi,

    While you should always call BeingInsertion etc. to ensure your code works with devices that require it, it sounds like your device doesn't need that because of the auto-sheet feeder, so those methods *should* be irrelevant as far as your problems go.

    It might pay you to alter the statusupdateevent to check whether or not the status event you've received is actually an image arriving. It might be you're asking for an image when you get some other kind of status event and that's messing something up... maybe. The value of e.Status should equal CheckScanner.StatusScanComplete before you actually attempt to read the image.

    I think the reason you don't get an image after the first one is that the dataevent has been disabled... in the status update event, after you retrieve the image, reset both DeviceEnabled (in case the AutoDisable property is set to true as well) and DataEventEnabled to true. That should allow the next image to be captured.

    Short of the status check, I'm not sure why you'd only get half an image though.
  • Friday, October 02, 2009 7:20 PM
    Answerer
     
     Answered
    Acutally, in addition to my previous comments I think this part of the documentation is key;

    "If the application has to retrieve the image or a cropped part of the image, it calls the RetrieveImage method. The image data is sent from the device to the service object and stored in the ImageData property. When the corresponding DataEvent event is delivered, the current image (or cropped part of the current image) may be accessed by the application reading the image file that is contained in the ImageData property."

    Looking at my own implementation, I call RetrieveImage in the statusupdate event if e.Status == CheckScanner.StatusScanComplete, then in my event handler for the DataEvent (which I have already connected to previously) I retrieve the contents of the ImageData property and then re-enable the device and data event.

    It's quite likely you're reading the buffer before it's completely full because you're not waiting for the data event before retrieving the image, which would explain the half/corrupted image, and failure to re-enable the device/data event would prevent further images being scanned.

    The CheckScanner is defintely one of the more awkward Pos .Net devices to use.

  • Sunday, October 04, 2009 4:11 AM
     
     Answered
    While not related to your specific problem, I strongly recommend that you pass the form when you create the PosExplorer in order to ensure that all events are marshaled to the UI thread.

    While I've used MICRs, I don't have any personal experience with CheckScanners.  I would just recommend that you read the UPOS spec carefully for this device category and see if you may have overlooked something.

All Replies

  • Thursday, October 01, 2009 7:03 PM
    Answerer
     
     
    Hi Steve,

    When and where are you calling RetrieveImage... can you post the code ?

    There is a status event that that indicates the image has been read, if you are calling RetrieveImage from the StatusUpdateEvent event handler when you get the event code that means image read, then the buffer *should* contain a complete image as far as I know.

  • Friday, October 02, 2009 9:25 AM
     
      Has Code
    Imports Microsoft.PointOfService
    Imports System.Threading
    
    Public Class Form1
    
        Private explorer As PosExplorer
        Private scannerList As DeviceCollection
        Private activeDevice As DeviceInfo
        Private WithEvents activeScanner As Microsoft.PointOfService.CheckScanner
        Private autoReset As New AutoResetEvent(False)
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            explorer = New PosExplorer
    
            scannerList = explorer.GetDevices
    
    
            For Each Device As DeviceInfo In scannerList
                If Device.ServiceObjectName = "MagTek MicrImage" Then
                    activeDevice = Device
                    Exit For
                End If
            Next
    
            activeScanner = CType(explorer.CreateInstance(activeDevice), CheckScanner)
            activeScanner.Open()
            activeScanner.Claim(1000)
            activeScanner.DeviceEnabled = True
            activeScanner.DataEventEnabled = True
        End Sub
    
        Private Sub activeScanner_StatusUpdateEvent(ByVal sender As Object, ByVal e As Microsoft.PointOfService.StatusUpdateEventArgs) Handles activeScanner.StatusUpdateEvent
            Dim crop As Integer = Microsoft.PointOfService.CheckScanner.CropAreaEntireImage
            activeScanner.RetrieveImage(crop)
            activeScanner.ImageData.Save("c:\temp\scanner-" & Now.ToString("dd-MM-yyyy-HH-mm-ss") & ".bmp")
        End Sub
    
        Private Sub btnEndInsertion_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEndInsertion.Click
            activeScanner.EndInsertion()
            activeScanner.BeginRemoval(1000)
            activeScanner.EndRemoval()
        End Sub
    
        Private Sub btnBeginInsertion_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBeginInsertion.Click
            activeScanner.BeginInsertion(10000)
        End Sub
    End Class
  • Friday, October 02, 2009 9:27 AM
     
     
    The problem i've got is knowing what order to do things in - i appreciate that BeginInsertion, EndInsertion, BeginRemoval, EndRemoval need always to be called according to the documentation but the device has an automatic sheet feeder and the StatusUpdateEvent is always called when a cheque is inserted regardless.  It seems to not save anything first time through, when i feed the check through again it saves it and then thats it, no more image files.
  • Friday, October 02, 2009 11:04 AM
    Answerer
     
     Answered
    Hi,

    While you should always call BeingInsertion etc. to ensure your code works with devices that require it, it sounds like your device doesn't need that because of the auto-sheet feeder, so those methods *should* be irrelevant as far as your problems go.

    It might pay you to alter the statusupdateevent to check whether or not the status event you've received is actually an image arriving. It might be you're asking for an image when you get some other kind of status event and that's messing something up... maybe. The value of e.Status should equal CheckScanner.StatusScanComplete before you actually attempt to read the image.

    I think the reason you don't get an image after the first one is that the dataevent has been disabled... in the status update event, after you retrieve the image, reset both DeviceEnabled (in case the AutoDisable property is set to true as well) and DataEventEnabled to true. That should allow the next image to be captured.

    Short of the status check, I'm not sure why you'd only get half an image though.
  • Friday, October 02, 2009 7:20 PM
    Answerer
     
     Answered
    Acutally, in addition to my previous comments I think this part of the documentation is key;

    "If the application has to retrieve the image or a cropped part of the image, it calls the RetrieveImage method. The image data is sent from the device to the service object and stored in the ImageData property. When the corresponding DataEvent event is delivered, the current image (or cropped part of the current image) may be accessed by the application reading the image file that is contained in the ImageData property."

    Looking at my own implementation, I call RetrieveImage in the statusupdate event if e.Status == CheckScanner.StatusScanComplete, then in my event handler for the DataEvent (which I have already connected to previously) I retrieve the contents of the ImageData property and then re-enable the device and data event.

    It's quite likely you're reading the buffer before it's completely full because you're not waiting for the data event before retrieving the image, which would explain the half/corrupted image, and failure to re-enable the device/data event would prevent further images being scanned.

    The CheckScanner is defintely one of the more awkward Pos .Net devices to use.

  • Sunday, October 04, 2009 4:11 AM
     
     Answered
    While not related to your specific problem, I strongly recommend that you pass the form when you create the PosExplorer in order to ensure that all events are marshaled to the UI thread.

    While I've used MICRs, I don't have any personal experience with CheckScanners.  I would just recommend that you read the UPOS spec carefully for this device category and see if you may have overlooked something.
  • Monday, October 05, 2009 8:05 AM
     
      Has Code
    Following everyone's helpful comments it now works as it should - i can insert cheques repeatedly and the image is saved correctly each time - i guess its just a case of getting everything in the right order.  I am posting the code here for reference to help anyone else out with a similar problem.  Many thanks all!

    Imports Microsoft.PointOfService
    
    Public Class Form1
    
        Private explorer As PosExplorer
        Private scannerList As DeviceCollection
        Private activeDevice As DeviceInfo
        Private WithEvents activeScanner As Microsoft.PointOfService.CheckScanner
    
        Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            activeScanner.Release()
            activeScanner.Close()
        End Sub
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            explorer = New PosExplorer(Me)
    
            scannerList = explorer.GetDevices
    
    
            For Each Device As DeviceInfo In scannerList
                If Device.ServiceObjectName = "MagTek MicrImage" Then
                    activeDevice = Device
                    Exit For
                End If
            Next
    
            activeScanner = CType(explorer.CreateInstance(activeDevice), CheckScanner)
            activeScanner.Open()
            activeScanner.Claim(1000)
            activeScanner.DeviceEnabled = True
            activeScanner.DataEventEnabled = True
            activeScanner.BeginInsertion(1000)
        End Sub
    
        Private Sub activeScanner_DataEvent(ByVal sender As Object, ByVal e As Microsoft.PointOfService.DataEventArgs) Handles activeScanner.DataEvent
            activeScanner.ImageData.Save("c:\temp\scanner-" & Now.ToString("dd-MM-yyyy-HH-mm-ss") & ".bmp")
            activeScanner.DeviceEnabled = True
            activeScanner.DataEventEnabled = True
        End Sub
    
        Private Sub activeScanner_StatusUpdateEvent(ByVal sender As Object, ByVal e As Microsoft.PointOfService.StatusUpdateEventArgs) Handles activeScanner.StatusUpdateEvent
            If e.Status = CheckScanner.StatusScanComplete Then
                activeScanner.EndInsertion()
                activeScanner.BeginRemoval(1000)
                activeScanner.EndRemoval()
                Dim crop As Integer = Microsoft.PointOfService.CheckScanner.CropAreaEntireImage
                activeScanner.RetrieveImage(crop)
            End If
        End Sub
    
    End Class