mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-11 04:07:21 +03:00
Merge pull request #962 from hugovk/sane
Remove Sane directory now it has its own repo
This commit is contained in:
commit
ffa8852ac0
34
Sane/CHANGES
34
Sane/CHANGES
|
@ -1,34 +0,0 @@
|
|||
|
||||
from V1.0 to V2.0
|
||||
|
||||
_sane.c:
|
||||
- Values for option constraints are correctly translated to floats
|
||||
if value type is TYPE_FIXED for SANE_CONSTRAINT_RANGE and
|
||||
SANE_CONSTRAINT_WORD_LIST
|
||||
- added constants INFO_INEXACT, INFO_RELOAD_OPTIONS,
|
||||
INFO_RELOAD_PARAMS (possible return values of set_option())
|
||||
to module dictionnary.
|
||||
- removed additional return variable 'i' from SaneDev_get_option(),
|
||||
because it is only set when SANE_ACTION_SET_VALUE is used.
|
||||
- scanDev.get_parameters() now returns the scanner mode as 'format',
|
||||
no more the typical PIL codes. So 'L' became 'gray', 'RGB' is now
|
||||
'color', 'R' is 'red', 'G' is 'green', 'B' is 'red'. This matches
|
||||
the way scanDev.mode is set.
|
||||
This should be the only incompatibility vs. version 1.0.
|
||||
|
||||
sane.py
|
||||
- ScanDev got new method __load_option_dict() called from __init__()
|
||||
and from __setattr__() if backend reported that the frontend should
|
||||
reload the options.
|
||||
- Nice human-readable __repr__() method added for class Option
|
||||
- if __setattr__ (i.e. set_option) reports that all other options
|
||||
have to be reloaded due to a change in the backend then they are reloaded.
|
||||
- due to the change in SaneDev_get_option() only the 'value' is
|
||||
returned from get_option().
|
||||
- in __setattr__ integer values are automatically converted to floats
|
||||
if SANE backend expects SANE_FIXED (i.e. fix-point float)
|
||||
- The scanner options can now directly be accessed via scanDev[optionName]
|
||||
instead scanDev.opt[optionName]. (The old way still works).
|
||||
|
||||
V1.0:
|
||||
A.M. Kuchling's original pysane package.
|
|
@ -1,22 +0,0 @@
|
|||
Python SANE module V1.1 (30 Sep. 2004)
|
||||
================================================================================
|
||||
|
||||
The SANE module provides an interface to the SANE scanner and frame
|
||||
grabber interface for Linux. This module was contributed by Andrew
|
||||
Kuchling and is extended and currently maintained by Ralph Heinkel
|
||||
(rheinkel-at-email.de). If you write to me please make sure to have the
|
||||
word 'SANE' or 'sane' in the subject of your mail, otherwise it might
|
||||
be classified as spam in the future.
|
||||
|
||||
|
||||
To build this module, type (in the Sane directory)::
|
||||
|
||||
python setup.py build
|
||||
|
||||
In order to install the module type::
|
||||
|
||||
python setup.py install
|
||||
|
||||
|
||||
For some basic documentation please look at the file sanedoc.txt
|
||||
The two demo_*.py scripts give basic examples on how to use the software.
|
1405
Sane/_sane.c
1405
Sane/_sane.c
File diff suppressed because it is too large
Load Diff
|
@ -1,41 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Shows how to scan a 16 bit grayscale image into a numarray object
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
# Get the path set up to find PIL modules if not installed yet:
|
||||
import sys ; sys.path.append('../PIL')
|
||||
|
||||
from numarray import *
|
||||
import sane
|
||||
import Image
|
||||
|
||||
def toImage(arr):
|
||||
if arr.type().bytes == 1:
|
||||
# need to swap coordinates btw array and image (with [::-1])
|
||||
im = Image.frombytes('L', arr.shape[::-1], arr.tostring())
|
||||
else:
|
||||
arr_c = arr - arr.min()
|
||||
arr_c *= (255./arr_c.max())
|
||||
arr = arr_c.astype(UInt8)
|
||||
# need to swap coordinates btw array and image (with [::-1])
|
||||
im = Image.frombytes('L', arr.shape[::-1], arr.tostring())
|
||||
return im
|
||||
|
||||
print('SANE version:', sane.init())
|
||||
print('Available devices=', sane.get_devices())
|
||||
|
||||
s = sane.open(sane.get_devices()[0][0])
|
||||
|
||||
# Set scan parameters
|
||||
s.mode = 'gray'
|
||||
s.br_x=320. ; s.br_y=240.
|
||||
|
||||
print('Device parameters:', s.get_parameters())
|
||||
|
||||
s.depth=16
|
||||
arr16 = s.arr_scan()
|
||||
toImage(arr16).show()
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Shows how to scan a color image into a PIL rgb-image
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
# Get the path set up to find PIL modules if not installed yet:
|
||||
import sys ; sys.path.append('../PIL')
|
||||
|
||||
import sane
|
||||
print('SANE version:', sane.init())
|
||||
print('Available devices=', sane.get_devices())
|
||||
|
||||
s = sane.open(sane.get_devices()[0][0])
|
||||
|
||||
s.mode = 'color'
|
||||
s.br_x=320. ; s.br_y=240.
|
||||
|
||||
print('Device parameters:', s.get_parameters())
|
||||
|
||||
# Initiate the scan
|
||||
s.start()
|
||||
|
||||
# Get an Image object
|
||||
# (For my B&W QuickCam, this is a grey-scale image. Other scanning devices
|
||||
# may return a
|
||||
im=s.snap()
|
||||
|
||||
# Write the image out as a GIF file
|
||||
#im.save('foo.gif')
|
||||
|
||||
# The show method() simply saves the image to a temporary file and calls "xv".
|
||||
im.show()
|
288
Sane/sane.py
288
Sane/sane.py
|
@ -1,288 +0,0 @@
|
|||
# sane.py
|
||||
#
|
||||
# Python wrapper on top of the _sane module, which is in turn a very
|
||||
# thin wrapper on top of the SANE library. For a complete understanding
|
||||
# of SANE, consult the documentation at the SANE home page:
|
||||
# http://www.mostang.com/sane/ .
|
||||
|
||||
__version__ = '2.0'
|
||||
__author__ = ['Andrew Kuchling', 'Ralph Heinkel']
|
||||
|
||||
from PIL import Image
|
||||
|
||||
import _sane
|
||||
from _sane import *
|
||||
|
||||
TYPE_STR = { TYPE_BOOL: "TYPE_BOOL", TYPE_INT: "TYPE_INT",
|
||||
TYPE_FIXED: "TYPE_FIXED", TYPE_STRING: "TYPE_STRING",
|
||||
TYPE_BUTTON: "TYPE_BUTTON", TYPE_GROUP: "TYPE_GROUP" }
|
||||
|
||||
UNIT_STR = { UNIT_NONE: "UNIT_NONE",
|
||||
UNIT_PIXEL: "UNIT_PIXEL",
|
||||
UNIT_BIT: "UNIT_BIT",
|
||||
UNIT_MM: "UNIT_MM",
|
||||
UNIT_DPI: "UNIT_DPI",
|
||||
UNIT_PERCENT: "UNIT_PERCENT",
|
||||
UNIT_MICROSECOND: "UNIT_MICROSECOND" }
|
||||
|
||||
|
||||
class Option:
|
||||
"""Class representing a SANE option.
|
||||
Attributes:
|
||||
index -- number from 0 to n, giving the option number
|
||||
name -- a string uniquely identifying the option
|
||||
title -- single-line string containing a title for the option
|
||||
desc -- a long string describing the option; useful as a help message
|
||||
type -- type of this option. Possible values: TYPE_BOOL,
|
||||
TYPE_INT, TYPE_STRING, and so forth.
|
||||
unit -- units of this option. Possible values: UNIT_NONE,
|
||||
UNIT_PIXEL, etc.
|
||||
size -- size of the value in bytes
|
||||
cap -- capabilities available; CAP_EMULATED, CAP_SOFT_SELECT, etc.
|
||||
constraint -- constraint on values. Possible values:
|
||||
None : No constraint
|
||||
(min,max,step) Integer values, from min to max, stepping by
|
||||
list of integers or strings: only the listed values are allowed
|
||||
"""
|
||||
|
||||
def __init__(self, args, scanDev):
|
||||
self.scanDev = scanDev # needed to get current value of this option
|
||||
self.index, self.name = args[0], args[1]
|
||||
self.title, self.desc = args[2], args[3]
|
||||
self.type, self.unit = args[4], args[5]
|
||||
self.size, self.cap = args[6], args[7]
|
||||
self.constraint = args[8]
|
||||
def f(x):
|
||||
if x=='-': return '_'
|
||||
else: return x
|
||||
if not isinstance(self.name, str): self.py_name=str(self.name)
|
||||
else: self.py_name=''.join(map(f, self.name))
|
||||
|
||||
def is_active(self):
|
||||
return _sane.OPTION_IS_ACTIVE(self.cap)
|
||||
def is_settable(self):
|
||||
return _sane.OPTION_IS_SETTABLE(self.cap)
|
||||
def __repr__(self):
|
||||
if self.is_settable():
|
||||
settable = 'yes'
|
||||
else:
|
||||
settable = 'no'
|
||||
if self.is_active():
|
||||
active = 'yes'
|
||||
curValue = repr(getattr(self.scanDev, self.py_name))
|
||||
else:
|
||||
active = 'no'
|
||||
curValue = '<not available, inactive option>'
|
||||
s = """\nName: %s
|
||||
Cur value: %s
|
||||
Index: %d
|
||||
Title: %s
|
||||
Desc: %s
|
||||
Type: %s
|
||||
Unit: %s
|
||||
Constr: %s
|
||||
active: %s
|
||||
settable: %s\n""" % (self.py_name, curValue,
|
||||
self.index, self.title, self.desc,
|
||||
TYPE_STR[self.type], UNIT_STR[self.unit],
|
||||
repr(self.constraint), active, settable)
|
||||
return s
|
||||
|
||||
|
||||
class _SaneIterator:
|
||||
""" intended for ADF scans.
|
||||
"""
|
||||
|
||||
def __init__(self, device):
|
||||
self.device = device
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __del__(self):
|
||||
self.device.cancel()
|
||||
|
||||
def next(self):
|
||||
try:
|
||||
self.device.start()
|
||||
except error as v:
|
||||
if v == 'Document feeder out of documents':
|
||||
raise StopIteration
|
||||
else:
|
||||
raise
|
||||
return self.device.snap(1)
|
||||
|
||||
|
||||
|
||||
class SaneDev:
|
||||
"""Class representing a SANE device.
|
||||
Methods:
|
||||
start() -- initiate a scan, using the current settings
|
||||
snap() -- snap a picture, returning an Image object
|
||||
arr_snap() -- snap a picture, returning a numarray object
|
||||
cancel() -- cancel an in-progress scanning operation
|
||||
fileno() -- return the file descriptor for the scanner (handy for select)
|
||||
|
||||
Also available, but rather low-level:
|
||||
get_parameters() -- get the current parameter settings of the device
|
||||
get_options() -- return a list of tuples describing all the options.
|
||||
|
||||
Attributes:
|
||||
optlist -- list of option names
|
||||
|
||||
You can also access an option name to retrieve its value, and to
|
||||
set it. For example, if one option has a .name attribute of
|
||||
imagemode, and scanner is a SaneDev object, you can do:
|
||||
print scanner.imagemode
|
||||
scanner.imagemode = 'Full frame'
|
||||
scanner.['imagemode'] returns the corresponding Option object.
|
||||
"""
|
||||
def __init__(self, devname):
|
||||
d=self.__dict__
|
||||
d['sane_signature'] = self._getSaneSignature(devname)
|
||||
d['scanner_model'] = d['sane_signature'][1:3]
|
||||
d['dev'] = _sane._open(devname)
|
||||
self.__load_option_dict()
|
||||
|
||||
def _getSaneSignature(self, devname):
|
||||
devices = get_devices()
|
||||
if not devices:
|
||||
raise RuntimeError('no scanner available')
|
||||
for dev in devices:
|
||||
if devname == dev[0]:
|
||||
return dev
|
||||
raise RuntimeError('no such scan device "%s"' % devname)
|
||||
|
||||
def __load_option_dict(self):
|
||||
d=self.__dict__
|
||||
d['opt']={}
|
||||
optlist=d['dev'].get_options()
|
||||
for t in optlist:
|
||||
o=Option(t, self)
|
||||
if o.type!=TYPE_GROUP:
|
||||
d['opt'][o.py_name]=o
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
dev=self.__dict__['dev']
|
||||
optdict=self.__dict__['opt']
|
||||
if key not in optdict:
|
||||
self.__dict__[key]=value ; return
|
||||
opt=optdict[key]
|
||||
if opt.type==TYPE_GROUP:
|
||||
raise AttributeError("Groups can't be set: "+key)
|
||||
if not _sane.OPTION_IS_ACTIVE(opt.cap):
|
||||
raise AttributeError('Inactive option: '+key)
|
||||
if not _sane.OPTION_IS_SETTABLE(opt.cap):
|
||||
raise AttributeError("Option can't be set by software: "+key)
|
||||
if isinstance(value, int) and opt.type == TYPE_FIXED:
|
||||
# avoid annoying errors of backend if int is given instead float:
|
||||
value = float(value)
|
||||
self.last_opt = dev.set_option(opt.index, value)
|
||||
# do binary AND to find if we have to reload options:
|
||||
if self.last_opt & INFO_RELOAD_OPTIONS:
|
||||
self.__load_option_dict()
|
||||
|
||||
def __getattr__(self, key):
|
||||
dev=self.__dict__['dev']
|
||||
optdict=self.__dict__['opt']
|
||||
if key=='optlist':
|
||||
return list(self.opt.keys())
|
||||
if key=='area':
|
||||
return (self.tl_x, self.tl_y),(self.br_x, self.br_y)
|
||||
if key not in optdict:
|
||||
raise AttributeError('No such attribute: '+key)
|
||||
opt=optdict[key]
|
||||
if opt.type==TYPE_BUTTON:
|
||||
raise AttributeError("Buttons don't have values: "+key)
|
||||
if opt.type==TYPE_GROUP:
|
||||
raise AttributeError("Groups don't have values: "+key)
|
||||
if not _sane.OPTION_IS_ACTIVE(opt.cap):
|
||||
raise AttributeError('Inactive option: '+key)
|
||||
value = dev.get_option(opt.index)
|
||||
return value
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.opt[key]
|
||||
|
||||
def get_parameters(self):
|
||||
"""Return a 5-tuple holding all the current device settings:
|
||||
(format, last_frame, (pixels_per_line, lines), depth, bytes_per_line)
|
||||
|
||||
- format is one of 'L' (grey), 'RGB', 'R' (red), 'G' (green), 'B' (blue).
|
||||
- last_frame [bool] indicates if this is the last frame of a multi frame image
|
||||
- (pixels_per_line, lines) specifies the size of the scanned image (x,y)
|
||||
- lines denotes the number of scanlines per frame
|
||||
- depth gives number of pixels per sample
|
||||
"""
|
||||
return self.dev.get_parameters()
|
||||
|
||||
def get_options(self):
|
||||
"Return a list of tuples describing all the available options"
|
||||
return self.dev.get_options()
|
||||
|
||||
def start(self):
|
||||
"Initiate a scanning operation"
|
||||
return self.dev.start()
|
||||
|
||||
def cancel(self):
|
||||
"Cancel an in-progress scanning operation"
|
||||
return self.dev.cancel()
|
||||
|
||||
def snap(self, no_cancel=0):
|
||||
"Snap a picture, returning a PIL image object with the results"
|
||||
(mode, last_frame,
|
||||
(xsize, ysize), depth, bytes_per_line) = self.get_parameters()
|
||||
if mode in ['gray', 'red', 'green', 'blue']:
|
||||
format = 'L'
|
||||
elif mode == 'color':
|
||||
format = 'RGB'
|
||||
else:
|
||||
raise ValueError('got unknown "mode" from self.get_parameters()')
|
||||
im=Image.new(format, (xsize,ysize))
|
||||
self.dev.snap( im.im.id, no_cancel )
|
||||
return im
|
||||
|
||||
def scan(self):
|
||||
self.start()
|
||||
return self.snap()
|
||||
|
||||
def multi_scan(self):
|
||||
return _SaneIterator(self)
|
||||
|
||||
def arr_snap(self, multipleOf=1):
|
||||
"""Snap a picture, returning a numarray object with the results.
|
||||
By default the resulting array has the same number of pixels per
|
||||
line as specified in self.get_parameters()[2][0]
|
||||
However sometimes it is necessary to obtain arrays where
|
||||
the number of pixels per line is e.g. a multiple of 4. This can then
|
||||
be achieved with the option 'multipleOf=4'. So if the scanner
|
||||
scanned 34 pixels per line, you will obtain an array with 32 pixels
|
||||
per line.
|
||||
"""
|
||||
(mode, last_frame, (xsize, ysize), depth, bpl) = self.get_parameters()
|
||||
if not mode in ['gray', 'red', 'green', 'blue']:
|
||||
raise RuntimeError('arr_snap() only works with monochrome images')
|
||||
if multipleOf < 1:
|
||||
raise ValueError('option "multipleOf" must be a positive number')
|
||||
elif multipleOf > 1:
|
||||
pixels_per_line = xsize - divmod(xsize, 4)[1]
|
||||
else:
|
||||
pixels_per_line = xsize
|
||||
return self.dev.arr_snap(pixels_per_line)
|
||||
|
||||
def arr_scan(self, multipleOf=1):
|
||||
self.start()
|
||||
return self.arr_snap(multipleOf=multipleOf)
|
||||
|
||||
def fileno(self):
|
||||
"Return the file descriptor for the scanning device"
|
||||
return self.dev.fileno()
|
||||
|
||||
def close(self):
|
||||
self.dev.close()
|
||||
|
||||
|
||||
def open(devname):
|
||||
"Open a device for scanning"
|
||||
new=SaneDev(devname)
|
||||
return new
|
294
Sane/sanedoc.txt
294
Sane/sanedoc.txt
|
@ -1,294 +0,0 @@
|
|||
The _sane_ module is an Python interface to the SANE (Scanning is Now
|
||||
Easy) library, which provides access to various raster scanning
|
||||
devices such as flatbed scanners and digital cameras. For more
|
||||
information about SANE, consult the SANE Web site at
|
||||
http://www.mostang.com/sane/ . Note that this
|
||||
documentation doesn't duplicate all the information in the SANE
|
||||
documentation, which you must also consult to get a complete
|
||||
understanding.
|
||||
|
||||
This module has been originally developed by A.M. Kuchling (amk1@erols.com),
|
||||
now development has been taken over by Ralph Heinkel (rheinkel-at-email.de).
|
||||
If you write to me please make sure to have the word 'SANE' or 'sane' in
|
||||
the subject of your mail, otherwise it might be classified as spam in the
|
||||
future.
|
||||
|
||||
|
||||
The module exports two object types, a bunch of constants, and two
|
||||
functions.
|
||||
|
||||
get_devices()
|
||||
Return a list of 4-tuples containing the available scanning
|
||||
devices. Each tuple contains 4 strings: the device name, suitable for
|
||||
passing to _open()_; the device's vendor; the model; and the type of
|
||||
device, such as 'virtual device' or 'video camera'.
|
||||
|
||||
>>> import sane ; sane.get_devices()
|
||||
[('epson:libusb:001:004', 'Epson', 'GT-8300', 'flatbed scanner')]
|
||||
|
||||
open(devicename)
|
||||
Open a device, given a string containing its name. SANE
|
||||
devices have names like 'epson:libusb:001:004'. If the attempt
|
||||
to open the device fails, a _sane.error_ exception will be raised. If
|
||||
there are no problems, a SaneDev object will be returned.
|
||||
As an easy way to open the scanner (if only one is available) just type
|
||||
>>> sane.open(sane.get_devices()[0][0])
|
||||
|
||||
|
||||
SaneDev objects
|
||||
===============
|
||||
|
||||
The basic process of scanning an image consists of getting a SaneDev
|
||||
object for the device, setting various parameters, starting the scan,
|
||||
and then reading the image data. Images are composed of one or more
|
||||
frames; greyscale and one-pass colour scanners return a single frame
|
||||
containing all the image data, but 3-pass scanners will usually return
|
||||
3 frames, one for each of the red, green, blue channels.
|
||||
|
||||
Methods:
|
||||
--------
|
||||
fileno()
|
||||
Returns a file descriptor for the scanning device. This
|
||||
method's existence means that SaneDev objects can be used by the
|
||||
select module.
|
||||
|
||||
get_parameters()
|
||||
Return a tuple containing information about the current settings of
|
||||
the device and the current frame: (format, last_frame,
|
||||
pixels_per_line, lines, depth, bytes_per_line).
|
||||
|
||||
mode -- 'gray' for greyscale image, 'color' for RGB image, or
|
||||
one of 'red', 'green', 'blue' if the image is a single
|
||||
channel of an RGB image (from PIL's point of view,
|
||||
this is equivalent to 'L').
|
||||
last_frame -- A Boolean value, which is true if this is the
|
||||
last frame of the image, and false otherwise.
|
||||
pixels_per_line -- Width of the frame.
|
||||
lines -- Height of the frame.
|
||||
depth -- Depth of the image, measured in bits. SANE will only
|
||||
allow using 8, 16, or 24-bit depths.
|
||||
bytes_per_line -- Bytes required to store a single line of
|
||||
data, as computed from pixels_per_line and depth.
|
||||
|
||||
start()
|
||||
Start a scan. This function must be called before the
|
||||
_snap()_ method can be used.
|
||||
|
||||
cancel()
|
||||
Cancel a scan already in progress.
|
||||
|
||||
snap(no_cancel=0)
|
||||
Snap a single frame of data, returning a PIL Image object
|
||||
containing the data. If no_cancel is false, the Sane library function
|
||||
sane_cancel is called after the scan. This is reasonable in most cases,
|
||||
but may cause backends for duplex ADF scanners to drop the backside image,
|
||||
when snap() is called for the front side image. If no_cancel is true,
|
||||
cancel() should be called manually, after all scans are finished.
|
||||
|
||||
scan()
|
||||
This is just a shortcut for s.start(); s.snap()
|
||||
Returns a PIL image
|
||||
|
||||
multi_scan()
|
||||
This method returns an iterator. It is intended to be used for
|
||||
scanning with an automatic document feeder. The next() method of the
|
||||
iterator tries to start a scan. If this is successful, it returns a
|
||||
PIL Image object, like scan(); if the document feeder runs out of
|
||||
paper, it raises StopIteration, thereby signaling that the sequence
|
||||
is ran out of items.
|
||||
|
||||
arr_snap(multipleOf=1)
|
||||
same as snap, but the result is a NumArray object. (Not that
|
||||
num_array must be installed already at compilation time, otherwise
|
||||
this feature will not be activated).
|
||||
By default the resulting array has the same number of pixels per
|
||||
line as specified in self.get_parameters()[2][0]
|
||||
However sometimes it is necessary to obtain arrays where
|
||||
the number of pixels per line is e.g. a multiple of 4. This can then
|
||||
be achieved with the option 'multipleOf=4'. So if the scanner
|
||||
scanned 34 pixels per line, you will obtain an array with 32 pixels
|
||||
per line.
|
||||
Note that this only works with monochrome images (e.g. gray-scales)
|
||||
|
||||
arr_scan(multipleOf=1)
|
||||
This is just a shortcut for s.start(); s.arr_snap(multipleOf=1)
|
||||
Returns a NumArray object
|
||||
|
||||
close()
|
||||
Closes the object.
|
||||
|
||||
|
||||
Attributes:
|
||||
-----------
|
||||
SaneDev objects have a few fixed attributes which are always
|
||||
available, and a larger collection of attributes which vary depending
|
||||
on the device. An Epson 1660 photo scanner has attributes like
|
||||
'mode', 'depth', etc.
|
||||
Another (pseudo scanner), the _pnm:0_ device, takes a PNM file and
|
||||
simulates a scanner using the image data; a SaneDev object
|
||||
representing the _pnm:0_ device therefore has a _filename_ attribute
|
||||
which can be changed to specify the filename, _contrast_ and
|
||||
_brightness_ attributes to modify the returned image, and so forth.
|
||||
|
||||
The values of the scanner options may be an integer, floating-point
|
||||
value, or string, depending on the nature of the option.
|
||||
|
||||
sane_signature
|
||||
The tuple for this scandev that is returned by sane.get_devices()
|
||||
e.g. ('epson:libusb:001:006', 'Epson', 'GT-8300', 'flatbed scanner')
|
||||
|
||||
scanner_model
|
||||
same as sane_signature[1:3], i.e. ('Epson', 'GT-8300') for the case above.
|
||||
|
||||
optlist
|
||||
A list containing the all the options supported by this device.
|
||||
|
||||
>>> import sane ; s=sane.open('epson:libusb:001:004') ; s.optlist
|
||||
['focus_position', 'color_correction', 'sharpness', ...., 'br_x']
|
||||
|
||||
A closer look at all options listed in s.optlist can be obtained
|
||||
through the SaneOption objects.
|
||||
|
||||
SaneOption objects
|
||||
==================
|
||||
|
||||
SANE's option handling is its most elaborate subsystem, intended to
|
||||
allow automatically generating dialog boxes and prompts for user
|
||||
configuration of the scanning device. The SaneOption object can be
|
||||
used to get a human-readable name and description for an option, the
|
||||
units to use, and what the legal values are. No information about the
|
||||
current value of the option is available; for that, read the
|
||||
corresponding attribute of a SaneDev object.
|
||||
|
||||
This documentation does not explain all the details of SANE's option
|
||||
handling; consult the SANE documentation for all the details.
|
||||
|
||||
A scandevice option is accessed via __getitem__. For example
|
||||
s['mode'] returns the option descriptor for the mode-option which
|
||||
controls whether the scanner works in color, grayscale, or b/w mode.
|
||||
|
||||
>>> s['mode']
|
||||
Name: mode
|
||||
Cur value: Color
|
||||
Index: 2
|
||||
Title: Scan mode
|
||||
Desc: Selects the scan mode (e.g., lineart, monochrome, or color).
|
||||
Type: TYPE_STRING
|
||||
Unit: UNIT_NONE
|
||||
Constr: ['Binary', 'Gray', 'Color']
|
||||
active: yes
|
||||
settable: yes
|
||||
|
||||
In order to change 'mode' to 'gray', just type:
|
||||
>>> s.mode = 'gray'
|
||||
|
||||
|
||||
With the attributes and methods of sane-option objects it is possible
|
||||
to access individual option values:
|
||||
|
||||
is_active()
|
||||
Returns true if the option is active.
|
||||
|
||||
is_settable()
|
||||
Returns true if the option can be set under software control.
|
||||
|
||||
|
||||
Attributes:
|
||||
|
||||
cap
|
||||
An integer containing various flags about the object's
|
||||
capabilities; whether it's active, whether it's settable, etc. Also
|
||||
available as the _capability_ attribute.
|
||||
|
||||
constraint
|
||||
The constraint placed on the value of this option. If it's
|
||||
_None_, there are essentially no constraint of the value. It may also
|
||||
be a list of integers or strings, in which case the value *must* be
|
||||
one of the possibilities in the list. Numeric values may have a
|
||||
3-tuple as the constraint; this 3-tuple contains _(minimum, maximum,
|
||||
increment)_, and the value must be in the defined range.
|
||||
|
||||
desc
|
||||
A lengthy description of what the option does; it may be shown
|
||||
to the user for clarification.
|
||||
|
||||
index
|
||||
An integer giving the option's index in the option list.
|
||||
|
||||
name
|
||||
A short name for the option, as it comes from the sane-backend.
|
||||
|
||||
py_name
|
||||
The option's name, as a legal Python identifier. The name
|
||||
attribute may contain the '-' character, so it will be converted to
|
||||
'_' for the py_name attribute.
|
||||
|
||||
size
|
||||
For a string-valued option, this is the maximum length allowed.
|
||||
|
||||
title
|
||||
A single-line string that can be used as a title string.
|
||||
|
||||
type
|
||||
A constant giving the type of this option: will be one of the following
|
||||
constants found in the SANE module:
|
||||
TYPE_BOOL
|
||||
TYPE_INT
|
||||
TYPE_FIXED
|
||||
TYPE_STRING
|
||||
TYPE_BUTTON
|
||||
TYPE_GROUP
|
||||
|
||||
unit
|
||||
For numeric-valued options, this is a constant representing
|
||||
the unit used for this option. It will be one of the following
|
||||
constants found in the SANE module:
|
||||
UNIT_NONE
|
||||
UNIT_PIXEL
|
||||
UNIT_BIT
|
||||
UNIT_MM
|
||||
UNIT_DPI
|
||||
UNIT_PERCENT
|
||||
|
||||
|
||||
|
||||
Example us usage:
|
||||
=================
|
||||
>>> import sane
|
||||
>>> print 'SANE version:', sane.init()
|
||||
>>> print 'Available devices=', sane.get_devices()
|
||||
SANE version: (16777230, 1, 0, 14)
|
||||
>>> s = sane.open(sane.get_devices()[0][0])
|
||||
>>> print 'Device parameters:', s.get_parameters()
|
||||
Device parameters: ('L', 1, (424, 585), 1, 53)
|
||||
>>> print s.resolution
|
||||
50
|
||||
|
||||
## In order to scan a color image into a PIL object:
|
||||
>>> s.mode = 'color'
|
||||
>>> s.start()
|
||||
>>> img = s.snap()
|
||||
>>> img.show()
|
||||
|
||||
|
||||
## In order to obtain a 16-bit grayscale image at 100DPI in a numarray object
|
||||
## with bottom-right coordinates set to (160, 120) [in millimeter] :
|
||||
>>> s.mode = 'gray'
|
||||
>>> s.br_x=160. ; s.br_y=120.
|
||||
>>> s.resolution = 100
|
||||
>>> s.depth=16
|
||||
>>> s.start()
|
||||
>>> s.get_parameters()[2] # just check the size
|
||||
(624, 472)
|
||||
>>> arr16 = s.arr_snap()
|
||||
>>> arr16
|
||||
array([[63957, 64721, 65067, ..., 65535, 65535, 65535],
|
||||
[63892, 64342, 64236, ..., 65535, 65535, 65535],
|
||||
[64286, 64248, 64705, ..., 65535, 65535, 65535],
|
||||
...,
|
||||
[65518, 65249, 65058, ..., 65535, 65535, 65535],
|
||||
[64435, 65047, 65081, ..., 65535, 65535, 65535],
|
||||
[65309, 65438, 65535, ..., 65535, 65535, 65535]], type=UInt16)
|
||||
>>> arr16.shape # inverse order of coordinates, first y, then x!
|
||||
(472, 624)
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
from distutils.core import setup, Extension
|
||||
|
||||
PIL_BUILD_DIR = '..'
|
||||
PIL_IMAGING_DIR = PIL_BUILD_DIR+'/libImaging'
|
||||
|
||||
defs = []
|
||||
try:
|
||||
import numarray
|
||||
defs.append(('WITH_NUMARRAY',None))
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
sane = Extension('_sane',
|
||||
include_dirs = [PIL_IMAGING_DIR],
|
||||
libraries = ['sane'],
|
||||
library_dirs = [PIL_IMAGING_DIR],
|
||||
define_macros = defs,
|
||||
sources = ['_sane.c'])
|
||||
|
||||
setup (name = 'pysane',
|
||||
version = '2.0',
|
||||
description = 'This is the pysane package',
|
||||
py_modules = ['sane'],
|
||||
ext_modules = [sane])
|
Loading…
Reference in New Issue
Block a user