mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-05 06:00:58 +03:00
Merge remote-tracking branch 'upstream/master' into landscape-fixes
This commit is contained in:
commit
947e34616c
35
CHANGES.rst
35
CHANGES.rst
|
@ -1,9 +1,42 @@
|
||||||
Changelog (Pillow)
|
Changelog (Pillow)
|
||||||
==================
|
==================
|
||||||
|
|
||||||
2.6.0 (unreleased)
|
2.7.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Support for 4-bit greyscale TIFF images #980
|
||||||
|
[hugovk, wiredfool]
|
||||||
|
|
||||||
|
- Updated manifest #957
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix PyPy 2.4 regression #952
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Webp Metadata Skip Test comments #954
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fixes for things rpmlint complains about #942
|
||||||
|
[manisandro]
|
||||||
|
|
||||||
|
2.6.1 (2014-10-11)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fix SciPy regression in Image.resize #945
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix manifest to include all test files.
|
||||||
|
[aclark]
|
||||||
|
|
||||||
|
2.6.0 (2014-10-01)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Relax precision of ImageDraw tests for x86, GimpGradient for PPC
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
2.6.0-rc1 (2014-09-29)
|
||||||
|
----------------------
|
||||||
|
|
||||||
- Use redistributable image for testing #884
|
- Use redistributable image for testing #884
|
||||||
[hugovk]
|
[hugovk]
|
||||||
|
|
||||||
|
|
25
MANIFEST.in
25
MANIFEST.in
|
@ -1,40 +1,26 @@
|
||||||
|
|
||||||
include *.c
|
include *.c
|
||||||
include *.h
|
include *.h
|
||||||
include *.md
|
include *.md
|
||||||
include *.py
|
include *.py
|
||||||
include *.rst
|
include *.rst
|
||||||
include *.txt
|
include *.txt
|
||||||
|
include *.yaml
|
||||||
include .coveragerc
|
include .coveragerc
|
||||||
include .gitattributes
|
include .gitattributes
|
||||||
include .travis.yml
|
include .travis.yml
|
||||||
include Makefile
|
include Makefile
|
||||||
include tox.ini
|
include tox.ini
|
||||||
recursive-include Images *.bdf
|
|
||||||
recursive-include Images *.fli
|
|
||||||
recursive-include Images *.gif
|
|
||||||
recursive-include Images *.icns
|
|
||||||
recursive-include Images *.ico
|
|
||||||
recursive-include Images *.jpg
|
|
||||||
recursive-include Images *.pbm
|
|
||||||
recursive-include Images *.pil
|
|
||||||
recursive-include Images *.png
|
|
||||||
recursive-include Images *.ppm
|
|
||||||
recursive-include Images *.psd
|
|
||||||
recursive-include Images *.tar
|
|
||||||
recursive-include Images *.webp
|
|
||||||
recursive-include Images *.xpm
|
|
||||||
recursive-include PIL *.md
|
recursive-include PIL *.md
|
||||||
recursive-include Sane *.c
|
recursive-include Sane *.c
|
||||||
recursive-include Sane *.py
|
recursive-include Sane *.py
|
||||||
recursive-include Sane *.rst
|
recursive-include Sane *.rst
|
||||||
recursive-include Sane *.txt
|
recursive-include Sane *.txt
|
||||||
recursive-include Sane CHANGES
|
recursive-include Sane CHANGES
|
||||||
recursive-include Sane README
|
recursive-include Sane README.rst
|
||||||
recursive-include Scripts *.py
|
recursive-include Scripts *.py
|
||||||
recursive-include Scripts *.rst
|
recursive-include Scripts *.rst
|
||||||
recursive-include Scripts *.sh
|
recursive-include Scripts *.sh
|
||||||
recursive-include Scripts README
|
recursive-include Scripts README.rst
|
||||||
recursive-include Tests *.bdf
|
recursive-include Tests *.bdf
|
||||||
recursive-include Tests *.bin
|
recursive-include Tests *.bin
|
||||||
recursive-include Tests *.bmp
|
recursive-include Tests *.bmp
|
||||||
|
@ -44,10 +30,11 @@ recursive-include Tests *.dcx
|
||||||
recursive-include Tests *.doc
|
recursive-include Tests *.doc
|
||||||
recursive-include Tests *.eps
|
recursive-include Tests *.eps
|
||||||
recursive-include Tests *.fli
|
recursive-include Tests *.fli
|
||||||
|
recursive-include Tests *.ggr
|
||||||
recursive-include Tests *.gif
|
recursive-include Tests *.gif
|
||||||
recursive-include Tests *.gnuplot
|
recursive-include Tests *.gnuplot
|
||||||
recursive-include Tests *.html
|
recursive-include Tests *.html
|
||||||
recursive-include Tests *.icm
|
recursive-include Tests *.icc
|
||||||
recursive-include Tests *.icns
|
recursive-include Tests *.icns
|
||||||
recursive-include Tests *.ico
|
recursive-include Tests *.ico
|
||||||
recursive-include Tests *.j2k
|
recursive-include Tests *.j2k
|
||||||
|
@ -70,6 +57,7 @@ recursive-include Tests *.rst
|
||||||
recursive-include Tests *.sgi
|
recursive-include Tests *.sgi
|
||||||
recursive-include Tests *.spider
|
recursive-include Tests *.spider
|
||||||
recursive-include Tests *.tar
|
recursive-include Tests *.tar
|
||||||
|
recursive-include Tests *.tga
|
||||||
recursive-include Tests *.tif
|
recursive-include Tests *.tif
|
||||||
recursive-include Tests *.tiff
|
recursive-include Tests *.tiff
|
||||||
recursive-include Tests *.ttf
|
recursive-include Tests *.ttf
|
||||||
|
@ -78,7 +66,6 @@ recursive-include Tests *.webp
|
||||||
recursive-include Tests *.xpm
|
recursive-include Tests *.xpm
|
||||||
recursive-include Tk *.c
|
recursive-include Tk *.c
|
||||||
recursive-include Tk *.rst
|
recursive-include Tk *.rst
|
||||||
recursive-include Tk *.txt
|
|
||||||
recursive-include depends *.rst
|
recursive-include depends *.rst
|
||||||
recursive-include depends *.sh
|
recursive-include depends *.sh
|
||||||
recursive-include docs *.bat
|
recursive-include docs *.bat
|
||||||
|
|
|
@ -1010,8 +1010,6 @@ class Image:
|
||||||
|
|
||||||
def draft(self, mode, size):
|
def draft(self, mode, size):
|
||||||
"""
|
"""
|
||||||
NYI
|
|
||||||
|
|
||||||
Configures the image file loader so it returns a version of the
|
Configures the image file loader so it returns a version of the
|
||||||
image that as closely as possible matches the given mode and
|
image that as closely as possible matches the given mode and
|
||||||
size. For example, you can use this method to convert a color
|
size. For example, you can use this method to convert a color
|
||||||
|
@ -1530,6 +1528,7 @@ class Image:
|
||||||
|
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
|
size=tuple(size)
|
||||||
if self.size == size:
|
if self.size == size:
|
||||||
return self._new(self.im)
|
return self._new(self.im)
|
||||||
|
|
||||||
|
@ -2335,7 +2334,7 @@ def composite(image1, image2, mask):
|
||||||
:param image1: The first image.
|
:param image1: The first image.
|
||||||
:param image2: The second image. Must have the same mode and
|
:param image2: The second image. Must have the same mode and
|
||||||
size as the first image.
|
size as the first image.
|
||||||
:param mask: A mask image. This image can can have mode
|
:param mask: A mask image. This image can have mode
|
||||||
"1", "L", or "RGBA", and must have the same size as the
|
"1", "L", or "RGBA", and must have the same size as the
|
||||||
other two images.
|
other two images.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -90,8 +90,8 @@ try:
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
# Allow error import for doc purposes, but error out when accessing
|
# Allow error import for doc purposes, but error out when accessing
|
||||||
# anything in core.
|
# anything in core.
|
||||||
from _util import import_err
|
from _util import deferred_error
|
||||||
_imagingcms = import_err(ex)
|
_imagingcms = deferred_error(ex)
|
||||||
from PIL._util import isStringType
|
from PIL._util import isStringType
|
||||||
|
|
||||||
core = _imagingcms
|
core = _imagingcms
|
||||||
|
|
3
PIL/OleFileIO.py
Normal file → Executable file
3
PIL/OleFileIO.py
Normal file → Executable file
|
@ -1,5 +1,4 @@
|
||||||
#!/usr/local/bin/python
|
#!/usr/bin/env python
|
||||||
# -*- coding: latin-1 -*-
|
|
||||||
## OleFileIO_PL:
|
## OleFileIO_PL:
|
||||||
## Module to read Microsoft OLE2 files (also called Structured Storage or
|
## Module to read Microsoft OLE2 files (also called Structured Storage or
|
||||||
## Microsoft Compound Document File Format), such as Microsoft Office
|
## Microsoft Compound Document File Format), such as Microsoft Office
|
||||||
|
|
|
@ -149,6 +149,7 @@ OPEN_INFO = {
|
||||||
(II, 0, 1, 2, (8,), ()): ("L", "L;IR"),
|
(II, 0, 1, 2, (8,), ()): ("L", "L;IR"),
|
||||||
(II, 0, 3, 1, (32,), ()): ("F", "F;32F"),
|
(II, 0, 3, 1, (32,), ()): ("F", "F;32F"),
|
||||||
(II, 1, 1, 1, (1,), ()): ("1", "1"),
|
(II, 1, 1, 1, (1,), ()): ("1", "1"),
|
||||||
|
(II, 1, 1, 1, (4,), ()): ("L", "L;4"),
|
||||||
(II, 1, 1, 2, (1,), ()): ("1", "1;R"),
|
(II, 1, 1, 2, (1,), ()): ("1", "1;R"),
|
||||||
(II, 1, 1, 1, (8,), ()): ("L", "L"),
|
(II, 1, 1, 1, (8,), ()): ("L", "L"),
|
||||||
(II, 1, 1, 1, (8, 8), (2,)): ("LA", "LA"),
|
(II, 1, 1, 1, (8, 8), (2,)): ("LA", "LA"),
|
||||||
|
@ -449,10 +450,10 @@ class ImageFileDirectory(collections.MutableMapping):
|
||||||
if size > 4:
|
if size > 4:
|
||||||
here = fp.tell()
|
here = fp.tell()
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print ("Tag Location: %s" %here)
|
print("Tag Location: %s" % here)
|
||||||
fp.seek(i32(ifd, 8))
|
fp.seek(i32(ifd, 8))
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print ("Data Location: %s" %fp.tell())
|
print("Data Location: %s" % fp.tell())
|
||||||
data = ImageFile._safe_read(fp, size)
|
data = ImageFile._safe_read(fp, size)
|
||||||
fp.seek(here)
|
fp.seek(here)
|
||||||
else:
|
else:
|
||||||
|
@ -659,14 +660,14 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
if not self.__next:
|
if not self.__next:
|
||||||
raise EOFError("no more images in TIFF file")
|
raise EOFError("no more images in TIFF file")
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print("Seeking to frame %s, on frame %s, __next %s, location: %s"%
|
print("Seeking to frame %s, on frame %s, __next %s, location: %s" %
|
||||||
(frame, self.__frame, self.__next, self.fp.tell()))
|
(frame, self.__frame, self.__next, self.fp.tell()))
|
||||||
# reset python3 buffered io handle in case fp
|
# reset python3 buffered io handle in case fp
|
||||||
# was passed to libtiff, invalidating the buffer
|
# was passed to libtiff, invalidating the buffer
|
||||||
self.fp.tell()
|
self.fp.tell()
|
||||||
self.fp.seek(self.__next)
|
self.fp.seek(self.__next)
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print("Loading tags, location: %s"%self.fp.tell())
|
print("Loading tags, location: %s" % self.fp.tell())
|
||||||
self.tag.load(self.fp)
|
self.tag.load(self.fp)
|
||||||
self.__next = self.tag.next
|
self.__next = self.tag.next
|
||||||
self.__frame += 1
|
self.__frame += 1
|
||||||
|
@ -883,6 +884,10 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
try:
|
try:
|
||||||
fp = hasattr(self.fp, "fileno") and \
|
fp = hasattr(self.fp, "fileno") and \
|
||||||
os.dup(self.fp.fileno())
|
os.dup(self.fp.fileno())
|
||||||
|
# flush the file descriptor, prevents error on pypy 2.4+
|
||||||
|
# should also eliminate the need for fp.tell for py3
|
||||||
|
# in _seek
|
||||||
|
self.fp.flush()
|
||||||
except IOError:
|
except IOError:
|
||||||
# io.BytesIO have a fileno, but returns an IOError if
|
# io.BytesIO have a fileno, but returns an IOError if
|
||||||
# it doesn't use a file descriptor.
|
# it doesn't use a file descriptor.
|
||||||
|
@ -1149,8 +1154,11 @@ def _save(im, fp, filename):
|
||||||
# following tiffcp.c->cpTag->TIFF_RATIONAL
|
# following tiffcp.c->cpTag->TIFF_RATIONAL
|
||||||
atts[k] = float(v[0][0])/float(v[0][1])
|
atts[k] = float(v[0][0])/float(v[0][1])
|
||||||
continue
|
continue
|
||||||
if type(v) == tuple and len(v) > 2:
|
if (type(v) == tuple and
|
||||||
|
(len(v) > 2 or
|
||||||
|
(len(v) == 2 and v[1] == 0))):
|
||||||
# List of ints?
|
# List of ints?
|
||||||
|
# Avoid divide by zero in next if-clause
|
||||||
if type(v[0]) in (int, float):
|
if type(v[0]) in (int, float):
|
||||||
atts[k] = list(v)
|
atts[k] = list(v)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# -*- coding: iso-8859-1 -*-
|
|
||||||
#
|
|
||||||
# The Python Imaging Library.
|
# The Python Imaging Library.
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
@ -76,7 +74,7 @@ def open(filename):
|
||||||
|
|
||||||
|
|
||||||
quake2palette = (
|
quake2palette = (
|
||||||
# default palette taken from piffo 0.93 by Hans Häggström
|
# default palette taken from piffo 0.93 by Hans Häggström
|
||||||
b"\x01\x01\x01\x0b\x0b\x0b\x12\x12\x12\x17\x17\x17\x1b\x1b\x1b\x1e"
|
b"\x01\x01\x01\x0b\x0b\x0b\x12\x12\x12\x17\x17\x17\x1b\x1b\x1b\x1e"
|
||||||
b"\x1e\x1e\x22\x22\x22\x26\x26\x26\x29\x29\x29\x2c\x2c\x2c\x2f\x2f"
|
b"\x1e\x1e\x22\x22\x22\x26\x26\x26\x29\x29\x29\x2c\x2c\x2c\x2f\x2f"
|
||||||
b"\x2f\x32\x32\x32\x35\x35\x35\x37\x37\x37\x3a\x3a\x3a\x3c\x3c\x3c"
|
b"\x2f\x32\x32\x32\x35\x35\x35\x37\x37\x37\x3a\x3a\x3a\x3c\x3c\x3c"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# ;-)
|
# ;-)
|
||||||
|
|
||||||
VERSION = '1.1.7' # PIL version
|
VERSION = '1.1.7' # PIL version
|
||||||
PILLOW_VERSION = '2.5.3' # Pillow
|
PILLOW_VERSION = '2.6.0' # Pillow
|
||||||
|
|
||||||
_plugins = ['BmpImagePlugin',
|
_plugins = ['BmpImagePlugin',
|
||||||
'BufrStubImagePlugin',
|
'BufrStubImagePlugin',
|
||||||
|
|
|
@ -6,6 +6,7 @@ Released quarterly.
|
||||||
|
|
||||||
* [ ] Get master to the appropriate code release state. [Travis CI](https://travis-ci.org/python-pillow/Pillow) should be running cleanly for all merges to master.
|
* [ ] Get master to the appropriate code release state. [Travis CI](https://travis-ci.org/python-pillow/Pillow) should be running cleanly for all merges to master.
|
||||||
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`, Update date in `CHANGES.rst`.
|
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`, Update date in `CHANGES.rst`.
|
||||||
|
* [ ] Run pre-release check via `make pre`
|
||||||
* [ ] Tag and push to release branch in python-pillow repo.
|
* [ ] Tag and push to release branch in python-pillow repo.
|
||||||
* [ ] Upload binaries.
|
* [ ] Upload binaries.
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ Released as required for security or installation fixes.
|
||||||
* [ ] Make necessary changes in master.
|
* [ ] Make necessary changes in master.
|
||||||
* [ ] Cherry pick individual commits. Touch up `CHANGES.rst` to reflect reality.
|
* [ ] Cherry pick individual commits. Touch up `CHANGES.rst` to reflect reality.
|
||||||
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`
|
* [ ] Update version in `PIL/__init__.py`, `setup.py`, `_imaging.c`
|
||||||
|
* [ ] Run pre-release check via `make pre`
|
||||||
* [ ] Push to release branch in personal repo. Let Travis run cleanly.
|
* [ ] Push to release branch in personal repo. Let Travis run cleanly.
|
||||||
* [ ] Tag and push to release branch in python-pillow repo.
|
* [ ] Tag and push to release branch in python-pillow repo.
|
||||||
* [ ] Upload binaries.
|
* [ ] Upload binaries.
|
||||||
|
@ -28,6 +30,7 @@ Security fixes that need to be pushed to the distros prior to public release.
|
||||||
* [ ] Commit against master, cherry pick to affected release branches.
|
* [ ] Commit against master, cherry pick to affected release branches.
|
||||||
* [ ] Run local test matrix on each release & Python version.
|
* [ ] Run local test matrix on each release & Python version.
|
||||||
* [ ] Privately send to distros.
|
* [ ] Privately send to distros.
|
||||||
|
* [ ] Run pre-release check via `make pre`
|
||||||
* [ ] Amend any commits with the CVE #
|
* [ ] Amend any commits with the CVE #
|
||||||
* [ ] On release date, tag and push to GitHub.
|
* [ ] On release date, tag and push to GitHub.
|
||||||
```
|
```
|
||||||
|
@ -53,3 +56,4 @@ python setup.py sdist upload
|
||||||
* [ ] Retrieve the OS X Wheels from Rackspace files, upload to PyPi (Twine?)
|
* [ ] Retrieve the OS X Wheels from Rackspace files, upload to PyPi (Twine?)
|
||||||
* [ ] Grab Windows binaries, `twine upload dist/*.[whl|egg]`. Manually upload .exe installers.
|
* [ ] Grab Windows binaries, `twine upload dist/*.[whl|egg]`. Manually upload .exe installers.
|
||||||
* [ ] Announce release availability. [Twitter](https://twitter.com/pythonpillow), web.
|
* [ ] Announce release availability. [Twitter](https://twitter.com/pythonpillow), web.
|
||||||
|
|
||||||
|
|
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])
|
|
BIN
Tests/images/hopper.msp
Normal file
BIN
Tests/images/hopper.msp
Normal file
Binary file not shown.
BIN
Tests/images/hopper_gray_4bpp.tif
Normal file
BIN
Tests/images/hopper_gray_4bpp.tif
Normal file
Binary file not shown.
BIN
Tests/images/total-pages-zero.tif
Normal file
BIN
Tests/images/total-pages-zero.tif
Normal file
Binary file not shown.
|
@ -80,7 +80,7 @@ class TestImage(PillowTestCase):
|
||||||
ret = GimpGradientFile.sphere_increasing(middle, pos)
|
ret = GimpGradientFile.sphere_increasing(middle, pos)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(ret, 0.9682458365518543)
|
self.assert_almost_equal(ret, 0.9682458365518543)
|
||||||
|
|
||||||
def test_sphere_decreasing(self):
|
def test_sphere_decreasing(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
|
|
@ -342,6 +342,24 @@ class TestFileLibTiff(LibTiffTestCase):
|
||||||
im.load()
|
im.load()
|
||||||
self.assertFalse(im.tag.next)
|
self.assertFalse(im.tag.next)
|
||||||
|
|
||||||
|
def test_4bit(self):
|
||||||
|
# Arrange
|
||||||
|
test_file = "Tests/images/hopper_gray_4bpp.tif"
|
||||||
|
original = hopper("L")
|
||||||
|
|
||||||
|
# Act
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = True
|
||||||
|
im = Image.open(test_file)
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = False
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (128, 128))
|
||||||
|
self.assertEqual(im.mode, "L")
|
||||||
|
self.assert_image_similar(im, original, 7.3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@ from helper import unittest, PillowTestCase, hopper
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
TEST_FILE = "Tests/images/hopper.msp"
|
||||||
|
|
||||||
|
|
||||||
class TestFileMsp(PillowTestCase):
|
class TestFileMsp(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
file = self.tempfile("temp.msp")
|
file = self.tempfile("temp.msp")
|
||||||
|
|
||||||
hopper("1").save(file)
|
hopper("1").save(file)
|
||||||
|
@ -17,6 +18,23 @@ class TestFileMsp(PillowTestCase):
|
||||||
self.assertEqual(im.size, (128, 128))
|
self.assertEqual(im.size, (128, 128))
|
||||||
self.assertEqual(im.format, "MSP")
|
self.assertEqual(im.format, "MSP")
|
||||||
|
|
||||||
|
def test_open(self):
|
||||||
|
# Arrange
|
||||||
|
# Act
|
||||||
|
im = Image.open(TEST_FILE)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (128, 128))
|
||||||
|
self.assert_image_similar(im, hopper("1"), 4)
|
||||||
|
|
||||||
|
def test_cannot_save_save_wrong_mode(self):
|
||||||
|
# Arrange
|
||||||
|
im = hopper()
|
||||||
|
file = self.tempfile("temp.msp")
|
||||||
|
|
||||||
|
# Act/Assert
|
||||||
|
self.assertRaises(IOError, lambda: im.save(file))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -144,28 +144,27 @@ class TestFileTiff(PillowTestCase):
|
||||||
def test_multipage(self):
|
def test_multipage(self):
|
||||||
# issue #862
|
# issue #862
|
||||||
im = Image.open('Tests/images/multipage.tiff')
|
im = Image.open('Tests/images/multipage.tiff')
|
||||||
# file is a multipage tiff, 10x10 green, 10x10 red, 20x20 blue
|
# file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue
|
||||||
|
|
||||||
im.seek(0)
|
im.seek(0)
|
||||||
self.assertEqual(im.size, (10,10))
|
self.assertEqual(im.size, (10, 10))
|
||||||
self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,128,0))
|
self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 128, 0))
|
||||||
|
|
||||||
im.seek(1)
|
im.seek(1)
|
||||||
im.load()
|
im.load()
|
||||||
self.assertEqual(im.size, (10,10))
|
self.assertEqual(im.size, (10, 10))
|
||||||
self.assertEqual(im.convert('RGB').getpixel((0,0)), (255,0,0))
|
self.assertEqual(im.convert('RGB').getpixel((0, 0)), (255, 0, 0))
|
||||||
|
|
||||||
im.seek(2)
|
im.seek(2)
|
||||||
im.load()
|
im.load()
|
||||||
self.assertEqual(im.size, (20,20))
|
self.assertEqual(im.size, (20, 20))
|
||||||
self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255))
|
self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255))
|
||||||
|
|
||||||
def test_multipage_last_frame(self):
|
def test_multipage_last_frame(self):
|
||||||
im = Image.open('Tests/images/multipage-lastframe.tif')
|
im = Image.open('Tests/images/multipage-lastframe.tif')
|
||||||
im.load()
|
im.load()
|
||||||
self.assertEqual(im.size, (20,20))
|
self.assertEqual(im.size, (20, 20))
|
||||||
self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255))
|
self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255))
|
||||||
|
|
||||||
|
|
||||||
def test___str__(self):
|
def test___str__(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -294,6 +293,39 @@ class TestFileTiff(PillowTestCase):
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(ret, [0, 1])
|
self.assertEqual(ret, [0, 1])
|
||||||
|
|
||||||
|
def test_4bit(self):
|
||||||
|
# Arrange
|
||||||
|
test_file = "Tests/images/hopper_gray_4bpp.tif"
|
||||||
|
original = hopper("L")
|
||||||
|
|
||||||
|
# Act
|
||||||
|
im = Image.open(test_file)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (128, 128))
|
||||||
|
self.assertEqual(im.mode, "L")
|
||||||
|
self.assert_image_similar(im, original, 7.3)
|
||||||
|
|
||||||
|
|
||||||
|
def test_page_number_x_0(self):
|
||||||
|
# Issue 973
|
||||||
|
# Test TIFF with tag 297 (Page Number) having value of 0 0.
|
||||||
|
# The first number is the current page number.
|
||||||
|
# The second is the total number of pages, zero means not available.
|
||||||
|
|
||||||
|
# Arrange
|
||||||
|
outfile = self.tempfile("temp.tif")
|
||||||
|
|
||||||
|
# Created by printing a page in Chrome to PDF, then:
|
||||||
|
# /usr/bin/gs -q -sDEVICE=tiffg3 -sOutputFile=total-pages-zero.tif
|
||||||
|
# -dNOPAUSE /tmp/test.pdf -c quit
|
||||||
|
infile = "Tests/images/total-pages-zero.tif"
|
||||||
|
im = Image.open(infile)
|
||||||
|
|
||||||
|
# Act / Assert
|
||||||
|
# Should not divide by zero
|
||||||
|
im.save(outfile)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -8,10 +8,13 @@ class TestFileWebpMetadata(PillowTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
try:
|
try:
|
||||||
from PIL import _webp
|
from PIL import _webp
|
||||||
if not _webp.HAVE_WEBPMUX:
|
|
||||||
self.skipTest('webpmux support not installed')
|
|
||||||
except:
|
except:
|
||||||
self.skipTest('WebP support not installed')
|
self.skipTest('WebP support not installed')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not _webp.HAVE_WEBPMUX:
|
||||||
|
self.skipTest('WebPMux support not installed')
|
||||||
|
|
||||||
|
|
||||||
def test_read_exif_metadata(self):
|
def test_read_exif_metadata(self):
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ class TestImageDraw(PillowTestCase):
|
||||||
del draw
|
del draw
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assert_image_equal(
|
self.assert_image_similar(
|
||||||
im, Image.open("Tests/images/imagedraw_arc.png"))
|
im, Image.open("Tests/images/imagedraw_arc.png"),1)
|
||||||
|
|
||||||
def test_arc1(self):
|
def test_arc1(self):
|
||||||
self.helper_arc(BBOX1)
|
self.helper_arc(BBOX1)
|
||||||
|
@ -96,8 +96,8 @@ class TestImageDraw(PillowTestCase):
|
||||||
del draw
|
del draw
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assert_image_equal(
|
self.assert_image_similar(
|
||||||
im, Image.open("Tests/images/imagedraw_chord.png"))
|
im, Image.open("Tests/images/imagedraw_chord.png"),1)
|
||||||
|
|
||||||
def test_chord1(self):
|
def test_chord1(self):
|
||||||
self.helper_chord(BBOX1)
|
self.helper_chord(BBOX1)
|
||||||
|
@ -115,8 +115,8 @@ class TestImageDraw(PillowTestCase):
|
||||||
del draw
|
del draw
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assert_image_equal(
|
self.assert_image_similar(
|
||||||
im, Image.open("Tests/images/imagedraw_ellipse.png"))
|
im, Image.open("Tests/images/imagedraw_ellipse.png"),1)
|
||||||
|
|
||||||
def test_ellipse1(self):
|
def test_ellipse1(self):
|
||||||
self.helper_ellipse(BBOX1)
|
self.helper_ellipse(BBOX1)
|
||||||
|
@ -153,8 +153,8 @@ class TestImageDraw(PillowTestCase):
|
||||||
del draw
|
del draw
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assert_image_equal(
|
self.assert_image_similar(
|
||||||
im, Image.open("Tests/images/imagedraw_pieslice.png"))
|
im, Image.open("Tests/images/imagedraw_pieslice.png"),1)
|
||||||
|
|
||||||
def test_pieslice1(self):
|
def test_pieslice1(self):
|
||||||
self.helper_pieslice(BBOX1)
|
self.helper_pieslice(BBOX1)
|
||||||
|
|
|
@ -55,6 +55,12 @@ class TestImageFile(PillowTestCase):
|
||||||
|
|
||||||
if EpsImagePlugin.has_ghostscript():
|
if EpsImagePlugin.has_ghostscript():
|
||||||
im1, im2 = roundtrip("EPS")
|
im1, im2 = roundtrip("EPS")
|
||||||
|
# This test fails on Ubuntu 12.04, PPC (Bigendian) It
|
||||||
|
# appears to be a ghostscript 9.05 bug, since the
|
||||||
|
# ghostscript rendering is wonky and the file is identical
|
||||||
|
# to that written on ubuntu 12.04 x64
|
||||||
|
# md5sum: ba974835ff2d6f3f2fd0053a23521d4a
|
||||||
|
|
||||||
# EPS comes back in RGB:
|
# EPS comes back in RGB:
|
||||||
self.assert_image_similar(im1, im2.convert('L'), 20)
|
self.assert_image_similar(im1, im2.convert('L'), 20)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from helper import unittest, PillowTestCase
|
from helper import unittest, PillowTestCase
|
||||||
|
|
||||||
|
from PIL import PILLOW_VERSION
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pyroma
|
import pyroma
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -23,8 +25,14 @@ class TestPyroma(PillowTestCase):
|
||||||
rating = pyroma.ratings.rate(data)
|
rating = pyroma.ratings.rate(data)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
# Should have a perfect score
|
if 'rc' in PILLOW_VERSION:
|
||||||
self.assertEqual(rating, (10, []))
|
#Pyroma needs to chill about RC versions and not kill all our tests.
|
||||||
|
self.assertEqual(rating, (9,
|
||||||
|
['The packages version number does not comply with PEP-386.']))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Should have a perfect score
|
||||||
|
self.assertEqual(rating, (10, []))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
42
Tests/test_scipy.py
Normal file
42
Tests/test_scipy.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
from helper import PillowTestCase
|
||||||
|
|
||||||
|
try:
|
||||||
|
import numpy as np
|
||||||
|
from numpy.testing import assert_equal
|
||||||
|
|
||||||
|
from scipy import misc
|
||||||
|
HAS_SCIPY = True
|
||||||
|
except:
|
||||||
|
HAS_SCIPY = False
|
||||||
|
|
||||||
|
|
||||||
|
class Test_scipy_resize(PillowTestCase):
|
||||||
|
""" Tests for scipy regression in 2.6.0 """
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
if not HAS_SCIPY:
|
||||||
|
self.skipTest("Scipy Required")
|
||||||
|
|
||||||
|
def test_imresize(self):
|
||||||
|
im = np.random.random((10,20))
|
||||||
|
for T in np.sctypes['float'] + [float]:
|
||||||
|
# 1.1 rounds to below 1.1 for float16, 1.101 works
|
||||||
|
im1 = misc.imresize(im,T(1.101))
|
||||||
|
self.assertEqual(im1.shape,(11,22))
|
||||||
|
|
||||||
|
def test_imresize4(self):
|
||||||
|
im = np.array([[1,2],
|
||||||
|
[3,4]])
|
||||||
|
res = np.array([[ 1. , 1. , 1.5, 2. ],
|
||||||
|
[ 1. , 1. , 1.5, 2. ],
|
||||||
|
[ 2. , 2. , 2.5, 3. ],
|
||||||
|
[ 3. , 3. , 3.5, 4. ]], dtype=np.float32)
|
||||||
|
# Check that resizing by target size, float and int are the same
|
||||||
|
im2 = misc.imresize(im, (4,4), mode='F') # output size
|
||||||
|
im3 = misc.imresize(im, 2., mode='F') # fraction
|
||||||
|
im4 = misc.imresize(im, 200, mode='F') # percentage
|
||||||
|
assert_equal(im2, res)
|
||||||
|
assert_equal(im3, res)
|
||||||
|
assert_equal(im4, res)
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
* See the README file for information on usage and redistribution.
|
* See the README file for information on usage and redistribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PILLOW_VERSION "2.5.3"
|
#define PILLOW_VERSION "2.6.0"
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,9 @@ pygments_style = 'sphinx'
|
||||||
|
|
||||||
### HTML output ###
|
### HTML output ###
|
||||||
|
|
||||||
from better import better_theme_path
|
#from better import better_theme_path
|
||||||
html_theme_path = [better_theme_path]
|
#html_theme_path = [better_theme_path]
|
||||||
html_theme = 'better'
|
#html_theme = 'better'
|
||||||
|
|
||||||
html_title = "Pillow v{release} (PIL fork)".format(release=release)
|
html_title = "Pillow v{release} (PIL fork)".format(release=release)
|
||||||
html_short_title = "Home"
|
html_short_title = "Home"
|
||||||
|
|
|
@ -16,7 +16,7 @@ Let’s look at a few possible uses of this library.
|
||||||
Image Archives
|
Image Archives
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
The Python Imaging Library is ideal for for image archival and batch processing
|
The Python Imaging Library is ideal for image archival and batch processing
|
||||||
applications. You can use the library to create thumbnails, convert between
|
applications. You can use the library to create thumbnails, convert between
|
||||||
file formats, print images, etc.
|
file formats, print images, etc.
|
||||||
|
|
||||||
|
|
|
@ -296,7 +296,7 @@ Point Operations
|
||||||
|
|
||||||
The :py:meth:`~PIL.Image.Image.point` method can be used to translate the pixel
|
The :py:meth:`~PIL.Image.Image.point` method can be used to translate the pixel
|
||||||
values of an image (e.g. image contrast manipulation). In most cases, a
|
values of an image (e.g. image contrast manipulation). In most cases, a
|
||||||
function object expecting one argument can be passed to the this method. Each
|
function object expecting one argument can be passed to this method. Each
|
||||||
pixel is processed according to that function:
|
pixel is processed according to that function:
|
||||||
|
|
||||||
Applying point transforms
|
Applying point transforms
|
||||||
|
@ -397,7 +397,7 @@ Note that most drivers in the current version of the library only allow you to
|
||||||
seek to the next frame (as in the above example). To rewind the file, you may
|
seek to the next frame (as in the above example). To rewind the file, you may
|
||||||
have to reopen it.
|
have to reopen it.
|
||||||
|
|
||||||
The following iterator class lets you to use the for-statement to loop over the
|
The following iterator class lets you use the for-statement to loop over the
|
||||||
sequence:
|
sequence:
|
||||||
|
|
||||||
A sequence iterator class
|
A sequence iterator class
|
||||||
|
|
|
@ -67,10 +67,10 @@ Many of Pillow's features require external libraries:
|
||||||
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
||||||
above uses liblcms2. Tested with **1.19** and **2.2**.
|
above uses liblcms2. Tested with **1.19** and **2.2**.
|
||||||
|
|
||||||
* **libwebp** provides the Webp format.
|
* **libwebp** provides the WebP format.
|
||||||
|
|
||||||
* Pillow has been tested with version **0.1.3**, which does not read
|
* Pillow has been tested with version **0.1.3**, which does not read
|
||||||
transparent webp files. Versions **0.3.0** and **0.4.0** support
|
transparent WebP files. Versions **0.3.0** and **0.4.0** support
|
||||||
transparency.
|
transparency.
|
||||||
|
|
||||||
* **tcl/tk** provides support for tkinter bitmap and photo images.
|
* **tcl/tk** provides support for tkinter bitmap and photo images.
|
||||||
|
@ -121,12 +121,17 @@ Prerequisites are installed on **Ubuntu 10.04 LTS** with::
|
||||||
$ sudo apt-get install libtiff4-dev libjpeg62-dev zlib1g-dev \
|
$ sudo apt-get install libtiff4-dev libjpeg62-dev zlib1g-dev \
|
||||||
libfreetype6-dev tcl8.5-dev tk8.5-dev python-tk
|
libfreetype6-dev tcl8.5-dev tk8.5-dev python-tk
|
||||||
|
|
||||||
Prerequisites are installed with on **Ubuntu 12.04 LTS** or **Raspian Wheezy
|
Prerequisites are installed on **Ubuntu 12.04 LTS** or **Raspian Wheezy
|
||||||
7.0** with::
|
7.0** with::
|
||||||
|
|
||||||
$ sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev \
|
$ sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev \
|
||||||
libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk
|
libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk
|
||||||
|
|
||||||
|
Prerequisites are installed on **Ubuntu 14.04 LTS** with::
|
||||||
|
|
||||||
|
$ sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev \
|
||||||
|
libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk
|
||||||
|
|
||||||
Prerequisites are installed on **Fedora 20** with::
|
Prerequisites are installed on **Fedora 20** with::
|
||||||
|
|
||||||
$ sudo yum install libtiff-devel libjpeg-devel libzip-devel freetype-devel \
|
$ sudo yum install libtiff-devel libjpeg-devel libzip-devel freetype-devel \
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
# requirements for working on docs
|
sphinx-better-theme
|
||||||
|
|
||||||
# install pillow from master if you're into that, but RtD needs this
|
## requirements for working on docs
|
||||||
pillow>=2.4.0
|
#
|
||||||
|
## install pillow from master if you're into that, but RtD needs this
|
||||||
Jinja2==2.7.1
|
#pillow>=2.4.0
|
||||||
MarkupSafe==0.18
|
#
|
||||||
Pygments==1.6
|
#Jinja2==2.7.1
|
||||||
Sphinx==1.1.3
|
#MarkupSafe==0.18
|
||||||
docopt==0.6.1
|
#Pygments==1.6
|
||||||
docutils==0.11
|
#Sphinx==1.1.3
|
||||||
wsgiref==0.1.2
|
#docopt==0.6.1
|
||||||
sphinx-better-theme==0.1.5
|
#docutils==0.11
|
||||||
|
#wsgiref==0.1.2
|
||||||
# livereload not strictly necessary but really useful (make livehtml)
|
#sphinx-better-theme==0.1.5
|
||||||
tornado==3.1.1
|
#
|
||||||
livereload==1.0.1
|
## livereload not strictly necessary but really useful (make livehtml)
|
||||||
|
#tornado==3.1.1
|
||||||
|
#livereload==1.0.1
|
||||||
|
|
|
@ -600,7 +600,6 @@ ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
double big_hypotenuse, small_hypotenuse, ratio_max, ratio_min;
|
double big_hypotenuse, small_hypotenuse, ratio_max, ratio_min;
|
||||||
int dxmin, dxmax, dymin, dymax;
|
int dxmin, dxmax, dymin, dymax;
|
||||||
Edge e[4];
|
Edge e[4];
|
||||||
int vertices[4][2];
|
|
||||||
|
|
||||||
DRAWINIT();
|
DRAWINIT();
|
||||||
|
|
||||||
|
|
0
libImaging/Jpeg2KEncode.c
Executable file → Normal file
0
libImaging/Jpeg2KEncode.c
Executable file → Normal file
Loading…
Reference in New Issue
Block a user