It is currently Fri May 25, 2018 9:46 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 34 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Re: Image Scanning on OS-X
PostPosted: Fri May 01, 2015 8:30 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1502
Location: Germany
In the meantime I have also solved the errors with setting measurement unit and scan area ("Object is nil."). The setting of measurement unit and scan area had to be moved to the callback didSelectFunctionalUnit(). Now the modified code example below works like a charm on both Snow Leopard and Mavericks.

The only quirk remaining is that setting the scan area doesn't seem to have any effect: the resulting image MyScan.png is always a whole page although for testing I even changed the measurement unit to the (for me) more familiar centimeters and a smaller area...
Code:
#ICDeviceLocationTypeMaskLocal     = $00000100
#ICDeviceLocationTypeMaskRemote    = $0000FE00
#ICDeviceTypeMaskScanner           = $00000002
#ICDeviceTypeScanner               = $00000002

ImportC ""
  class_addMethod(Class.i, Selector.i, *Callback, Types.P-ASCII)
  class_createInstance(Class.i, ExtraBytes.i)
  class_addProtocol(Class.i, Protocol.i)
  objc_allocateClassPair(ModelClass.i, NewClassName.P-ASCII, ExtraBytes.i)
  objc_lookUpClass(ClassName.P-ASCII)
  object_setClass(ObjectToModify.i, NewClass.i)
  objc_registerClassPair(NewClass.i)
  objc_getProtocol(ProtocolName.P-ASCII)
  sel_registerName(MethodName.P-ASCII)
EndImport

ImportC "/System/Library/Frameworks/ImageCaptureCore.framework/ImageCaptureCore"
EndImport

ImportC "/System/Library/Frameworks/Quartz.framework/Quartz"
EndImport

Enumeration
  #MainWindow
  #scannerList
  #scanButton
EndEnumeration

Global Dim scanners.i(0)
Global.i delegateClass, activeScanner, selectedScanner, scanning, selectedFunctionalUnit

Procedure scan()
  Debug "initiating scan..."
  scanning = 1
  CocoaMessage(0, activeScanner, "requestScan")   
EndProcedure

ProcedureC deviceDidBecomeReady(object.i, selector.i, device.i)
  Protected FunctionalUnitArray.I
  Protected NumFunctionalUnits.I

  Debug "selected device is ready..."
 
  scanFolder = CocoaMessage(0, 0, "NSURL fileURLWithPath:$", @"/Users/Shardik/Scans/")
  scanFile = CocoaMessage(0, 0, "NSString stringWithString:$", @"MyScan")
 
  ; CocoaMessage(0, device, "requestSelectFunctionalUnit:", 0)   ;0 for flatbed type
  CocoaMessage(0, device, "requestSelectFunctionalUnit:", 3)   ;3 for document feeder type
  CocoaMessage(0, activeScanner, "setTransferMode:", 0)        ;0 for file-mode
  CocoaMessage(0, activeScanner, "setDownloadsDirectory:", scanFolder)
  CocoaMessage(0, activeScanner, "setDocumentName:$", @"MyScan")
  CocoaMessage(0, activeScanner, "setDocumentUTI:$", @"public.png")

  FunctionalUnitArray = CocoaMessage(0, device, "availableFunctionalUnitTypes")

  If FunctionalUnitArray
    NumFunctionalUnits = CocoaMessage(0, FunctionalUnitArray, "count")

    If NumFunctionalUnits
      Debug "Functional unit types:"

      For i = 0 To NumFunctionalUnits - 1
        Select CocoaMessage(0, CocoaMessage(0, FunctionalUnitArray,
          "objectAtIndex:", i), "integerValue")
          Case 0
            Debug "- Flatbed"
          Case 1
            Debug "- Positive transparency"
          Case 2
            Debug "- Negative transparency"
          Case 3
            Debug "- Document feeder"
        EndSelect   
      Next i
    EndIf
  EndIf
EndProcedure

