Setting scan coordinates in device options on pyinsane
<p>I use Sane's command line utility (<code>scanimage</code>) in order to scan films from the transparency unit of my scanner. Here is the command that I have been using with success:</p>

<pre><code>scanimage --device-name pixma:04A9190D \
--source 'Transparency Unit' \
--resolution "4800" \
--format "tiff" \
--mode "color" \
-l "80.6" -x "56.2" -t "25.8" -y "219.2" \
&gt; scan.tiff
</code></pre>

<p>I have decided to move this to Python code, using <code>pyinsane</code> in order to enable further integration with my image-processing workflow. This should supposedly give the following in Python code:</p>

<pre><code>import pyinsane.abstract as pyinsane
device = pyinsane.get_devices()[0]

device.options['resolution'].value = 4800
device.options['mode'].value = 'Color'
device.options['source'].value = 'Transparency Unit'

# Setting coordinates to non-integers fails
device.options['tl-y'].value = 25.8
device.options['tl-x'].value = 80.6
device.options['br-y'].value = 219.2
device.options['br-x'].value = 56.2

scan_session = device.scan(multiple=False)
try:
    while True:
        scan_session.scan.read()
except EOFError:
    pass
image = scan_session.images[0]
</code></pre>

<p>But my first trials have been unsuccessful because I can not figure out how to set the scan coordinates <code>pyinsane</code>. As you see, I have found the appropriate options, but I don't know what unit they are in. <code>scanimage</code> takes the coordinates in millimetres by default, but <code>pyinsane</code> only takes integers. I have tried using pixel coordinates to no avail. I wonder what units the coordinate parameters take, and whether I am using them in the right order.</p>

<p>pyinsane's option descriptions actually say the values are in milimeters:  </p>

<pre><code>Option: br-x
  Title: Bottom-right x
  Desc: Bottom-right x position of scan area.
  Type: &lt;class 'pyinsane.rawapi.SaneValueType'&gt; : Fixed (2)
  Unit: &lt;class 'pyinsane.rawapi.SaneUnit'&gt; : Mm (3)
  Size: 4
  Capabilities: &lt;class 'pyinsane.rawapi.SaneCapabilities'&gt; :[ Automatic, Soft_select, Soft_detect,]
  Constraint type: &lt;class 'pyinsane.rawapi.SaneConstraintType'&gt; : Range (1)
  Constraint: (0, 14160319, 0)
  Value: 20
</code></pre>

<p>But they are not! I divided the range maximum for <code>br-x</code> variable by the width of the scanning area of my scanner, and I got to the number 65536 (which is 2^16). Setting the coordinates to the millimetre value times 65536 works. Maybe these values define the number of steps of the stepper motor?</p>

<p>Also not that while scanimage interprets the <code>-x</code> and <code>-y</code> switches as width and length, and the <code>-l</code> and <code>-t</code> switches as offset, pyinsane takes bottom-right x (<code>br-x</code>), top-left y (<code>tl-y</code>), etc.</p>

python scanning sane pyinsane