Python library to access and use image scanners.
Support for:
- Sane (Scanners on GNU/Linux, *BSD, MacOSX, etc)
- WIA 2 (Windows Image Acquisition ; Scanners on Microsoft Windows >= Vista)
It supports:
- Flatbed
- Automatic Document Feeder
- While scanning, can provide chunks of the image for on-the-fly preview (see Paperwork for instance)
- Python 3.x
Not tested but should work too:
- Handheld image scanners
On all platforms:
- Pillow (if the abstraction layer is used)
Platform specific:
- GNU/Linux, *BSD, MacOSX, etc: libsane
# recommanded to get the latest stable version
sudo pip install pyinsane2
or
# for the development version
git clone https://github.com/jflesch/pyinsane.git
cd pyinsane
sudo python3 ./setup.py install
python3 ./setup.py nosetests --tests tests.tests_saneapi # GNU/Linux
python3 ./setup.py nosetests --tests tests.tests_wiaapi # Windows
python3 ./setup.py nosetests --tests tests.tests_abstract
Tests require at least one scanner with a flatbed and an ADF (Automatic Document Feeder).
If possible, they should be run with at least 2 scanners connected. The first that appear in "scanimage -L" must be the one with the ADF.
For reference, my current setup is:
- HP Officejet 4500 G510g (Flatbed + ADF)
- HP Deskjet 2050 J510 series (Flatbed)
import pyinsane2
pyinsane2.init()
try:
devices = pyinsane2.get_devices()
assert(len(devices) > 0)
device = devices[0]
print("I'm going to use the following scanner: %s" % (str(device)))
scanner_id = device.name
finally:
pyinsane2.exit()
or if you already know its name/id:
import pyinsane2
pyinsane2.init()
try:
device = pyinsane2.Scanner(name="somethingsomething")
print("I'm going to use the following scanner: %s" % (str(device)))
finally:
pyinsane2.exit()
import pyinsane2
pyinsane2.init()
try:
devices = pyinsane2.get_devices()
assert(len(devices) > 0)
device = devices[0]
print("I'm going to use the following scanner: %s" % (str(device)))
pyinsane2.set_scanner_opt(device, 'resolution', [300])
# Beware: Some scanners have "Lineart" or "Gray" as default mode
# better set the mode everytime
pyinsane2.set_scanner_opt(device, 'mode', ['Color'])
# Beware: by default, some scanners only scan part of the area
# they could scan.
pyinsane2.maximize_scan_area(device)
scan_session = device.scan(multiple=False)
try:
while True:
scan_session.scan.read()
except EOFError:
pass
image = scan_session.images[-1]
finally:
pyinsane2.exit()
See examples/scan.py for a more complete example.
import pyinsane2
pyinsane2.init()
try:
devices = pyinsane2.get_devices()
assert(len(devices) > 0)
device = devices[0]
print("I'm going to use the following scanner: %s" % (str(device)))
try:
pyinsane2.set_scanner_opt(device, 'source', ['ADF', 'Feeder'])
except PyinsaneException:
print("No document feeder found")
return
# Beware: Some scanners have "Lineart" or "Gray" as default mode
# better set the mode everytime
pyinsane2.set_scanner_opt(device, 'mode', ['Color'])
# Beware: by default, some scanners only scan part of the area
# they could scan.
pyinsane2.maximize_scan_area(device)
scan_session = device.scan(multiple=True)
try:
while True:
try:
scan_session.scan.read()
except EOFError:
print ("Got a page ! (current number of pages read: %d)"
% (len(scan_session.images)))
except StopIteration:
print("Document feeder is now empty. Got %d pages"
% len(scan_session.images))
for idx in range(0, len(scan_session.images)):
image = scan_session.images[idx]
finally:
pyinsane2.exit()
The options available depends on the backend and on the specific driver used.
The WIA implementation emulates common Sane options ('tl-x', 'br-x', 'tl-y', 'br-y', 'color', 'mode', 'source'). So you should use Sane options by default.
See the Sane documentation for the most common options.
Beware options casing can change between WIA and Sane implementation !
You should use pyinsane2.set_scanner_opt()
whenever possible.
You can access the option values with:
device.options['option_name'].value
You can set the option values with:
device.options['option_name'].value = new_value
# or use the helper:
pyinsane2.set_scanner_opt(
device, 'option_name',
['possible_new_value_1', 'possible_new_value_2']
)
You can get the constraint (accepted values) with:
device.options['option_name'].constraint
Constraints are usually:
- None : unknown constraints / no constraint
- tuple :
(min_value, max_value)
- list : possible values (Ex:
['Flatbed', 'Feeder']
or[75, 150, 300]
)
When using the Sane API as is, some issues with some Sane drivers can become obvious in complex programs (uninitialized memory bytes, segfault, etc). You can get corrupted images or even crash your program.
This module works around issues like the following one by using a dedicated process for scanning:
--> |
(see this comment for details)
When pyinsane2.init()
is called, it will create 2 Unix pipes (FIFO)
in your temporary directory and a dedicated process. To avoid forking
other file descriptors from your program, you should initialize pyinsane2
as soon as possible.
Building requires nothing except Python. Libsane is loaded dynamically using ctypes
.
Build requires:
- Either Python 3.4 + Windows SDK 7.1 (Visual C++ 2010) + Windows DDK (aka WDK)
- Or Python 3.5 + Visual C++ 2016 (included in Visual Studio 2016)
(see the Python wiki for more information)
WIA provides one WiaItem2 by possible source (Flatbed, ADF, etc). And each of these items has its own properties.
To make the model consistent with Sane, all the properties have been merged in the same list. When you update a property specific to sources, it is updated on all the WIAItem2. The update is considered successful if it worked at least on one.
Some properties are emulated to make the API behavior consistent with the Sane implementation. The WIA implementation emulates common Sane options ('tl-x', 'br-x', 'tl-y', 'br-y', 'color', 'mode', 'source'). If your program must be cross-platform, you are strongly advised to use these emulated options instead of the WIA ones ('xpos', 'ypos', 'xextent', 'yextent', etc).
The folder 'examples' contains more detailed examples. For instance, examples/scan.py shows how to get pieces of a scan as it goes.
To run one of these scripts, run:
python -m examples.[script] [args]
For instance
python -m examples.scan toto.png
GPL v3 2012-2016(c) Jerome Flesch ([email protected])