ProcedureC didAddDevice(object.i, selector.i, deviceBrowser.i, addedDevice.i, moreComing.i)
  Debug "device found and added..."
 
  deviceType.i = CocoaMessage(0, addedDevice, "type")   
  deviceName.s = PeekS(CocoaMessage(0, CocoaMessage(0, addedDevice, "name"), "UTF8String"), -1, #PB_UTF8)
 
  If moreComing = #NO And (deviceType & #ICDeviceTypeMaskScanner) = #ICDeviceTypeScanner
    newIndex = ArraySize(scanners()) + 1
    ReDim scanners(newIndex)
    scanners(newIndex) = addedDevice
    AddGadgetItem(#scannerList, -1, deviceName)
    CocoaMessage(0, addedDevice, "setDelegate:",
                 class_createInstance(delegateClass, 0))   ;PureBasic app controls the scanner
  EndIf
EndProcedure

ProcedureC didRemoveDevice(object.i, selector.i, removedDevice.i)
  Debug "device removed"
EndProcedure

ProcedureC didRemoveDeviceInBrowser(object.i, selector.i, deviceBrowser.i, removedDevice.i, moreGoing.i)
  Debug "device removed in browser..."
  CocoaMessage(0, removedDevice, "requestCloseSession")
  CocoaMessage(0, removedDevice, "setDelegate:", 0)
  RemoveGadgetItem(#scannerList, selectedScanner - 1)
  ReDim scanners(ArraySize(scanners()) - 1)

  If activeScanner = removedDevice
    activeScanner = 0
  EndIf
EndProcedure

ProcedureC didOpenSessionWithError(object.i, selector.i, device.i, error.i)
  Debug "session opened... errors: " + Str(error)
EndProcedure

ProcedureC didCloseSessionWithError(object.i, selector.i, device.i, error.i)
  Debug "session closed... errors: " + Str(error)
EndProcedure

ProcedureC didSelectFunctionalUnit(object.i, selector.i, scannerDevice.i, functionalUnit.i, error.i)
  Protected scanArea.NSRect

  If error = 0
    If functionalUnit <> 0
      Debug "functional unit selected: " + functionalUnit
      CocoaMessage(0, functionalUnit, "setMeasurementUnit:", 0)
      Debug "MeasurementUnit set to Inches"

      With scanArea
        \origin\x = 0
        \origin\y = 0
        \size\width = 10
        \size\height = 10
      EndWith
 
      CocoaMessage(0, functionalUnit, "setScanArea:@", @scanArea)
      CocoaMessage(@scanArea, functionalUnit, "scanArea")
      Debug "scanArea set to (" + Str(scanArea\origin\x) + "," +
        Str(scanArea\origin\y) + ")-(" +
        Str(scanArea\origin\x + scanArea\size\width) + "," +
        Str(scanArea\origin\y + scanArea\size\height) + ")"
    EndIf
  Else
    Debug "functional unit selected... errors: " + Str(error)
  EndIf
EndProcedure

ProcedureC didReceiveStatusInformation(object.i, selector.i, device.i, StatusDictionary.i)
  Debug "receiving status info..."

  If StatusDictionary
    Debug PeekS(CocoaMessage(0, CocoaMessage(0, StatusDictionary,
      "valueForKey:$", @"ICLocalizedStatusNotificationKey"), "UTF8String"),
      -1, #PB_UTF8)
  EndIf
EndProcedure

ProcedureC didScanToURL(object.i, selector.i, scannerDevice.i, URL.i, *data)
  Debug "scanned to " +
    PeekS(CocoaMessage(0, CocoaMessage(0, URL, "absoluteString"), "UTF8String"),
    -1, #PB_UTF8)
  scanning = 0
EndProcedure

ProcedureC didCompleteScanWithError(object.i, selector.i, scannerDevice.i, error.i)
  Debug "scan completed... errors: " + Str(error)
  scanning = 0
EndProcedure
 
ProcedureC didEncounterError(object.i, selector.i, device.i, error.i)
  Debug "encountered error: " + Str(error)
  scanning = 0
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, 100, 100, 800, 500, "Scanner Application", wFlags)
ListViewGadget(#scannerList, 0, 0, 200, 500)
ButtonGadget(#scanButton, 220, 10, 100, 30, "SCAN")
SetGadgetColor(#scannerList, #PB_Gadget_BackColor, RGB(200, 200, 255))

deviceBrowser = CocoaMessage(0, 0, "ICDeviceBrowser new")

delegateClass = objc_allocateClassPair(objc_lookUpClass("NSObject"), "PB_Delegate", 0)   ;PureBasic app class

class_addMethod(delegateClass,
                sel_registerName("didRemoveDevice:"), @didRemoveDevice(), "v@:@")
class_addMethod(delegateClass,
                sel_registerName("deviceDidBecomeReady:"), @deviceDidBecomeReady(), "v@:@")
class_addMethod(delegateClass,
                sel_registerName("device:didEncounterError:"), @didEncounterError(), "v@:@@")
class_addMethod(delegateClass,
                sel_registerName("device:didOpenSessionWithError:"), @didOpenSessionWithError(), "v@:@@")
class_addMethod(delegateClass,
                sel_registerName("device:didCloseSessionWithError:"), @didCloseSessionWithError(), "v@:@@")
class_addMethod(delegateClass,
                sel_registerName("device:didReceiveStatusInformation:"), @didReceiveStatusInformation(), "v@:@@")
class_addMethod(delegateClass,
                sel_registerName("deviceBrowser:didAddDevice:moreComing:"), @didAddDevice(), "v@:@@@")
class_addMethod(delegateClass,
                sel_registerName("deviceBrowser:didRemoveDevice:moreGoing:"), @didRemoveDeviceInBrowser(), "v@:@@@")
class_addMethod(delegateClass,
                sel_registerName("scannerDevice:didScanToURL:data:"), @didScanToURL(), "v@:@@@")
class_addMethod(delegateClass,
                sel_registerName("scannerDevice:didCompleteScanWithError:"), @didCompleteScanWithError(), "v@:@@")
class_addMethod(delegateClass,
                sel_registerName("scannerDevice:didSelectFunctionalUnit:error:"), @didSelectFunctionalUnit(), "v@:@@@")

objc_registerClassPair(delegateClass)

CocoaMessage(0, deviceBrowser, "setDelegate:", class_createInstance(delegateClass, 0))   ;PureBasic app controls the browser
CocoaMessage(0, deviceBrowser, "setBrowsedDeviceTypeMask:", #ICDeviceLocationTypeMaskLocal |
                                                            #ICDeviceLocationTypeMaskRemote |
                                                            #ICDeviceTypeMaskScanner)
CocoaMessage(0, deviceBrowser, "start")

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      appQuit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #scanButton
          scan()
        Case #scannerList
          Select EventType()
            Case #PB_EventType_LeftDoubleClick
              selectedScanner = GetGadgetState(#scannerList) + 1
              activeScanner = scanners(selectedScanner)
              CocoaMessage(0, activeScanner, "requestOpenSession")
          EndSelect
      EndSelect
  EndSelect
Until appQuit = 1

If activeScanner
  CocoaMessage(0, activeScanner, "release")
EndIf

CocoaMessage(0, deviceBrowser, "stop")
; CocoaMessage(0, deviceBrowser, "release")

Update 1: I have modified the didReceiveStatusInformation() callback to also display the status which is contained in the status dictionary passed as a parameter to this callback.

Update 2: I have modified the deviceDidBecomeReady() callback to also display the available functional unit types.

Update 3: To prevent an invalid memory access (IMA) when closing the program after the scanner's power button had already been switched off, I have added
Code:
  If activeScanner = removedDevice
    activeScanner = 0
  EndIf
in procedure didRemoveDeviceInBrowser() and changed
Code:
CocoaMessage(0, activeScanner, "release")
to
Code:
If activeScanner
  CocoaMessage(0, activeScanner, "release")
EndIf
at the end of the code example. I have tested this code successfully with PB 5.44 x86 in both ASCII and Unicode mode on MacOS 10.6.8 (Snow Leopard) and with PB 5.44 x86 and x64 in both ASCII and Unicode mode on MacOS 10.7.5 (Lion).


Last edited by Shardik on Wed Dec 28, 2016 9:30 pm, edited 5 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Fri May 01, 2015 11:01 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 2067
Location: Singapore
Image
Shardik wrote:
...I have also solved the errors with setting measurement unit and scan area ("Object is nil."). The setting of measurement unit and scan area had to be moved to the callback didSelectFunctionalUnit()...
You're a true genius. But more importantly, how did you figure that out? I didn't find that anywhere in the documentation or in any of the tonnes of examples that I had pored over.

Shardik wrote:
The only quirk remaining is that setting the scan area doesn't seem to have any effect: the resulting image MyScan.png is always a whole page although...
No; it works! I've tested it with both inches and centimetres settings, and it scans precisely the given area. Amazing!

The reason that you're not getting it is because the Brother ADS-2100 that you're using is a document-feeder type, which ignores the scan area setting.

This is wonderful! We're really getting this thing to work.

I bow to you, GURU.
Image

But I still await updates on reading the availableFunctionalUnitTypes property array, as well as the status message returned by the didReceiveStatusInformation() method. :lol:

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Sat May 02, 2015 7:33 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1502
Location: Germany
TI-994A,

thank you very much for your kind words. But unfortunately you are massively exaggerating about my capabilities. All PB Mac programmers can't be grateful enough to Wilbert who is a true genius, a Cocoa framework magician and assembler guru. Without Wilbert's incredible work and Fred's help on the former oMsg() library which finally became the native CocoaMessage() function and the multitude of Wilbert's excellent code examples my help for your scanning program would not have been possible. And I bet that if Wilbert would have had a proper scanner at home, he would have had worked out a scanning solution for you in minutes while I needed many hours... :lol:

TI-994A wrote:
The reason that you're not getting it is because the Brother ADS-2100 that you're using is a document-feeder type, which ignores the scan area setting.
That's another proof of my silliness... :oops:
Of course it's technically not possible to use a sheet feeder type scanner for scanning only a given area...

TI-994A wrote:
But I still await updates on reading the availableFunctionalUnitTypes property array, as well as the status message returned by the didReceiveStatusInformation() method. :lol:
I have modified the didReceiveStatusInformation() callback in my last code posting to also display the status contained in the status dictionary and the deviceDidBecomeReady() callback to report the available functional unit types. :wink:


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Sat May 02, 2015 11:24 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 2067
Location: Singapore
SHARDIK! YOU DID IT MAN!

Image

Shardik wrote:
...you are massively exaggerating about my capabilities. All PB Mac programmers can't be grateful enough to Wilbert who is a true genius ... and the multitude of Wilbert's excellent code examples...
Yes; I too have studied his many code examples intently, and yours too, and would not have imagined to approach this topic without them. Like you said, if only he had a scanner.

But you went out of your way to help me, and to borrow a quote from John McClane (Bruce Willis, Die Hard 4.0), "That's what makes you that guy."

Bottom-line: I can't thank you enough. Danke Vielmals!

Just FYI, in the didSelectFunctionalUnit() method, I was able to get the selected functional unit type with this CocoaMessage():
Code:
CocoaMessage(0, functionalUnit, "type")
Shardik wrote:
...the modified code example below works like a charm on both Snow Leopard and Mavericks.
It should also be noted that all my tests were done on Mac OSX Lion v10.7.5. So, it clearly works on Snow Leopard, Lion, and Mavericks :D

I truly believe that this is one for the PureBasic books, and warrants an addition into the Mac OSX Tricks 'n' Tips section. Please do the honours, Shardik; this is definitely your baby. :wink:

Thanks again, and hope you have a wonderful weekend. I know I will! :lol:

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Sat May 02, 2015 11:48 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3112
Location: Netherlands
TI-994A wrote:
I truly believe that this is one for the PureBasic books, and warrants an addition into the Mac OSX Tricks 'n' Tips section.

I added a link to the source in the first post of that thread :wink:
It's indeed a very nice contribution :D

_________________
MacOS 10.13 High Sierra, PB 5.60 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Sat May 02, 2015 1:43 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2011 3:47 am
Posts: 2067
Location: Singapore
wilbert wrote:
I added a link to the source in the first post of that thread :wink:
It's indeed a very nice contribution :D
Hi wilbert. I just saw the new link in the Mac OSX Tricks 'n' Tips section; a very nice contribution indeed. Thank you.

And like Shardik said, it wouldn't have been possible without your contributions. I'd have to say that the techniques implemented in this example were most certainly derived from the many API examples that you, and the other OSX gurus, had posted in these forums over the years. Truly educational stuff.

So, dank u wel. :D

I just realised that it took 36 days to get this thing off the ground. But it is well worth every minute! :lol:

_________________
Texas Instruments 99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Sat May 02, 2015 2:32 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3112
Location: Netherlands
TI-994A wrote:
And like Shardik said, it wouldn't have been possible without your contributions. I'd have to say that the techniques implemented in this example were most certainly derived from the many API examples that you, and the other OSX gurus, had posted in these forums over the years. Truly educational stuff.

We all contribute :)

It's just nice to see the steps that have been made since PureBasic OSX made the move from Carbon to Cocoa. 8)

_________________
MacOS 10.13 High Sierra, PB 5.60 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Fri Dec 23, 2016 7:05 am 
Offline
Enthusiast
Enthusiast

Joined: Tue Jun 21, 2011 10:39 am
Posts: 326
This example worked before but after I upgraded to a newer Xcode I get scan errors. The os is the same version and I tried it on older versions of PB but no luck. The only change on my Mac is Xcode 4.6. Can it be the problem? :?


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Wed Dec 28, 2016 10:18 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1502
Location: Germany
coder14 wrote:
This example worked before but after I upgraded to a newer Xcode I get scan errors. The os is the same version and I tried it on older versions of PB but no luck. The only change on my Mac is Xcode 4.6. Can it be the problem? :?

To which exact version of Xcode did you upgrade? After having updated the most recent code example I can't reproduce any problems on MacOS 10.7.5 (Lion) with Xcode 4.6.3 using PB 5.44 x86 and x64 in both ASCII and Unicode mode. I also tested the code example successfully on MacOS 10.6.8 with PB 5.44 x86 in ASCII and Unicode mode.

You should also take a look into my tips in your other thread.


Top
 Profile  
Reply with quote  
 Post subject: Re: Image Scanning on OS-X
PostPosted: Thu Dec 29, 2016 7:15 am 
Offline
Enthusiast
Enthusiast

Joined: Tue Jun 21, 2011 10:39 am
Posts: 326
Shardik wrote:
coder14 wrote:
This example worked before but after I upgraded to a newer Xcode I get scan errors. The os is the same version and I tried it on older versions of PB but no luck. The only change on my Mac is Xcode 4.6. Can it be the problem? :?

To which exact version of Xcode did you upgrade? After having updated the most recent code example I can't reproduce any problems on MacOS 10.7.5 (Lion) with Xcode 4.6.3 using PB 5.44 x86 and x64 in both ASCII and Unicode mode. I also tested the code example successfully on MacOS 10.6.8 with PB 5.44 x86 in ASCII and Unicode mode.

You should also take a look into my tips in your other thread.

I think that it worked for you because your scanner is ADF by default. Mine is a flatbed and the scan failed because the ADF was selected in the "deviceDidBecomeReady" proc. It works now. Thank you.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 34 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye