mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
Merge branch 'master' into icns-support
This commit is contained in:
commit
5dd67abd71
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -5,3 +5,11 @@ dist
|
|||
.tox
|
||||
*.so
|
||||
docs/_build
|
||||
|
||||
# Vim cruft
|
||||
.*.swp
|
||||
|
||||
#emacs
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
|
|
15
.travis.yml
15
.travis.yml
|
@ -4,19 +4,32 @@ language: python
|
|||
virtualenv:
|
||||
system_site_packages: true
|
||||
|
||||
notifications:
|
||||
irc: "chat.freenode.net#pil"
|
||||
|
||||
python:
|
||||
- 2.6
|
||||
- 2.7
|
||||
- 3.2
|
||||
- 3.3
|
||||
- "pypy"
|
||||
|
||||
install:
|
||||
- "sudo apt-get -qq install libfreetype6-dev liblcms2-dev libwebp-dev python-qt4 ghostscript libffi-dev"
|
||||
- "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake"
|
||||
- "pip install cffi"
|
||||
|
||||
# webp
|
||||
- pushd depends && ./install_webp.sh && popd
|
||||
|
||||
# openjpeg
|
||||
- pushd depends && ./install_openjpeg.sh && popd
|
||||
|
||||
script:
|
||||
- python setup.py clean
|
||||
- python setup.py build_ext --inplace
|
||||
- python selftest.py
|
||||
- python Tests/run.py
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: "pypy"
|
||||
|
|
39
CHANGES.rst
39
CHANGES.rst
|
@ -4,9 +4,42 @@ Changelog (Pillow)
|
|||
2.4.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Fixes for Jpeg encoding in Python 3, fixes #577
|
||||
[wiredfool]
|
||||
|
||||
- Added support for JPEG 2000
|
||||
[al45tair]
|
||||
|
||||
- Add more detailed error messages to Image.py
|
||||
[larsmans]
|
||||
|
||||
- Avoid conflicting _expand functions in PIL & MINGW, fixes #538
|
||||
[aclark]
|
||||
|
||||
- Merge from Philippe Lagadec’s OleFileIO_PL fork
|
||||
[vadmium]
|
||||
|
||||
- Fix ImageColor.getcolor
|
||||
[homm]
|
||||
|
||||
- Make ICO files work with the ImageFile.Parser interface, fixes #522
|
||||
[wiredfool]
|
||||
|
||||
- Handle 32bit compiled python on 64bit architecture
|
||||
[choppsv1]
|
||||
|
||||
- Fix support for characters >128 using .pcf or .pil fonts in Py3k. Fixes #505
|
||||
[wiredfool]
|
||||
|
||||
- Skip CFFI test earlier if it's not installed
|
||||
[wiredfool]
|
||||
|
||||
- Fixed opening and saving odd sized .pcx files, fixes #523
|
||||
[wiredfool]
|
||||
|
||||
- Fixed palette handling when converting from mode P->RGB->P
|
||||
[d_schmidt]
|
||||
|
||||
- Fixed saving mode P image as a PNG with transparency = palette color 0
|
||||
[d-schmidt]
|
||||
|
||||
|
@ -48,6 +81,12 @@ Changelog (Pillow)
|
|||
|
||||
- Prefer homebrew freetype over X11 freetype (but still allow both)
|
||||
[dmckeone]
|
||||
|
||||
2.3.1 (2014-03-14)
|
||||
------------------
|
||||
|
||||
- Fix insecure use of tempfile.mktemp (CVE-2014-1932 CVE-2014-1933)
|
||||
[wiredfool]
|
||||
|
||||
2.3.0 (2014-01-01)
|
||||
------------------
|
||||
|
|
|
@ -19,6 +19,7 @@ recursive-include Images *.psd
|
|||
recursive-include Images *.tar
|
||||
recursive-include Images *.webp
|
||||
recursive-include Images *.xpm
|
||||
recursive-include PIL *.md
|
||||
recursive-include Sane *.c
|
||||
recursive-include Sane *.py
|
||||
recursive-include Sane *.txt
|
||||
|
@ -27,9 +28,13 @@ recursive-include Sane README
|
|||
recursive-include Scripts *.py
|
||||
recursive-include Scripts README
|
||||
recursive-include Tests *.bin
|
||||
recursive-include Tests *.bmp
|
||||
recursive-include Tests *.eps
|
||||
recursive-include Tests *.gif
|
||||
recursive-include Tests *.gnuplot
|
||||
recursive-include Tests *.html
|
||||
recursive-include Tests *.icm
|
||||
recursive-include Tests *.ico
|
||||
recursive-include Tests *.jpg
|
||||
recursive-include Tests *.pcf
|
||||
recursive-include Tests *.pcx
|
||||
|
|
|
@ -67,8 +67,10 @@ def Ghostscript(tile, size, fp, scale=1):
|
|||
|
||||
import tempfile, os, subprocess
|
||||
|
||||
outfile = tempfile.mktemp()
|
||||
infile = tempfile.mktemp()
|
||||
out_fd, outfile = tempfile.mkstemp()
|
||||
os.close(out_fd)
|
||||
in_fd, infile = tempfile.mkstemp()
|
||||
os.close(in_fd)
|
||||
|
||||
with open(infile, 'wb') as f:
|
||||
fp.seek(offset)
|
||||
|
|
|
@ -237,7 +237,10 @@ def _save(im, fp, filename):
|
|||
# convert on the fly (EXPERIMENTAL -- I'm not sure PIL
|
||||
# should automatically convert images on save...)
|
||||
if Image.getmodebase(im.mode) == "RGB":
|
||||
imOut = im.convert("P")
|
||||
palette_size = 256
|
||||
if im.palette:
|
||||
palette_size = len(im.palette.getdata()[1]) // 3
|
||||
imOut = im.convert("P", palette=1, colors=palette_size)
|
||||
rawmode = "P"
|
||||
else:
|
||||
imOut = im.convert("L")
|
||||
|
@ -248,9 +251,13 @@ def _save(im, fp, filename):
|
|||
palette = im.encoderinfo["palette"]
|
||||
except KeyError:
|
||||
palette = None
|
||||
if im.palette:
|
||||
# use existing if possible
|
||||
palette = im.palette.getdata()[1]
|
||||
im.encoderinfo["optimize"] = im.encoderinfo.get("optimize", True)
|
||||
if im.encoderinfo["optimize"]:
|
||||
# When the mode is L, and we optimize, we end up with
|
||||
# im.mode == P and rawmode = L, which fails.
|
||||
# If we're optimizing the palette, we're going to be
|
||||
# in a rawmode of P anyway.
|
||||
rawmode = 'P'
|
||||
|
||||
header, usedPaletteColors = getheader(imOut, palette, im.encoderinfo)
|
||||
for s in header:
|
||||
|
@ -391,6 +398,9 @@ def getheader(im, palette=None, info=None):
|
|||
for i in range(len(imageBytes)):
|
||||
imageBytes[i] = newPositions[imageBytes[i]]
|
||||
im.frombytes(bytes(imageBytes))
|
||||
newPaletteBytes = paletteBytes + (768 - len(paletteBytes)) * b'\x00'
|
||||
im.putpalette(newPaletteBytes)
|
||||
im.palette = ImagePalette.ImagePalette("RGB", palette = paletteBytes, size = len(paletteBytes))
|
||||
|
||||
if not paletteBytes:
|
||||
paletteBytes = sourcePalette
|
||||
|
|
|
@ -222,6 +222,10 @@ class IcoImageFile(ImageFile.ImageFile):
|
|||
self.mode = im.mode
|
||||
self.size = im.size
|
||||
|
||||
|
||||
def load_seek(self):
|
||||
# Flage the ImageFile.Parser so that it just does all the decode at the end.
|
||||
pass
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
|
21
PIL/Image.py
21
PIL/Image.py
|
@ -504,14 +504,17 @@ class Image:
|
|||
self.readonly = 0
|
||||
|
||||
def _dump(self, file=None, format=None):
|
||||
import tempfile
|
||||
import tempfile, os
|
||||
if not file:
|
||||
file = tempfile.mktemp()
|
||||
f, file = tempfile.mkstemp(format or '')
|
||||
os.close(f)
|
||||
|
||||
self.load()
|
||||
if not format or format == "PPM":
|
||||
self.im.save_ppm(file)
|
||||
else:
|
||||
file = file + "." + format
|
||||
if file.endswith(format):
|
||||
file = file + "." + format
|
||||
self.save(file, format)
|
||||
return file
|
||||
|
||||
|
@ -734,7 +737,10 @@ class Image:
|
|||
|
||||
if mode == "P" and palette == ADAPTIVE:
|
||||
im = self.im.quantize(colors)
|
||||
return self._new(im)
|
||||
new = self._new(im)
|
||||
from PIL import ImagePalette
|
||||
new.palette = ImagePalette.raw("RGB", new.im.getpalette("RGB"))
|
||||
return new
|
||||
|
||||
# colorspace conversion
|
||||
if dither is None:
|
||||
|
@ -1959,7 +1965,7 @@ def fromarray(obj, mode=None):
|
|||
else:
|
||||
ndmax = 4
|
||||
if ndim > ndmax:
|
||||
raise ValueError("Too many dimensions.")
|
||||
raise ValueError("Too many dimensions: %d > %d." % (ndim, ndmax))
|
||||
|
||||
size = shape[1], shape[0]
|
||||
if strides is not None:
|
||||
|
@ -2012,7 +2018,7 @@ def open(fp, mode="r"):
|
|||
"""
|
||||
|
||||
if mode != "r":
|
||||
raise ValueError("bad mode")
|
||||
raise ValueError("bad mode %r" % mode)
|
||||
|
||||
if isPath(fp):
|
||||
filename = fp
|
||||
|
@ -2048,7 +2054,8 @@ def open(fp, mode="r"):
|
|||
#traceback.print_exc()
|
||||
pass
|
||||
|
||||
raise IOError("cannot identify image file")
|
||||
raise IOError("cannot identify image file %r"
|
||||
% (filename if filename else fp))
|
||||
|
||||
#
|
||||
# Image processing.
|
||||
|
|
|
@ -20,15 +20,6 @@
|
|||
from PIL import Image
|
||||
import re
|
||||
|
||||
|
||||
##
|
||||
# Convert color string to RGB tuple.
|
||||
#
|
||||
# @param color A CSS3-style colour string.
|
||||
# @return An RGB-tuple.
|
||||
# @exception ValueError If the color string could not be interpreted
|
||||
# as an RGB value.
|
||||
|
||||
def getrgb(color):
|
||||
"""
|
||||
Convert a color string to an RGB tuple. If the string cannot be parsed,
|
||||
|
@ -37,7 +28,7 @@ def getrgb(color):
|
|||
.. versionadded:: 1.1.4
|
||||
|
||||
:param color: A color string
|
||||
:return: ``(red, green, blue)``
|
||||
:return: ``(red, green, blue[, alpha])``
|
||||
"""
|
||||
try:
|
||||
rgb = colormap[color]
|
||||
|
@ -114,20 +105,21 @@ def getcolor(color, mode):
|
|||
.. versionadded:: 1.1.4
|
||||
|
||||
:param color: A color string
|
||||
:return: ``(red, green, blue)``
|
||||
:return: ``(graylevel [, alpha]) or (red, green, blue[, alpha])``
|
||||
"""
|
||||
# same as getrgb, but converts the result to the given mode
|
||||
color = getrgb(color)
|
||||
if mode == "RGB":
|
||||
return color
|
||||
if mode == "RGBA":
|
||||
if len(color) == 3:
|
||||
color = (color + (255,))
|
||||
r, g, b, a = color
|
||||
return r, g, b, a
|
||||
color, alpha = getrgb(color), 255
|
||||
if len(color) == 4:
|
||||
color, alpha = color[0:3], color[3]
|
||||
|
||||
if Image.getmodebase(mode) == "L":
|
||||
r, g, b = color
|
||||
return (r*299 + g*587 + b*114)//1000
|
||||
color = (r*299 + g*587 + b*114)//1000
|
||||
if mode[-1] == 'A':
|
||||
return (color, alpha)
|
||||
else:
|
||||
if mode[-1] == 'A':
|
||||
return color + (alpha,)
|
||||
return color
|
||||
|
||||
colormap = {
|
||||
|
|
|
@ -23,13 +23,14 @@ from PIL import Image, ImageColor
|
|||
class ImagePalette:
|
||||
"Color palette for palette mapped images"
|
||||
|
||||
def __init__(self, mode = "RGB", palette = None):
|
||||
def __init__(self, mode = "RGB", palette = None, size = 0):
|
||||
self.mode = mode
|
||||
self.rawmode = None # if set, palette contains raw data
|
||||
self.palette = palette or list(range(256))*len(self.mode)
|
||||
self.colors = {}
|
||||
self.dirty = None
|
||||
if len(self.mode)*256 != len(self.palette):
|
||||
if ((size == 0 and len(self.mode)*256 != len(self.palette)) or
|
||||
(size != 0 and size != len(self.palette))):
|
||||
raise ValueError("wrong palette size")
|
||||
|
||||
def getdata(self):
|
||||
|
|
|
@ -172,8 +172,8 @@ class IptcImageFile(ImageFile.ImageFile):
|
|||
self.fp.seek(offset)
|
||||
|
||||
# Copy image data to temporary file
|
||||
outfile = tempfile.mktemp()
|
||||
o = open(outfile, "wb")
|
||||
o_fd, outfile = tempfile.mkstemp(text=False)
|
||||
o = os.fdopen(o_fd)
|
||||
if encoding == "raw":
|
||||
# To simplify access to the extracted file,
|
||||
# prepend a PPM header
|
||||
|
|
|
@ -344,13 +344,17 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
# ALTERNATIVE: handle JPEGs via the IJG command line utilities
|
||||
|
||||
import tempfile, os
|
||||
file = tempfile.mktemp()
|
||||
os.system("djpeg %s >%s" % (self.filename, file))
|
||||
f, path = tempfile.mkstemp()
|
||||
os.close(f)
|
||||
if os.path.exists(self.filename):
|
||||
os.system("djpeg '%s' >'%s'" % (self.filename, path))
|
||||
else:
|
||||
raise ValueError("Invalid Filename")
|
||||
|
||||
try:
|
||||
self.im = Image.core.open_ppm(file)
|
||||
self.im = Image.core.open_ppm(path)
|
||||
finally:
|
||||
try: os.unlink(file)
|
||||
try: os.unlink(path)
|
||||
except: pass
|
||||
|
||||
self.mode = self.im.mode
|
||||
|
@ -438,7 +442,7 @@ samplings = {
|
|||
}
|
||||
|
||||
def convert_dict_qtables(qtables):
|
||||
qtables = [qtables[key] for key in xrange(len(qtables)) if qtables.has_key(key)]
|
||||
qtables = [qtables[key] for key in range(len(qtables)) if key in qtables]
|
||||
for idx, table in enumerate(qtables):
|
||||
qtables[idx] = [table[i] for i in zigzag_index]
|
||||
return qtables
|
||||
|
@ -500,7 +504,7 @@ def _save(im, fp, filename):
|
|||
except ValueError:
|
||||
raise ValueError("Invalid quantization table")
|
||||
else:
|
||||
qtables = [lines[s:s+64] for s in xrange(0, len(lines), 64)]
|
||||
qtables = [lines[s:s+64] for s in range(0, len(lines), 64)]
|
||||
if isinstance(qtables, (tuple, list, dict)):
|
||||
if isinstance(qtables, dict):
|
||||
qtables = convert_dict_qtables(qtables)
|
||||
|
|
141
PIL/OleFileIO-README.md
Normal file
141
PIL/OleFileIO-README.md
Normal file
|
@ -0,0 +1,141 @@
|
|||
OleFileIO_PL
|
||||
============
|
||||
|
||||
[OleFileIO_PL](http://www.decalage.info/python/olefileio) is a Python module to read [Microsoft OLE2 files (also called Structured Storage, Compound File Binary Format or Compound Document File Format)](http://en.wikipedia.org/wiki/Compound_File_Binary_Format), such as Microsoft Office documents, Image Composer and FlashPix files, Outlook messages, ...
|
||||
|
||||
This is an improved version of the OleFileIO module from [PIL](http://www.pythonware.com/products/pil/index.htm), the excellent Python Imaging Library, created and maintained by Fredrik Lundh. The API is still compatible with PIL, but I have improved the internal implementation significantly, with new features, bugfixes and a more robust design.
|
||||
|
||||
As far as I know, this module is now the most complete and robust Python implementation to read MS OLE2 files, portable on several operating systems. (please tell me if you know other similar Python modules)
|
||||
|
||||
WARNING: THIS IS (STILL) WORK IN PROGRESS.
|
||||
|
||||
Main improvements over PIL version of OleFileIO:
|
||||
------------------------------------------------
|
||||
|
||||
- Better compatibility with Python 2.6 (also compatible with Python 3.0+)
|
||||
- Support for files larger than 6.8MB
|
||||
- Robust: many checks to detect malformed files
|
||||
- Improved API
|
||||
- New features: metadata extraction, stream/storage timestamps
|
||||
- Added setup.py and install.bat to ease installation
|
||||
|
||||
News
|
||||
----
|
||||
|
||||
- 2013-07-24 v0.26: added methods to parse stream/storage timestamps, improved listdir to include storages, fixed parsing of direntry timestamps
|
||||
- 2013-05-27 v0.25: improved metadata extraction, properties parsing and exception handling, fixed [issue #12](https://bitbucket.org/decalage/olefileio_pl/issue/12/error-when-converting-timestamps-in-ole)
|
||||
- 2013-05-07 v0.24: new features to extract metadata (get\_metadata method and OleMetadata class), improved getproperties to convert timestamps to Python datetime
|
||||
- 2012-10-09: published [python-oletools](http://www.decalage.info/python/oletools), a package of analysis tools based on OleFileIO_PL
|
||||
- 2012-09-11 v0.23: added support for file-like objects, fixed [issue #8](https://bitbucket.org/decalage/olefileio_pl/issue/8/bug-with-file-object)
|
||||
- 2012-02-17 v0.22: fixed issues #7 (bug in getproperties) and #2 (added close method)
|
||||
- 2011-10-20: code hosted on bitbucket to ease contributions and bug tracking
|
||||
- 2010-01-24 v0.21: fixed support for big-endian CPUs, such as PowerPC Macs.
|
||||
- 2009-12-11 v0.20: small bugfix in OleFileIO.open when filename is not plain str.
|
||||
- 2009-12-10 v0.19: fixed support for 64 bits platforms (thanks to Ben G. and Martijn for reporting the bug)
|
||||
- see changelog in source code for more info.
|
||||
|
||||
Download:
|
||||
---------
|
||||
|
||||
The archive is available on [the project page](https://bitbucket.org/decalage/olefileio_pl/downloads).
|
||||
|
||||
|
||||
How to use this module:
|
||||
-----------------------
|
||||
|
||||
See sample code at the end of the module, and also docstrings.
|
||||
|
||||
Here are a few examples:
|
||||
|
||||
:::python
|
||||
import OleFileIO_PL
|
||||
|
||||
# Test if a file is an OLE container:
|
||||
assert OleFileIO_PL.isOleFile('myfile.doc')
|
||||
|
||||
# Open an OLE file from disk:
|
||||
ole = OleFileIO_PL.OleFileIO('myfile.doc')
|
||||
|
||||
# Get list of streams:
|
||||
print(ole.listdir())
|
||||
|
||||
# Test if known streams/storages exist:
|
||||
if ole.exists('worddocument'):
|
||||
print("This is a Word document.")
|
||||
print("size :", ole.get_size('worddocument'))
|
||||
if ole.exists('macros/vba'):
|
||||
print("This document seems to contain VBA macros.")
|
||||
|
||||
# Extract the "Pictures" stream from a PPT file:
|
||||
if ole.exists('Pictures'):
|
||||
pics = ole.openstream('Pictures')
|
||||
data = pics.read()
|
||||
f = open('Pictures.bin', 'wb')
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
# Extract metadata (new in v0.24) - see source code for all attributes:
|
||||
meta = ole.get_metadata()
|
||||
print('Author:', meta.author)
|
||||
print('Title:', meta.title)
|
||||
print('Creation date:', meta.create_time)
|
||||
# print all metadata:
|
||||
meta.dump()
|
||||
|
||||
# Close the OLE file:
|
||||
ole.close()
|
||||
|
||||
# Work with a file-like object (e.g. StringIO) instead of a file on disk:
|
||||
data = open('myfile.doc', 'rb').read()
|
||||
f = io.BytesIO(data)
|
||||
ole = OleFileIO_PL.OleFileIO(f)
|
||||
print(ole.listdir())
|
||||
ole.close()
|
||||
|
||||
|
||||
It can also be used as a script from the command-line to display the structure of an OLE file, for example:
|
||||
|
||||
OleFileIO_PL.py myfile.doc
|
||||
|
||||
A real-life example: [using OleFileIO_PL for malware analysis and forensics](http://blog.gregback.net/2011/03/using-remnux-for-forensic-puzzle-6/).
|
||||
|
||||
How to contribute:
|
||||
------------------
|
||||
|
||||
The code is available in [a Mercurial repository on bitbucket](https://bitbucket.org/decalage/olefileio_pl). You may use it to submit enhancements or to report any issue.
|
||||
|
||||
If you would like to help us improve this module, or simply provide feedback, you may also send an e-mail to decalage(at)laposte.net. You can help in many ways:
|
||||
|
||||
- test this module on different platforms / Python versions
|
||||
- find and report bugs
|
||||
- improve documentation, code samples, docstrings
|
||||
- write unittest test cases
|
||||
- provide tricky malformed files
|
||||
|
||||
How to report bugs:
|
||||
-------------------
|
||||
|
||||
To report a bug, for example a normal file which is not parsed correctly, please use the [issue reporting page](https://bitbucket.org/decalage/olefileio_pl/issues?status=new&status=open), or send an e-mail with an attachment containing the debugging output of OleFileIO_PL.
|
||||
|
||||
For this, launch the following command :
|
||||
|
||||
OleFileIO_PL.py -d -c file >debug.txt
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
OleFileIO_PL is open-source.
|
||||
|
||||
OleFileIO_PL changes are Copyright (c) 2005-2013 by Philippe Lagadec.
|
||||
|
||||
The Python Imaging Library (PIL) is
|
||||
|
||||
- Copyright (c) 1997-2005 by Secret Labs AB
|
||||
|
||||
- Copyright (c) 1995-2005 by Fredrik Lundh
|
||||
|
||||
By obtaining, using, and/or copying this software and/or its associated documentation, you agree that you have read, understood, and will comply with the following terms and conditions:
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Secret Labs AB or the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.
|
||||
|
||||
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2057
PIL/OleFileIO.py
2057
PIL/OleFileIO.py
File diff suppressed because it is too large
Load Diff
|
@ -55,12 +55,18 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
|
||||
if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
|
||||
raise SyntaxError("bad PCX image size")
|
||||
if Image.DEBUG:
|
||||
print ("BBox: %s %s %s %s" % bbox)
|
||||
|
||||
|
||||
# format
|
||||
version = i8(s[1])
|
||||
bits = i8(s[3])
|
||||
planes = i8(s[65])
|
||||
stride = i16(s,66)
|
||||
if Image.DEBUG:
|
||||
print ("PCX version %s, bits %s, planes %s, stride %s" %
|
||||
(version, bits, planes, stride))
|
||||
|
||||
self.info["dpi"] = i16(s,12), i16(s,14)
|
||||
|
||||
|
@ -98,7 +104,9 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
self.size = bbox[2]-bbox[0], bbox[3]-bbox[1]
|
||||
|
||||
bbox = (0, 0) + self.size
|
||||
|
||||
if Image.DEBUG:
|
||||
print ("size: %sx%s" % self.size)
|
||||
|
||||
self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
@ -126,6 +134,16 @@ def _save(im, fp, filename, check=0):
|
|||
|
||||
# bytes per plane
|
||||
stride = (im.size[0] * bits + 7) // 8
|
||||
# stride should be even
|
||||
stride = stride + (stride % 2)
|
||||
# Stride needs to be kept in sync with the PcxEncode.c version.
|
||||
# Ideally it should be passed in in the state, but the bytes value
|
||||
# gets overwritten.
|
||||
|
||||
|
||||
if Image.DEBUG:
|
||||
print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
|
||||
im.size[0], bits, stride))
|
||||
|
||||
# under windows, we could determine the current screen size with
|
||||
# "Image.core.display_mode()[1]", but I think that's overkill...
|
||||
|
|
|
@ -505,7 +505,7 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
|
|||
else:
|
||||
# check palette contents
|
||||
if im.palette:
|
||||
colors = len(im.palette.getdata()[1])//3
|
||||
colors = max(min(len(im.palette.getdata()[1])//3, 256), 2)
|
||||
else:
|
||||
colors = 256
|
||||
|
||||
|
|
|
@ -25,10 +25,23 @@ else:
|
|||
return bytes((i&255,))
|
||||
|
||||
# Input, le = little endian, be = big endian
|
||||
#TODO: replace with more readable struct.unpack equivalent
|
||||
def i16le(c, o=0):
|
||||
"""
|
||||
Converts a 2-bytes (16 bits) string to an integer.
|
||||
|
||||
c: string containing bytes to convert
|
||||
o: offset of bytes to convert in string
|
||||
"""
|
||||
return i8(c[o]) | (i8(c[o+1])<<8)
|
||||
|
||||
def i32le(c, o=0):
|
||||
"""
|
||||
Converts a 4-bytes (32 bits) string to an integer.
|
||||
|
||||
c: string containing bytes to convert
|
||||
o: offset of bytes to convert in string
|
||||
"""
|
||||
return i8(c[o]) | (i8(c[o+1])<<8) | (i8(c[o+2])<<16) | (i8(c[o+3])<<24)
|
||||
|
||||
def i16be(c, o=0):
|
||||
|
|
22
Sane/_sane.c
22
Sane/_sane.c
|
@ -916,10 +916,13 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
|
|||
call which returns SANE_STATUS_EOF in order to start
|
||||
a new frame.
|
||||
*/
|
||||
do {
|
||||
st = sane_read(self->h, buffer, READSIZE, &len);
|
||||
}
|
||||
while (st == SANE_STATUS_GOOD);
|
||||
if (st != SANE_STATUS_EOF)
|
||||
{
|
||||
do {
|
||||
st = sane_read(self->h, buffer, READSIZE, &len);
|
||||
}
|
||||
while (st == SANE_STATUS_GOOD);
|
||||
}
|
||||
if (st != SANE_STATUS_EOF)
|
||||
{
|
||||
Py_BLOCK_THREADS
|
||||
|
@ -937,10 +940,13 @@ SaneDev_snap(SaneDevObject *self, PyObject *args)
|
|||
}
|
||||
}
|
||||
/* enforce SANE_STATUS_EOF. Can be necessary for ADF scans for some backends */
|
||||
do {
|
||||
st = sane_read(self->h, buffer, READSIZE, &len);
|
||||
}
|
||||
while (st == SANE_STATUS_GOOD);
|
||||
if (st != SANE_STATUS_EOF)
|
||||
{
|
||||
do {
|
||||
st = sane_read(self->h, buffer, READSIZE, &len);
|
||||
}
|
||||
while (st == SANE_STATUS_GOOD);
|
||||
}
|
||||
if (st != SANE_STATUS_EOF)
|
||||
{
|
||||
sane_cancel(self->h);
|
||||
|
|
BIN
Tests/images/high_ascii_chars.png
Normal file
BIN
Tests/images/high_ascii_chars.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
Tests/images/python.ico
Normal file
BIN
Tests/images/python.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
Tests/images/test.colors.gif
Normal file
BIN
Tests/images/test.colors.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -3,7 +3,7 @@ from tester import *
|
|||
from PIL import Image
|
||||
import os
|
||||
|
||||
base = 'Tests/images/bmp/'
|
||||
base = os.path.join('Tests', 'images', 'bmp')
|
||||
|
||||
|
||||
def get_files(d, ext='.bmp'):
|
||||
|
@ -78,9 +78,9 @@ def test_good():
|
|||
|
||||
except Exception as msg:
|
||||
# there are three here that are unsupported:
|
||||
unsupported = ('Tests/images/bmp/g/rgb32bf.bmp',
|
||||
'Tests/images/bmp/g/pal8rle.bmp',
|
||||
'Tests/images/bmp/g/pal4rle.bmp')
|
||||
unsupported = (os.path.join(base, 'g', 'rgb32bf.bmp'),
|
||||
os.path.join(base, 'g', 'pal8rle.bmp'),
|
||||
os.path.join(base, 'g', 'pal4rle.bmp'))
|
||||
if f not in unsupported:
|
||||
assert_true(False, "Unsupported Image %s: %s" %(f,msg))
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
from tester import *
|
||||
|
||||
from PIL import Image, PyAccess
|
||||
|
||||
import test_image_putpixel as put
|
||||
import test_image_getpixel as get
|
||||
|
||||
|
||||
|
||||
try:
|
||||
import cffi
|
||||
except:
|
||||
skip()
|
||||
|
||||
from PIL import Image, PyAccess
|
||||
|
||||
import test_image_putpixel as put
|
||||
import test_image_getpixel as get
|
||||
|
||||
|
||||
Image.USE_CFFI_ACCESS = True
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ def test_roundtrip():
|
|||
|
||||
def test_roundtrip2():
|
||||
#see https://github.com/python-imaging/Pillow/issues/403
|
||||
out = 'temp.gif'#tempfile('temp.gif')
|
||||
out = tempfile('temp.gif')
|
||||
im = Image.open('Images/lena.gif')
|
||||
im2 = im.copy()
|
||||
im2.save(out)
|
||||
|
@ -46,3 +46,42 @@ def test_roundtrip2():
|
|||
|
||||
assert_image_similar(reread.convert('RGB'), lena(), 50)
|
||||
|
||||
|
||||
def test_palette_handling():
|
||||
# see https://github.com/python-imaging/Pillow/issues/513
|
||||
|
||||
im = Image.open('Images/lena.gif')
|
||||
im = im.convert('RGB')
|
||||
|
||||
im = im.resize((100,100), Image.ANTIALIAS)
|
||||
im2 = im.convert('P', palette=Image.ADAPTIVE, colors=256)
|
||||
|
||||
f = tempfile('temp.gif')
|
||||
im2.save(f, optimize=True)
|
||||
|
||||
reloaded = Image.open(f)
|
||||
|
||||
assert_image_similar(im, reloaded.convert('RGB'), 10)
|
||||
|
||||
def test_palette_434():
|
||||
# see https://github.com/python-imaging/Pillow/issues/434
|
||||
|
||||
def roundtrip(im, *args, **kwargs):
|
||||
out = tempfile('temp.gif')
|
||||
im.save(out, *args, **kwargs)
|
||||
reloaded = Image.open(out)
|
||||
|
||||
return [im, reloaded]
|
||||
|
||||
orig = "Tests/images/test.colors.gif"
|
||||
im = Image.open(orig)
|
||||
|
||||
assert_image_equal(*roundtrip(im))
|
||||
assert_image_equal(*roundtrip(im, optimize=True))
|
||||
|
||||
im = im.convert("RGB")
|
||||
# check automatic P conversion
|
||||
reloaded = roundtrip(im)[1].convert('RGB')
|
||||
assert_image_equal(im, reloaded)
|
||||
|
||||
|
||||
|
|
|
@ -10,9 +10,7 @@ codecs = dir(Image.core)
|
|||
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
|
||||
skip("jpeg support not available")
|
||||
|
||||
# sample jpeg stream
|
||||
file = "Images/lena.jpg"
|
||||
data = open(file, "rb").read()
|
||||
test_file = "Images/lena.jpg"
|
||||
|
||||
def roundtrip(im, **options):
|
||||
out = BytesIO()
|
||||
|
@ -30,7 +28,7 @@ def test_sanity():
|
|||
# internal version number
|
||||
assert_match(Image.core.jpeglib_version, "\d+\.\d+$")
|
||||
|
||||
im = Image.open(file)
|
||||
im = Image.open(test_file)
|
||||
im.load()
|
||||
assert_equal(im.mode, "RGB")
|
||||
assert_equal(im.size, (128, 128))
|
||||
|
@ -40,7 +38,7 @@ def test_sanity():
|
|||
|
||||
def test_app():
|
||||
# Test APP/COM reader (@PIL135)
|
||||
im = Image.open(file)
|
||||
im = Image.open(test_file)
|
||||
assert_equal(im.applist[0],
|
||||
("APP0", b"JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00"))
|
||||
assert_equal(im.applist[1], ("COM", b"Python Imaging Library"))
|
||||
|
@ -49,8 +47,8 @@ def test_app():
|
|||
def test_cmyk():
|
||||
# Test CMYK handling. Thanks to Tim and Charlie for test data,
|
||||
# Michael for getting me to look one more time.
|
||||
file = "Tests/images/pil_sample_cmyk.jpg"
|
||||
im = Image.open(file)
|
||||
f = "Tests/images/pil_sample_cmyk.jpg"
|
||||
im = Image.open(f)
|
||||
# the source image has red pixels in the upper left corner.
|
||||
c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]
|
||||
assert_true(c == 0.0 and m > 0.8 and y > 0.8 and k == 0.0)
|
||||
|
@ -66,7 +64,7 @@ def test_cmyk():
|
|||
|
||||
def test_dpi():
|
||||
def test(xdpi, ydpi=None):
|
||||
im = Image.open(file)
|
||||
im = Image.open(test_file)
|
||||
im = roundtrip(im, dpi=(xdpi, ydpi or xdpi))
|
||||
return im.info.get("dpi")
|
||||
assert_equal(test(72), (72, 72))
|
||||
|
@ -80,9 +78,9 @@ def test_icc():
|
|||
icc_profile = im1.info["icc_profile"]
|
||||
assert_equal(len(icc_profile), 3144)
|
||||
# Roundtrip via physical file.
|
||||
file = tempfile("temp.jpg")
|
||||
im1.save(file, icc_profile=icc_profile)
|
||||
im2 = Image.open(file)
|
||||
f = tempfile("temp.jpg")
|
||||
im1.save(f, icc_profile=icc_profile)
|
||||
im2 = Image.open(f)
|
||||
assert_equal(im2.info.get("icc_profile"), icc_profile)
|
||||
# Roundtrip via memory buffer.
|
||||
im1 = roundtrip(lena())
|
||||
|
@ -203,3 +201,9 @@ def test_exif():
|
|||
im = Image.open("Tests/images/pil_sample_rgb.jpg")
|
||||
info = im._getexif()
|
||||
assert_equal(info[305], 'Adobe Photoshop CS Macintosh')
|
||||
|
||||
|
||||
def test_quality_keep():
|
||||
im = Image.open("Images/lena.jpg")
|
||||
f = tempfile('temp.jpg')
|
||||
assert_no_exception(lambda: im.save(f, quality='keep'))
|
||||
|
|
|
@ -2,29 +2,30 @@ from tester import *
|
|||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def _roundtrip(im):
|
||||
f = tempfile("temp.pcx")
|
||||
im.save(f)
|
||||
im2 = Image.open(f)
|
||||
|
||||
assert_equal(im2.mode, im.mode)
|
||||
assert_equal(im2.size, im.size)
|
||||
assert_equal(im2.format, "PCX")
|
||||
assert_image_equal(im2, im)
|
||||
|
||||
def test_sanity():
|
||||
for mode in ('1', 'L', 'P', 'RGB'):
|
||||
_roundtrip(lena(mode))
|
||||
|
||||
file = tempfile("temp.pcx")
|
||||
|
||||
lena("1").save(file)
|
||||
|
||||
im = Image.open(file)
|
||||
im.load()
|
||||
assert_equal(im.mode, "1")
|
||||
assert_equal(im.size, (128, 128))
|
||||
assert_equal(im.format, "PCX")
|
||||
|
||||
lena("1").save(file)
|
||||
im = Image.open(file)
|
||||
|
||||
lena("L").save(file)
|
||||
im = Image.open(file)
|
||||
|
||||
lena("P").save(file)
|
||||
im = Image.open(file)
|
||||
|
||||
lena("RGB").save(file)
|
||||
im = Image.open(file)
|
||||
def test_odd():
|
||||
# see issue #523, odd sized images should have a stride that's even.
|
||||
# not that imagemagick or gimp write pcx that way.
|
||||
# we were not handling properly.
|
||||
for mode in ('1', 'L', 'P', 'RGB'):
|
||||
# larger, odd sized images are better here to ensure that
|
||||
# we handle interrupted scan lines properly.
|
||||
_roundtrip(lena(mode).resize((511,511)))
|
||||
|
||||
|
||||
def test_pil184():
|
||||
# Check reading of files where xmin/xmax is not zero.
|
||||
|
|
|
@ -22,10 +22,28 @@ def test_sanity():
|
|||
|
||||
font.save(tempname)
|
||||
|
||||
def test_draw():
|
||||
def xtest_draw():
|
||||
|
||||
font = ImageFont.load(tempname)
|
||||
image = Image.new("L", font.getsize(message), "white")
|
||||
draw = ImageDraw.Draw(image)
|
||||
draw.text((0, 0), message, font=font)
|
||||
# assert_signature(image, "7216c60f988dea43a46bb68321e3c1b03ec62aee")
|
||||
|
||||
def _test_high_characters(message):
|
||||
|
||||
font = ImageFont.load(tempname)
|
||||
image = Image.new("L", font.getsize(message), "white")
|
||||
draw = ImageDraw.Draw(image)
|
||||
draw.text((0, 0), message, font=font)
|
||||
|
||||
compare = Image.open('Tests/images/high_ascii_chars.png')
|
||||
assert_image_equal(image, compare)
|
||||
|
||||
def test_high_characters():
|
||||
message = "".join([chr(i+1) for i in range(140,232)])
|
||||
_test_high_characters(message)
|
||||
# accept bytes instances in Py3.
|
||||
if bytes is not str:
|
||||
_test_high_characters(message.encode('latin1'))
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@ from tester import *
|
|||
|
||||
from PIL import Image
|
||||
|
||||
if hasattr(sys, 'pypy_version_info'):
|
||||
# This takes _forever_ on pypy. Open Bug,
|
||||
# see https://github.com/python-imaging/Pillow/issues/484
|
||||
skip()
|
||||
|
||||
def test_sanity():
|
||||
|
||||
im = lena()
|
||||
|
|
|
@ -26,9 +26,29 @@ for color in list(ImageColor.colormap.keys()):
|
|||
|
||||
assert_equal((0, 0, 0), ImageColor.getcolor("black", "RGB"))
|
||||
assert_equal((255, 255, 255), ImageColor.getcolor("white", "RGB"))
|
||||
assert_equal((0, 255, 115), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGB"))
|
||||
Image.new("RGB", (1, 1), "white")
|
||||
|
||||
assert_equal((0, 0, 0, 255), ImageColor.getcolor("black", "RGBA"))
|
||||
assert_equal((255, 255, 255, 255), ImageColor.getcolor("white", "RGBA"))
|
||||
assert_equal((0, 255, 115, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGBA"))
|
||||
Image.new("RGBA", (1, 1), "white")
|
||||
|
||||
assert_equal(0, ImageColor.getcolor("black", "L"))
|
||||
assert_equal(255, ImageColor.getcolor("white", "L"))
|
||||
assert_equal(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L"))
|
||||
Image.new("L", (1, 1), "white")
|
||||
|
||||
assert_equal(0, ImageColor.getcolor("black", "1"))
|
||||
assert_equal(255, ImageColor.getcolor("white", "1"))
|
||||
# The following test is wrong, but is current behavior
|
||||
# The correct result should be 255 due to the mode 1
|
||||
assert_equal(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
|
||||
# Correct behavior
|
||||
# assert_equal(255, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
|
||||
Image.new("1", (1, 1), "white")
|
||||
|
||||
assert_equal((0, 255), ImageColor.getcolor("black", "LA"))
|
||||
assert_equal((255, 255), ImageColor.getcolor("white", "LA"))
|
||||
assert_equal((162, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA"))
|
||||
Image.new("LA", (1, 1), "white")
|
||||
|
|
|
@ -57,6 +57,13 @@ def test_parser():
|
|||
# https://github.com/python-imaging/Pillow/issues/78
|
||||
#assert_exception(IOError, lambda: roundtrip("PDF"))
|
||||
|
||||
def test_ico():
|
||||
with open('Tests/images/python.ico', 'rb') as f:
|
||||
data = f.read()
|
||||
p = ImageFile.Parser()
|
||||
p.feed(data)
|
||||
assert_equal((48,48), p.image.size)
|
||||
|
||||
def test_safeblock():
|
||||
|
||||
im1 = lena()
|
||||
|
|
|
@ -3,7 +3,7 @@ from tester import *
|
|||
from PIL import Image
|
||||
try:
|
||||
from PIL import ImageTk
|
||||
except ImportError as v:
|
||||
except (OSError, ImportError) as v:
|
||||
skip(v)
|
||||
|
||||
success()
|
||||
|
|
60
_imaging.c
60
_imaging.c
|
@ -846,7 +846,7 @@ _crop(ImagingObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
static PyObject*
|
||||
_expand(ImagingObject* self, PyObject* args)
|
||||
_expand_image(ImagingObject* self, PyObject* args)
|
||||
{
|
||||
int x, y;
|
||||
int mode = 0;
|
||||
|
@ -2239,30 +2239,66 @@ textwidth(ImagingFontObject* self, const unsigned char* text)
|
|||
return xsize;
|
||||
}
|
||||
|
||||
void _font_text_asBytes(PyObject* encoded_string, unsigned char** text){
|
||||
PyObject* bytes = NULL;
|
||||
|
||||
*text = NULL;
|
||||
|
||||
if (PyUnicode_CheckExact(encoded_string)){
|
||||
bytes = PyUnicode_AsLatin1String(encoded_string);
|
||||
} else if (PyBytes_Check(encoded_string)) {
|
||||
bytes = encoded_string;
|
||||
}
|
||||
if (bytes) {
|
||||
*text = (unsigned char*)PyBytes_AsString(bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x03000000
|
||||
/* likely case here is py2.x with an ordinary string.
|
||||
but this isn't defined in Py3.x */
|
||||
if (PyString_Check(encoded_string)) {
|
||||
*text = (unsigned char *)PyString_AsString(encoded_string);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
_font_getmask(ImagingFontObject* self, PyObject* args)
|
||||
{
|
||||
Imaging im;
|
||||
Imaging bitmap;
|
||||
int x, b;
|
||||
int i=0;
|
||||
int status;
|
||||
Glyph* glyph;
|
||||
|
||||
PyObject* encoded_string;
|
||||
|
||||
unsigned char* text;
|
||||
char* mode = "";
|
||||
if (!PyArg_ParseTuple(args, "s|s:getmask", &text, &mode))
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|s:getmask", &encoded_string, &mode)){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_font_text_asBytes(encoded_string, &text);
|
||||
if (!text) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
im = ImagingNew(self->bitmap->mode, textwidth(self, text), self->ysize);
|
||||
if (!im)
|
||||
if (!im) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b = 0;
|
||||
(void) ImagingFill(im, &b);
|
||||
|
||||
b = self->baseline;
|
||||
for (x = 0; *text; text++) {
|
||||
glyph = &self->glyphs[*text];
|
||||
for (x = 0; text[i]; i++) {
|
||||
glyph = &self->glyphs[text[i]];
|
||||
bitmap = ImagingCrop(
|
||||
self->bitmap,
|
||||
glyph->sx0, glyph->sy0, glyph->sx1, glyph->sy1
|
||||
|
@ -2279,7 +2315,6 @@ _font_getmask(ImagingFontObject* self, PyObject* args)
|
|||
x = x + glyph->dx;
|
||||
b = b + glyph->dy;
|
||||
}
|
||||
|
||||
return PyImagingNew(im);
|
||||
|
||||
failed:
|
||||
|
@ -2291,10 +2326,17 @@ static PyObject*
|
|||
_font_getsize(ImagingFontObject* self, PyObject* args)
|
||||
{
|
||||
unsigned char* text;
|
||||
if (!PyArg_ParseTuple(args, "s:getsize", &text))
|
||||
PyObject* encoded_string;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:getsize", &encoded_string))
|
||||
return NULL;
|
||||
|
||||
return Py_BuildValue("ii", textwidth(self, text), self->ysize);
|
||||
_font_text_asBytes(encoded_string, &text);
|
||||
if (!text) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("ii", textwidth(self, text), self->ysize);
|
||||
}
|
||||
|
||||
static struct PyMethodDef _font_methods[] = {
|
||||
|
@ -2954,7 +2996,7 @@ static struct PyMethodDef methods[] = {
|
|||
{"crackcode", (PyCFunction)_crackcode, 1},
|
||||
#endif
|
||||
{"crop", (PyCFunction)_crop, 1},
|
||||
{"expand", (PyCFunction)_expand, 1},
|
||||
{"expand", (PyCFunction)_expand_image, 1},
|
||||
{"filter", (PyCFunction)_filter, 1},
|
||||
{"histogram", (PyCFunction)_histogram, 1},
|
||||
#ifdef WITH_MODEFILTER
|
||||
|
|
18
depends/install_openjpeg.sh
Executable file
18
depends/install_openjpeg.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# install openjpeg
|
||||
|
||||
|
||||
if [ ! -f openjpeg-2.0.0.tar.gz ]; then
|
||||
wget 'https://openjpeg.googlecode.com/files/openjpeg-2.0.0.tar.gz'
|
||||
fi
|
||||
|
||||
rm -r openjpeg-2.0.0
|
||||
tar -xvzf openjpeg-2.0.0.tar.gz
|
||||
|
||||
|
||||
pushd openjpeg-2.0.0
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr . && make && sudo make install
|
||||
|
||||
popd
|
||||
|
18
depends/install_webp.sh
Executable file
18
depends/install_webp.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
# install webp
|
||||
|
||||
|
||||
if [ ! -f libwebp-0.4.0.tar.gz ]; then
|
||||
wget 'https://webp.googlecode.com/files/libwebp-0.4.0.tar.gz'
|
||||
fi
|
||||
|
||||
rm -r libwebp-0.4.0
|
||||
tar -xvzf libwebp-0.4.0.tar.gz
|
||||
|
||||
|
||||
pushd libwebp-0.4.0
|
||||
|
||||
./configure --prefix=/usr --enable-libwebpmux --enable-libwebpdemux && make && sudo make install
|
||||
|
||||
popd
|
||||
|
|
@ -105,7 +105,6 @@ Create JPEG thumbnails
|
|||
except IOError:
|
||||
print("cannot create thumbnail for", infile)
|
||||
|
||||
|
||||
It is important to note that the library doesn’t decode or load the raster data
|
||||
unless it really has to. When you open a file, the file header is read to
|
||||
determine the file format and extract things like mode, size, and other
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Pillow: a modern fork of PIL
|
||||
============================
|
||||
Pillow
|
||||
======
|
||||
|
||||
Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the
|
||||
Pillow is the 'friendly' PIL fork by Alex Clark and Contributors. PIL is the
|
||||
Python Imaging Library by Fredrik Lundh and Contributors.
|
||||
|
||||
.. image:: https://travis-ci.org/python-imaging/Pillow.png
|
||||
|
@ -15,7 +15,7 @@ Python Imaging Library by Fredrik Lundh and Contributors.
|
|||
:target: https://pypi.python.org/pypi/Pillow/
|
||||
:alt: Number of PyPI downloads
|
||||
|
||||
To start using Pillow, read the :doc:`installation
|
||||
To start using Pillow, please read the :doc:`installation
|
||||
instructions <installation>`.
|
||||
|
||||
If you can't find the information you need, try the old `PIL Handbook`_, but be
|
||||
|
|
|
@ -172,6 +172,15 @@ Python Wheels
|
|||
|
||||
$ pip install --use-wheel Pillow
|
||||
|
||||
If the above does not work, it's likely because we haven't uploaded a
|
||||
wheel for the latest version of Pillow. In that case, try pinning it
|
||||
to a specific version:
|
||||
|
||||
::
|
||||
|
||||
$ pip install --use-wheel Pillow==2.3.0
|
||||
|
||||
|
||||
Platform support
|
||||
----------------
|
||||
|
||||
|
@ -216,4 +225,6 @@ current versions of Linux, OS X, and Windows.
|
|||
+----------------------------------+-------------+------------------------------+------------------------------+-----------------------+
|
||||
| Windows 8 Pro |Yes | 2.6,2.7,3.2,3.3,3.4a3 | 2.2.0 |x86,x86-64 |
|
||||
+----------------------------------+-------------+------------------------------+------------------------------+-----------------------+
|
||||
| Windows 8.1 Pro |Yes | 2.6,2.7,3.2,3.3,3.4 | 2.3.0 |x86,x86-64 |
|
||||
+----------------------------------+-------------+------------------------------+------------------------------+-----------------------+
|
||||
|
||||
|
|
190
encode.c
190
encode.c
|
@ -33,13 +33,13 @@
|
|||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Common */
|
||||
/* Common */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int (*encode)(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
UINT8* buffer, int bytes);
|
||||
int (*cleanup)(ImagingCodecState state);
|
||||
struct ImagingCodecStateInstance state;
|
||||
Imaging im;
|
||||
|
@ -59,21 +59,21 @@ PyImaging_EncoderNew(int contextsize)
|
|||
|
||||
encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType);
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* Clear the encoder state */
|
||||
memset(&encoder->state, 0, sizeof(encoder->state));
|
||||
|
||||
/* Allocate encoder context */
|
||||
if (contextsize > 0) {
|
||||
context = (void*) calloc(1, contextsize);
|
||||
if (!context) {
|
||||
Py_DECREF(encoder);
|
||||
(void) PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
context = (void*) calloc(1, contextsize);
|
||||
if (!context) {
|
||||
Py_DECREF(encoder);
|
||||
(void) PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
context = 0;
|
||||
context = 0;
|
||||
|
||||
/* Initialize encoder context */
|
||||
encoder->state.context = context;
|
||||
|
@ -111,14 +111,14 @@ _encode(ImagingEncoderObject* encoder, PyObject* args)
|
|||
int bufsize = 16384;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i", &bufsize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
buf = PyBytes_FromStringAndSize(NULL, bufsize);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
status = encoder->encode(encoder->im, &encoder->state,
|
||||
(UINT8*) PyBytes_AsString(buf), bufsize);
|
||||
(UINT8*) PyBytes_AsString(buf), bufsize);
|
||||
|
||||
/* adjust string length to avoid slicing in encoder */
|
||||
if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0)
|
||||
|
@ -144,28 +144,28 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
|
|||
int bufsize = 16384;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|i", &fh, &bufsize))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* Allocate an encoder buffer */
|
||||
buf = (UINT8*) malloc(bufsize);
|
||||
if (!buf)
|
||||
return PyErr_NoMemory();
|
||||
return PyErr_NoMemory();
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
||||
do {
|
||||
|
||||
/* This replaces the inner loop in the ImageFile _save
|
||||
function. */
|
||||
/* This replaces the inner loop in the ImageFile _save
|
||||
function. */
|
||||
|
||||
status = encoder->encode(encoder->im, &encoder->state, buf, bufsize);
|
||||
status = encoder->encode(encoder->im, &encoder->state, buf, bufsize);
|
||||
|
||||
if (status > 0)
|
||||
if (write(fh, buf, status) < 0) {
|
||||
if (status > 0)
|
||||
if (write(fh, buf, status) < 0) {
|
||||
ImagingSectionLeave(&cookie);
|
||||
free(buf);
|
||||
return PyErr_SetFromErrno(PyExc_IOError);
|
||||
}
|
||||
free(buf);
|
||||
return PyErr_SetFromErrno(PyExc_IOError);
|
||||
}
|
||||
|
||||
} while (encoder->state.errcode == 0);
|
||||
|
||||
|
@ -192,39 +192,39 @@ _setimage(ImagingEncoderObject* encoder, PyObject* args)
|
|||
|
||||
/* FIXME: should publish the ImagingType descriptor */
|
||||
if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1))
|
||||
return NULL;
|
||||
return NULL;
|
||||
im = PyImaging_AsImaging(op);
|
||||
if (!im)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->im = im;
|
||||
|
||||
state = &encoder->state;
|
||||
|
||||
if (x0 == 0 && x1 == 0) {
|
||||
state->xsize = im->xsize;
|
||||
state->ysize = im->ysize;
|
||||
state->xsize = im->xsize;
|
||||
state->ysize = im->ysize;
|
||||
} else {
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
}
|
||||
|
||||
if (state->xsize <= 0 ||
|
||||
state->xsize + state->xoff > im->xsize ||
|
||||
state->ysize <= 0 ||
|
||||
state->ysize + state->yoff > im->ysize) {
|
||||
PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image");
|
||||
return NULL;
|
||||
state->xsize + state->xoff > im->xsize ||
|
||||
state->ysize <= 0 ||
|
||||
state->ysize + state->yoff > im->ysize) {
|
||||
PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate memory buffer (if bits field is set) */
|
||||
if (state->bits > 0) {
|
||||
state->bytes = (state->bits * state->xsize+7)/8;
|
||||
state->buffer = (UINT8*) malloc(state->bytes);
|
||||
if (!state->buffer)
|
||||
return PyErr_NoMemory();
|
||||
state->bytes = (state->bits * state->xsize+7)/8;
|
||||
state->buffer = (UINT8*) malloc(state->bytes);
|
||||
if (!state->buffer)
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
/* Keep a reference to the image object, to make sure it doesn't
|
||||
|
@ -245,13 +245,13 @@ static struct PyMethodDef methods[] = {
|
|||
};
|
||||
|
||||
static PyTypeObject ImagingEncoderType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ImagingEncoder", /*tp_name*/
|
||||
sizeof(ImagingEncoderObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ImagingEncoder", /*tp_name*/
|
||||
sizeof(ImagingEncoderObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
|
@ -289,9 +289,9 @@ get_packer(ImagingEncoderObject* encoder, const char* mode,
|
|||
|
||||
pack = ImagingFindPacker(mode, rawmode, &bits);
|
||||
if (!pack) {
|
||||
Py_DECREF(encoder);
|
||||
PyErr_SetString(PyExc_SystemError, "unknown raw mode");
|
||||
return -1;
|
||||
Py_DECREF(encoder);
|
||||
PyErr_SetString(PyExc_SystemError, "unknown raw mode");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encoder->state.shuffle = pack;
|
||||
|
@ -302,7 +302,7 @@ get_packer(ImagingEncoderObject* encoder, const char* mode,
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* EPS */
|
||||
/* EPS */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
|
@ -312,7 +312,7 @@ PyImaging_EpsEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
encoder = PyImaging_EncoderNew(0);
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->encode = ImagingEpsEncode;
|
||||
|
||||
|
@ -321,7 +321,7 @@ PyImaging_EpsEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* GIF */
|
||||
/* GIF */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
|
@ -334,14 +334,14 @@ PyImaging_GifEncoderNew(PyObject* self, PyObject* args)
|
|||
int bits = 8;
|
||||
int interlace = 0;
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits, &interlace))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE));
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->encode = ImagingGifEncode;
|
||||
|
||||
|
@ -353,7 +353,7 @@ PyImaging_GifEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* PCX */
|
||||
/* PCX */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
|
@ -364,15 +364,19 @@ PyImaging_PcxEncoderNew(PyObject* self, PyObject* args)
|
|||
char *mode;
|
||||
char *rawmode;
|
||||
int bits = 8;
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoder = PyImaging_EncoderNew(0);
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
if (encoder == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
if (get_packer(encoder, mode, rawmode) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoder->encode = ImagingPcxEncode;
|
||||
|
||||
|
@ -381,7 +385,7 @@ PyImaging_PcxEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* RAW */
|
||||
/* RAW */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
|
@ -395,14 +399,14 @@ PyImaging_RawEncoderNew(PyObject* self, PyObject* args)
|
|||
int ystep = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder = PyImaging_EncoderNew(0);
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->encode = ImagingRawEncode;
|
||||
|
||||
|
@ -414,7 +418,7 @@ PyImaging_RawEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* XBM */
|
||||
/* XBM */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
|
@ -424,10 +428,10 @@ PyImaging_XbmEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
encoder = PyImaging_EncoderNew(0);
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, "1", "1;R") < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->encode = ImagingXbmEncode;
|
||||
|
||||
|
@ -436,7 +440,7 @@ PyImaging_XbmEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* ZIP */
|
||||
/* ZIP */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
|
@ -475,16 +479,16 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder->encode = ImagingZipEncode;
|
||||
|
||||
if (rawmode[0] == 'P')
|
||||
/* disable filtering */
|
||||
((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE;
|
||||
/* disable filtering */
|
||||
((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE;
|
||||
|
||||
((ZIPSTATE*)encoder->state.context)->optimize = optimize;
|
||||
((ZIPSTATE*)encoder->state.context)->compress_level = compress_level;
|
||||
|
@ -498,7 +502,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* JPEG */
|
||||
/* JPEG */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef HAVE_LIBJPEG
|
||||
|
@ -506,15 +510,15 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
|||
/* We better define this encoder last in this file, so the following
|
||||
undef's won't mess things up for the Imaging library proper. */
|
||||
|
||||
#undef HAVE_PROTOTYPES
|
||||
#undef HAVE_STDDEF_H
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef UINT8
|
||||
#undef UINT16
|
||||
#undef UINT32
|
||||
#undef INT8
|
||||
#undef INT16
|
||||
#undef INT32
|
||||
#undef HAVE_PROTOTYPES
|
||||
#undef HAVE_STDDEF_H
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef UINT8
|
||||
#undef UINT16
|
||||
#undef UINT32
|
||||
#undef INT8
|
||||
#undef INT16
|
||||
#undef INT32
|
||||
|
||||
#include "Jpeg.h"
|
||||
|
||||
|
@ -607,14 +611,14 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
|||
&progressive, &smooth, &optimize, &streamtype,
|
||||
&xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size,
|
||||
&rawExif, &rawExifLen))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
qarrays = get_qtables_arrays(qtables);
|
||||
|
||||
|
@ -724,11 +728,11 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// While failes on 64 bit machines, complains that pos is an int instead of a Py_ssize_t
|
||||
// while (PyDict_Next(dir, &pos, &key, &value)) {
|
||||
for (pos=0;pos<d_size;pos++){
|
||||
key = PyList_GetItem(keys,pos);
|
||||
value = PyList_GetItem(values,pos);
|
||||
// While failes on 64 bit machines, complains that pos is an int instead of a Py_ssize_t
|
||||
// while (PyDict_Next(dir, &pos, &key, &value)) {
|
||||
for (pos=0;pos<d_size;pos++){
|
||||
key = PyList_GetItem(keys,pos);
|
||||
value = PyList_GetItem(values,pos);
|
||||
status = 0;
|
||||
TRACE(("Attempting to set key: %d\n", (int)PyInt_AsLong(key)));
|
||||
if (PyInt_Check(value)) {
|
||||
|
|
|
@ -57,7 +57,16 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
if (state->x >= state->bytes) {
|
||||
|
||||
if (state->bytes % state->xsize && state->bytes > state->xsize) {
|
||||
int bands = state->bytes / state->xsize;
|
||||
int stride = state->bytes / bands;
|
||||
int i;
|
||||
for (i=1; i< bands; i++) { // note -- skipping first band
|
||||
memmove(&state->buffer[i*state->xsize],
|
||||
&state->buffer[i*stride],
|
||||
state->xsize);
|
||||
}
|
||||
}
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* encoder for PCX data
|
||||
*
|
||||
* history:
|
||||
* 99-02-07 fl created
|
||||
* 99-02-07 fl created
|
||||
*
|
||||
* Copyright (c) Fredrik Lundh 1999.
|
||||
* Copyright (c) Secret Labs AB 1999.
|
||||
|
@ -26,23 +26,41 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
{
|
||||
UINT8* ptr;
|
||||
int this;
|
||||
int bytes_per_line = 0;
|
||||
int padding = 0;
|
||||
int stride = 0;
|
||||
int bpp = 0;
|
||||
int planes = 1;
|
||||
int i;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* sanity check */
|
||||
if (state->xsize <= 0 || state->ysize <= 0) {
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->bytes = (state->xsize*state->bits + 7) / 8;
|
||||
state->state = FETCH;
|
||||
|
||||
}
|
||||
|
||||
for (;;)
|
||||
bpp = state->bits;
|
||||
if (state->bits == 24){
|
||||
planes = 3;
|
||||
bpp = 8;
|
||||
}
|
||||
|
||||
bytes_per_line = (state->xsize*bpp + 7) / 8;
|
||||
/* The stride here needs to be kept in sync with the version in
|
||||
PcxImagePlugin.py. If it's not, the header and the body of the
|
||||
image will be out of sync and bad things will happen on decode.
|
||||
*/
|
||||
stride = bytes_per_line + (bytes_per_line % 2);
|
||||
|
||||
padding = stride - bytes_per_line;
|
||||
|
||||
|
||||
for (;;) {
|
||||
|
||||
switch (state->state) {
|
||||
case FETCH:
|
||||
|
@ -68,81 +86,103 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* fall through */
|
||||
|
||||
case ENCODE:
|
||||
|
||||
/* compress this line */
|
||||
|
||||
/* when we arrive here, "count" contains the number of
|
||||
bytes having the value of "LAST" that we've already
|
||||
seen */
|
||||
while (state->x < planes * bytes_per_line) {
|
||||
/* If we're encoding an odd width file, and we've
|
||||
got more than one plane, we need to pad each
|
||||
color row with padding bytes at the end. Since
|
||||
The pixels are stored RRRRRGGGGGBBBBB, so we need
|
||||
to have the padding be RRRRRPGGGGGPBBBBBP. Hence
|
||||
the double loop
|
||||
*/
|
||||
while (state->x % bytes_per_line) {
|
||||
|
||||
while (state->x < state->bytes) {
|
||||
|
||||
if (state->count == 63) {
|
||||
|
||||
/* this run is full; flush it */
|
||||
if (bytes < 2)
|
||||
return ptr - buf;
|
||||
*ptr++ = 0xff;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
|
||||
state->count = 0;
|
||||
|
||||
}
|
||||
|
||||
this = state->buffer[state->x];
|
||||
|
||||
if (this == state->LAST) {
|
||||
|
||||
/* extend the current run */
|
||||
state->x++;
|
||||
state->count++;
|
||||
|
||||
} else {
|
||||
|
||||
/* start a new run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1)
|
||||
if (state->count == 63) {
|
||||
/* this run is full; flush it */
|
||||
if (bytes < 2)
|
||||
return ptr - buf;
|
||||
*ptr++ = 0xff;
|
||||
*ptr++ = state->LAST;
|
||||
bytes--;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2)
|
||||
return ptr - buf;
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
}
|
||||
bytes -= 2;
|
||||
|
||||
state->count = 0;
|
||||
|
||||
}
|
||||
|
||||
state->LAST = this;
|
||||
state->count = 1;
|
||||
this = state->buffer[state->x];
|
||||
|
||||
state->x++;
|
||||
if (this == state->LAST) {
|
||||
/* extend the current run */
|
||||
state->x++;
|
||||
state->count++;
|
||||
|
||||
} else {
|
||||
/* start a new run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = state->LAST;
|
||||
bytes--;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
state->LAST = this;
|
||||
state->count = 1;
|
||||
|
||||
state->x++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end of line; flush the current run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1)
|
||||
return ptr - buf;
|
||||
*ptr++ = state->LAST;
|
||||
bytes--;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2)
|
||||
/* end of line; flush the current run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1 + padding) {
|
||||
return ptr - buf;
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
}
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
bytes--;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2 + padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
if (bytes < padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
/* add the padding */
|
||||
for (i=0;i<padding;i++){
|
||||
*ptr++=0;
|
||||
bytes--;
|
||||
}
|
||||
/* reset for the next color plane. */
|
||||
if (state->x < planes * bytes_per_line) {
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[state->x];
|
||||
state->x++;
|
||||
}
|
||||
}
|
||||
|
||||
/* read next line */
|
||||
state->state = FETCH;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
setup.py
5
setup.py
|
@ -81,7 +81,8 @@ def _read(file):
|
|||
|
||||
try:
|
||||
import _tkinter
|
||||
except ImportError:
|
||||
except (ImportError, OSError):
|
||||
# pypy emits an oserror
|
||||
_tkinter = None
|
||||
|
||||
|
||||
|
@ -225,7 +226,7 @@ class pil_build_ext(build_ext):
|
|||
_add_directory(include_dirs, "/usr/X11/include")
|
||||
|
||||
elif sys.platform.startswith("linux"):
|
||||
for platform_ in (plat.processor(), plat.architecture()[0]):
|
||||
for platform_ in (plat.architecture()[0], plat.processor()):
|
||||
|
||||
if not platform_:
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue
Block a user