mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	merge a year of master into winbuild
This commit is contained in:
		
						commit
						fd55099ffc
					
				
							
								
								
									
										2
									
								
								.landscape.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.landscape.yaml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					strictness: medium
 | 
				
			||||||
 | 
					test-warnings: yes
 | 
				
			||||||
							
								
								
									
										75
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								.travis.yml
									
									
									
									
									
								
							| 
						 | 
					@ -3,25 +3,26 @@ language: python
 | 
				
			||||||
notifications:
 | 
					notifications:
 | 
				
			||||||
  irc: "chat.freenode.net#pil"
 | 
					  irc: "chat.freenode.net#pil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
env: MAX_CONCURRENCY=4
 | 
					# Run slow PyPy* first, to give them a headstart and reduce waiting time.
 | 
				
			||||||
 | 
					# Run latest 3.x and 2.x next, to get quick compatibility results.
 | 
				
			||||||
 | 
					# Then run the remainder.
 | 
				
			||||||
python:
 | 
					python:
 | 
				
			||||||
  - "pypy"
 | 
					  - "pypy"
 | 
				
			||||||
  - "pypy3"
 | 
					  - "pypy3"
 | 
				
			||||||
  - 2.6
 | 
					  - 3.4
 | 
				
			||||||
  - 2.7
 | 
					  - 2.7
 | 
				
			||||||
 | 
					  - 2.6
 | 
				
			||||||
  - "2.7_with_system_site_packages" # For PyQt4
 | 
					  - "2.7_with_system_site_packages" # For PyQt4
 | 
				
			||||||
  - 3.2
 | 
					  - 3.2
 | 
				
			||||||
  - 3.3
 | 
					  - 3.3
 | 
				
			||||||
  - 3.4
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
  - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick lcov"
 | 
					  - "travis_retry sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick"
 | 
				
			||||||
  - "pip install cffi"
 | 
					  - "travis_retry pip install cffi"
 | 
				
			||||||
  - "pip install coveralls nose coveralls-merge"
 | 
					  - "travis_retry pip install coverage nose"
 | 
				
			||||||
  - "gem install coveralls-lcov"
 | 
					  - "travis_retry pip install pyroma"
 | 
				
			||||||
  - travis_retry pip install pyroma
 | 
					
 | 
				
			||||||
  - if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi
 | 
					  - if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then travis_retry pip install unittest2; fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # webp
 | 
					  # webp
 | 
				
			||||||
  - pushd depends && ./install_webp.sh && popd
 | 
					  - pushd depends && ./install_webp.sh && popd
 | 
				
			||||||
| 
						 | 
					@ -39,24 +40,72 @@ script:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
after_success:
 | 
					after_success:
 | 
				
			||||||
   # gather the coverage data
 | 
					   # gather the coverage data
 | 
				
			||||||
 | 
					  - travis_retry sudo apt-get -qq install lcov
 | 
				
			||||||
  - lcov --capture --directory . -b . --output-file coverage.info
 | 
					  - lcov --capture --directory . -b . --output-file coverage.info
 | 
				
			||||||
   # filter to remove system headers
 | 
					   # filter to remove system headers
 | 
				
			||||||
  - lcov --remove coverage.info '/usr/*' -o coverage.filtered.info
 | 
					  - lcov --remove coverage.info '/usr/*' -o coverage.filtered.info
 | 
				
			||||||
   # convert to json
 | 
					   # convert to json
 | 
				
			||||||
 | 
					  - travis_retry gem install coveralls-lcov
 | 
				
			||||||
  - coveralls-lcov -v -n coverage.filtered.info > coverage.c.json
 | 
					  - coveralls-lcov -v -n coverage.filtered.info > coverage.c.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - coverage report
 | 
					  - coverage report
 | 
				
			||||||
 | 
					  - travis_retry pip install coveralls-merge
 | 
				
			||||||
  - coveralls-merge coverage.c.json
 | 
					  - coveralls-merge coverage.c.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - travis_retry pip install pep8 pyflakes
 | 
				
			||||||
  - pip install pep8 pyflakes
 | 
					 | 
				
			||||||
  - pep8 --statistics --count PIL/*.py
 | 
					  - pep8 --statistics --count PIL/*.py
 | 
				
			||||||
  - pep8  --statistics --count Tests/*.py
 | 
					  - pep8  --statistics --count Tests/*.py
 | 
				
			||||||
 | 
					  - pyflakes *.py       | tee >(wc -l)
 | 
				
			||||||
  - pyflakes PIL/*.py   | tee >(wc -l)
 | 
					  - pyflakes PIL/*.py   | tee >(wc -l)
 | 
				
			||||||
  - pyflakes Tests/*.py | tee >(wc -l)
 | 
					  - pyflakes Tests/*.py | tee >(wc -l)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Coverage and quality reports on just the latest diff.
 | 
					    # Coverage and quality reports on just the latest diff.
 | 
				
			||||||
    # (Installation is very slow on Py3, so just do it for Py2.)
 | 
					    # (Installation is very slow on Py3, so just do it for Py2.)
 | 
				
			||||||
  - if [ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]; then Scripts/diffcover-install.sh; fi
 | 
					  - if [ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]; then Scripts/diffcover-install.sh; fi
 | 
				
			||||||
  - if [ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]; then Scripts/diffcover-run.sh; fi
 | 
					  - if [ ${TRAVIS_PYTHON_VERSION:0:1} == "2" ]; then Scripts/diffcover-run.sh; fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # after_all
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					      if [ "$TRAVIS_REPO_SLUG" = "python-pillow/Pillow" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
 | 
				
			||||||
 | 
					        curl -Lo travis_after_all.py https://raw.github.com/dmakhno/travis_after_all/master/travis_after_all.py
 | 
				
			||||||
 | 
					        python travis_after_all.py
 | 
				
			||||||
 | 
					        export $(cat .to_export_back)
 | 
				
			||||||
 | 
					        if [ "$BUILD_LEADER" = "YES" ]; then
 | 
				
			||||||
 | 
					          if [ "$BUILD_AGGREGATE_STATUS" = "others_succeeded" ]; then
 | 
				
			||||||
 | 
					            echo "All jobs succeded! Triggering OS X build..."
 | 
				
			||||||
 | 
					            # Trigger an OS X build at the pillow-wheels repo
 | 
				
			||||||
 | 
					            ./build_children.sh
 | 
				
			||||||
 | 
					          else
 | 
				
			||||||
 | 
					            echo "Some jobs failed"
 | 
				
			||||||
 | 
					          fi
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					      fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					after_failure:
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					      if [ "$TRAVIS_REPO_SLUG" = "python-pillow/Pillow" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
 | 
				
			||||||
 | 
					        curl -Lo travis_after_all.py https://raw.github.com/dmakhno/travis_after_all/master/travis_after_all.py
 | 
				
			||||||
 | 
					        python travis_after_all.py
 | 
				
			||||||
 | 
					        export $(cat .to_export_back)
 | 
				
			||||||
 | 
					        if [ "$BUILD_LEADER" = "YES" ]; then
 | 
				
			||||||
 | 
					          if [ "$BUILD_AGGREGATE_STATUS" = "others_failed" ]; then
 | 
				
			||||||
 | 
					            echo "All jobs failed"
 | 
				
			||||||
 | 
					          else
 | 
				
			||||||
 | 
					            echo "Some jobs failed"
 | 
				
			||||||
 | 
					          fi
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					      fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					after_script:
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					      if [ "$TRAVIS_REPO_SLUG" = "python-pillow/Pillow" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
 | 
				
			||||||
 | 
					        echo leader=$BUILD_LEADER status=$BUILD_AGGREGATE_STATUS
 | 
				
			||||||
 | 
					      fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					matrix:
 | 
				
			||||||
 | 
					  fast_finish: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  global:
 | 
				
			||||||
 | 
					    # travis encrypt AUTH_TOKEN=
 | 
				
			||||||
 | 
					    secure: "Vzm7aG1Qv0SDQcqiPzZMedNLn5ZmpL7IzF0DYnqcD+/l+zmKU22SnJBcX0uVXumo+r7eZfpsShpqfcdsZvMlvmQnwz+Y6AGKQru9tCKZbTMnuRjWKKXekC+tr8Xt9CKvRVtte5PyXW31paxUI3/e+fQGBwoFjEEC+6EpEOjeRfE="
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										318
									
								
								CHANGES.rst
									
									
									
									
									
								
							
							
						
						
									
										318
									
								
								CHANGES.rst
									
									
									
									
									
								
							| 
						 | 
					@ -1,10 +1,283 @@
 | 
				
			||||||
Changelog (Pillow)
 | 
					Changelog (Pillow)
 | 
				
			||||||
==================
 | 
					==================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2.6.0 (unreleased)
 | 
					2.9.0 (Unreleased)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fixed CVE-2014-3598, a DOS in the Jpeg2KImagePlugin (backport)
 | 
					- Provide n_frames attribute to multi-frame formats #1261
 | 
				
			||||||
 | 
					  [anntzer, radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Add duration and loop set to GifImagePlugin #1172, #1269
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Ico files are little endian #1232
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Upgrade olefile from 0.30 to 0.42b #1226
 | 
				
			||||||
 | 
					  [radarhere, decalage2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Setting transparency value to 0 when the tRNS contains only null byte(s) #1239
 | 
				
			||||||
 | 
					  [juztin]
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					- Separated out feature checking from selftest #1233
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Style/health fixes
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Update WebP from 0.4.1 to 0.4.3 #1235
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Release GIL during image load (decode) #1224
 | 
				
			||||||
 | 
					  [lkesteloot]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Added icns save #1185
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix putdata memory leak #1196
 | 
				
			||||||
 | 
					  [benoit-pierre]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Keep user-specified ordering of icon sizes #1193
 | 
				
			||||||
 | 
					  [karimbahgat]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Tiff: allow writing floating point tag values #1113
 | 
				
			||||||
 | 
					  [bpedersen2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2.8.2 (2015-06-06)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Bug fix: Fixed Tiff handling of bad EXIF data
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2.8.1 (2015-04-02)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Bug fix: Catch struct.error on invalid JPEG, fixes #1163
 | 
				
			||||||
 | 
					  [wiredfool, hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2.8.0 (2015-04-01)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix 32-bit BMP loading (RGBA or RGBX)
 | 
				
			||||||
 | 
					  [artscoop]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix UnboundLocalError in ImageFile #1131
 | 
				
			||||||
 | 
					  [davarisg]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Re-enable test image caching
 | 
				
			||||||
 | 
					  [hugovk, homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix: Cannot identify EPS images, fixes #1104
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Configure setuptools to run nosetests, fixes #729
 | 
				
			||||||
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Style/health fixes
 | 
				
			||||||
 | 
					  [radarhere, hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Add support for HTTP response objects to Image.open()
 | 
				
			||||||
 | 
					  [mfitzp]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Improve reference docs for PIL.ImageDraw.Draw.pieslice() #1145
 | 
				
			||||||
 | 
					  [audreyr]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Added copy method font_variant() and accessible properties to truetype() #1123
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix ImagingEffectNoise #1128
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Remove unreachable code
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Let Python do the endian stuff + tests #1121
 | 
				
			||||||
 | 
					  [amoibos, radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix webp decode memory leak #1114
 | 
				
			||||||
 | 
					  [benoit-pierre]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fast path for opaque pixels in RGBa unpacker #1088
 | 
				
			||||||
 | 
					  [bgilbert]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Enable basic support for 'RGBa' raw encoding/decoding #1096
 | 
				
			||||||
 | 
					  [immerrr]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix pickling L mode images with no palette, #1095
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- iPython display hook #1091
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Adjust buffer size when quality=keep, fixes #148 (again)
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix for corrupted bitmaps embedded in truetype fonts. #1072 
 | 
				
			||||||
 | 
					  [jackyyf, wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2.7.0 (2015-01-01)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Split Sane into a separate repo: https://github.com/python-pillow/Sane
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Look for OSX and Linux fonts in common places. #1054
 | 
				
			||||||
 | 
					  [charleslaw]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix CVE-2014-9601, potential PNG decompression DOS #1060
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Use underscores, not spaces, in TIFF tag kwargs. #1044, #1058
 | 
				
			||||||
 | 
					  [anntzer, hugovk]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Update PSDraw for Python3, add tests. #1055
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Use Bicubic filtering by default for thumbnails. Don't use Jpeg Draft mode for thumbnails. #1029
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Fix MSVC compiler error: Use Py_ssize_t instead of ssize_t #1051
 | 
				
			||||||
 | 
					  [cgohlke]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix compiler error: MSVC needs variables defined at the start of the block #1048
 | 
				
			||||||
 | 
					  [cgohlke]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The GIF Palette optimization algorithm is only applicable to mode='P' or 'L' #993
 | 
				
			||||||
 | 
					  [moriyoshi]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Use PySide as an alternative to PyQt4/5.
 | 
				
			||||||
 | 
					  [holg]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Replace affine-based im.resize implementation with convolution-based im.stretch #997
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Replace Gaussian Blur implementation with iterated fast box blur. #961  Note: Radius parameter is interpreted differently than before.
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Better docs explaining import _imaging failure #1016, build #1017, mode #1018, PyAccess, PixelAccess objects #1019 Image.quantize #1020 and Image.save #1021
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix for saving TIFF image into an io.BytesIO buffer #1011
 | 
				
			||||||
 | 
					  [mfergie]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Fix antialias compilation on debug versions of Python #1010
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix for Image.putdata segfault #1009
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Ico save, additional tests #1007
 | 
				
			||||||
 | 
					  [exherb]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Use PyQt4 if it has already been imported, otherwise prefer PyQt5. #1003
 | 
				
			||||||
 | 
					  [AurelienBallier]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Speedup resample implementation up to 2.5 times. #977
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Speed up rotation by using cache aware loops, added transpose to rotations. #994
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix Bicubic interpolation #970
 | 
				
			||||||
 | 
					  [homm]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Support for 4-bit greyscale TIFF images #980
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 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.2 (2015-01-01)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix CVE-2014-9601, potential PNG decompression DOS #1060 
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix Regression in PyPy 2.4 in streamio  #958
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2.6.1 (2014-10-11)
 | 
				
			||||||
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix SciPy regression in Image.resize #945
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Fix manifest to include all test files.
 | 
				
			||||||
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Use redistributable ICC profiles for testing, skip if not available #923
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Additional documentation for JPEG info and save options #890
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix JPEG Encoding memory leak when exif or qtables were specified
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					- Image.tobytes() and Image.tostring() documentation update #916 #917
 | 
				
			||||||
 | 
					  [mgedmin]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- On Windows, do not execute convert.exe without specifying path #912
 | 
				
			||||||
 | 
					  [cgohlke]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix msvc build error #911
 | 
				
			||||||
 | 
					  [cgohlke]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix for handling P + transparency -> RGBA conversions #904
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Retain alpha in ImageEnhance operations #909
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Jpeg2k Decode/encode memory leak fix #898
 | 
				
			||||||
 | 
					  [joshware, wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- EpsFilePlugin Speed improvements #886
 | 
				
			||||||
 | 
					  [wiredfool, karstenw]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Don't resize if already the right size #892
 | 
				
			||||||
 | 
					  [radarhere]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix for reading multipage TIFFs #885
 | 
				
			||||||
 | 
					  [kostrom, wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Correctly handle saving gray and CMYK JPEGs with quality=keep #857
 | 
				
			||||||
 | 
					  [etienned]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Correct duplicate Tiff Metadata and Exif tag values
 | 
				
			||||||
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Windows fixes #871
 | 
				
			||||||
 | 
					  [wiredfool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fix TGA files with image ID field #856
 | 
				
			||||||
 | 
					  [megabuz]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fixed wrong P-mode of small, unoptimized L-mode GIF #843
 | 
				
			||||||
 | 
					  [uvNikita]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Fixed CVE-2014-3598, a DOS in the Jpeg2KImagePlugin
 | 
				
			||||||
  [Andrew Drake]
 | 
					  [Andrew Drake]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fixed CVE-2014-3589, a DOS in the IcnsImagePlugin
 | 
					- Fixed CVE-2014-3589, a DOS in the IcnsImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -49,7 +322,7 @@ Changelog (Pillow)
 | 
				
			||||||
- Added docs for ExifTags
 | 
					- Added docs for ExifTags
 | 
				
			||||||
  [Wintermute3]
 | 
					  [Wintermute3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, ImagePalette, IptcImagePlugin, SpiderImagePlugin, SgiImagePlugin, XpmImagePlugin and _util
 | 
					- More tests for CurImagePlugin, DcxImagePlugin, Effects.c, GimpGradientFile, ImageFont, ImageMath, ImagePalette, IptcImagePlugin, SpiderImagePlugin, SgiImagePlugin, XpmImagePlugin and _util
 | 
				
			||||||
  [hugovk]
 | 
					  [hugovk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fix return value of FreeTypeFont.textsize() does not include font offsets
 | 
					- Fix return value of FreeTypeFont.textsize() does not include font offsets
 | 
				
			||||||
| 
						 | 
					@ -109,7 +382,7 @@ Changelog (Pillow)
 | 
				
			||||||
  [wirefool]
 | 
					  [wirefool]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Top level flake8 fixes #741
 | 
					- Top level flake8 fixes #741
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Remove obsolete Animated Raster Graphics (ARG) support
 | 
					- Remove obsolete Animated Raster Graphics (ARG) support
 | 
				
			||||||
  [hugovk]
 | 
					  [hugovk]
 | 
				
			||||||
| 
						 | 
					@ -238,7 +511,7 @@ Changelog (Pillow)
 | 
				
			||||||
  [larsmans]
 | 
					  [larsmans]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Avoid conflicting _expand functions in PIL & MINGW, fixes #538
 | 
					- Avoid conflicting _expand functions in PIL & MINGW, fixes #538
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Merge from Philippe Lagadec’s OleFileIO_PL fork
 | 
					- Merge from Philippe Lagadec’s OleFileIO_PL fork
 | 
				
			||||||
  [vadmium]
 | 
					  [vadmium]
 | 
				
			||||||
| 
						 | 
					@ -653,13 +926,13 @@ Changelog (Pillow)
 | 
				
			||||||
  [blueyed]
 | 
					  [blueyed]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Package cleanup and additional documentation
 | 
					- Package cleanup and additional documentation
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.7.4 (2011-07-21)
 | 
					1.7.4 (2011-07-21)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fix brown bag release
 | 
					- Fix brown bag release
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.7.3 (2011-07-20)
 | 
					1.7.3 (2011-07-20)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
| 
						 | 
					@ -671,19 +944,19 @@ Changelog (Pillow)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Bug fix: Python 2.4 compat
 | 
					- Bug fix: Python 2.4 compat
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.7.1 (2011-05-31)
 | 
					1.7.1 (2011-05-31)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- More multi-arch support
 | 
					- More multi-arch support
 | 
				
			||||||
  [SteveM, regebro, barry, aclark]
 | 
					  [SteveM, regebro, barry, aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.7.0 (2011-05-27)
 | 
					1.7.0 (2011-05-27)
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Add support for multi-arch library directory /usr/lib/x86_64-linux-gnu
 | 
					- Add support for multi-arch library directory /usr/lib/x86_64-linux-gnu
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.6 (12/01/2010)
 | 
					1.6 (12/01/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
| 
						 | 
					@ -692,28 +965,28 @@ Changelog (Pillow)
 | 
				
			||||||
  [elro]
 | 
					  [elro]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Doc fixes
 | 
					- Doc fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.5 (11/28/2010)
 | 
					1.5 (11/28/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Module and package fixes
 | 
					- Module and package fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.4 (11/28/2010)
 | 
					1.4 (11/28/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Doc fixes
 | 
					- Doc fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.3 (11/28/2010)
 | 
					1.3 (11/28/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Add support for /lib64 and /usr/lib64 library directories on Linux
 | 
					- Add support for /lib64 and /usr/lib64 library directories on Linux
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Doc fixes
 | 
					- Doc fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.2 (08/02/2010)
 | 
					1.2 (08/02/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
| 
						 | 
					@ -722,26 +995,29 @@ Changelog (Pillow)
 | 
				
			||||||
  [jezdez]
 | 
					  [jezdez]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Doc fixes
 | 
					- Doc fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.1 (07/31/2010)
 | 
					1.1 (07/31/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Removed setuptools_hg requirement
 | 
					- Removed setuptools_hg requirement
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Doc fixes
 | 
					- Doc fixes
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.0 (07/30/2010)
 | 
					1.0 (07/30/2010)
 | 
				
			||||||
----------------
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Remove support for ``import Image``, etc. from the standard namespace. ``from PIL import Image`` etc. now required.
 | 
					- Remove support for ``import Image``, etc. from the standard namespace. ``from PIL import Image`` etc. now required.
 | 
				
			||||||
- Forked PIL based on `Hanno Schlichting's re-packaging <http://dist.plone.org/thirdparty/PIL-1.1.7.tar.gz>`_
 | 
					- Forked PIL based on `Hanno Schlichting's re-packaging <http://dist.plone.org/thirdparty/PIL-1.1.7.tar.gz>`_
 | 
				
			||||||
  [aclark]
 | 
					  [aclark4life]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. Note:: What follows is the original PIL 1.1.7 CHANGES
 | 
					.. Note:: What follows is the original PIL 1.1.7 CHANGES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					0.2b5 - 1.1.7 (1995-2010)
 | 
				
			||||||
 | 
					-------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
::
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    -*- coding: utf-8 -*-
 | 
					    -*- coding: utf-8 -*-
 | 
				
			||||||
| 
						 | 
					@ -1601,7 +1877,7 @@ Changelog (Pillow)
 | 
				
			||||||
    (1.1.2c1 and 1.1.2 final released)
 | 
					    (1.1.2c1 and 1.1.2 final released)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    + Adapted to Python 2.1.  Among other things, all uses of the
 | 
					    + Adapted to Python 2.1.  Among other things, all uses of the
 | 
				
			||||||
      "regex" module has been repleased with "re".
 | 
					      "regex" module have been replaced with "re".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    + Fixed attribute error when reading large PNG files (this bug
 | 
					    + Fixed attribute error when reading large PNG files (this bug
 | 
				
			||||||
      was introduced in maintenance code released after the 1.1.1
 | 
					      was introduced in maintenance code released after the 1.1.1
 | 
				
			||||||
| 
						 | 
					@ -2225,7 +2501,7 @@ Changelog (Pillow)
 | 
				
			||||||
                    the default value is 75.
 | 
					                    the default value is 75.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          JPEG	smooth		smooth dithered images.  value
 | 
					          JPEG	smooth		smooth dithered images.  value
 | 
				
			||||||
                    is strengh (1-100).  default is
 | 
					                    is strength (1-100).  default is
 | 
				
			||||||
                    off (0).
 | 
					                    off (0).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          PNG	optimize	minimize output file at the
 | 
					          PNG	optimize	minimize output file at the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +1,29 @@
 | 
				
			||||||
# Contributing
 | 
					# Contributing to Pillow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Fixes, Features and Changes
 | 
					Bug fixes, feature additions, tests, documentation and more can be contributed via [issues](https://github.com/python-pillow/Pillow/issues) and/or [pull requests](https://github.com/python-pillow/Pillow/issues). All contributions are welcome.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Send a pull request. We'll generally want documentation and [tests](Tests/README.rst) for new features. Tests or documentation on their own are also welcomed. Feel free to ask questions as an [issue](https://github.com/python-pillow/Pillow/issues/new) or on IRC (irc.freenode.net, #pil)
 | 
					## Bug fixes, feature additions, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Fork the repo
 | 
					Please send a pull request to the master branch. Please include [documentation](http://pillow.readthedocs.org) and [tests](Tests/README.rst) for new features. Tests or documentation without bug fixes or feature additions are welcome too. Feel free to ask questions [via issues](https://github.com/python-pillow/Pillow/issues/new) or irc://irc.freenode.net#pil
 | 
				
			||||||
- Make a branch
 | 
					 | 
				
			||||||
- Add your changes + Tests
 | 
					 | 
				
			||||||
- Run the test suite. Try to run on both Python 2.x and 3.x, or you'll get tripped up. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request. 
 | 
					 | 
				
			||||||
- Push to your fork, and make a pull request. 
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
A few guidelines:
 | 
					- Fork the Pillow repository.
 | 
				
			||||||
- Try to keep any code commits clean and separate from reformatting commits.
 | 
					- Create a branch from master.
 | 
				
			||||||
- All new code is going to need tests. 
 | 
					- Develop bug fixes, features, tests, etc.
 | 
				
			||||||
- Try to follow PEP8. 
 | 
					- Run the test suite on both Python 2.x and 3.x. You can enable [Travis CI on your repo](https://travis-ci.org/profile/) to catch test failures prior to the pull request, and [Coveralls](https://coveralls.io/repos/new) to see if the changed code is covered by tests.
 | 
				
			||||||
 | 
					- Create a pull request to pull the changes from your branch to the Pillow master.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Bugs
 | 
					### Guidelines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When reporting bugs, please include example code that reproduces the issue, and if possible a problem image. The best reproductions are self-contained scripts that pull in as few dependencies as possible. An entire Django stack is harder to handle. 
 | 
					- Separate code commits from reformatting commits.
 | 
				
			||||||
 | 
					- Provide tests for any newly added code.
 | 
				
			||||||
 | 
					- Follow PEP8.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Reporting Issues
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When reporting issues, please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. The best reproductions are self-contained scripts with minimal dependencies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Provide details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Let us know:
 | 
					 | 
				
			||||||
- What did you do?
 | 
					- What did you do?
 | 
				
			||||||
- What did you expect to happen?
 | 
					- What did you expect to happen?
 | 
				
			||||||
- What actually happened?
 | 
					- What actually happened?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										32
									
								
								MANIFEST.in
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								MANIFEST.in
									
									
									
									
									
								
							| 
						 | 
					@ -1,40 +1,22 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
include *.c
 | 
					include *.c
 | 
				
			||||||
include *.h
 | 
					include *.h
 | 
				
			||||||
include *.md
 | 
					include *.md
 | 
				
			||||||
include *.py
 | 
					include *.py
 | 
				
			||||||
 | 
					include *.sh
 | 
				
			||||||
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 LICENSE
 | 
				
			||||||
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 *.py
 | 
					 | 
				
			||||||
recursive-include Sane *.rst
 | 
					 | 
				
			||||||
recursive-include Sane *.txt
 | 
					 | 
				
			||||||
recursive-include Sane CHANGES
 | 
					 | 
				
			||||||
recursive-include Sane README
 | 
					 | 
				
			||||||
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 +26,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,15 +53,16 @@ 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
 | 
				
			||||||
recursive-include Tests *.txt
 | 
					recursive-include Tests *.txt
 | 
				
			||||||
recursive-include Tests *.webp
 | 
					recursive-include Tests *.webp
 | 
				
			||||||
recursive-include Tests *.xpm
 | 
					recursive-include Tests *.xpm
 | 
				
			||||||
 | 
					recursive-include Tests *.msp
 | 
				
			||||||
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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										101
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
					@ -1,28 +1,5 @@
 | 
				
			||||||
.PHONY: pre clean install test inplace coverage test-dep help docs livedocs
 | 
					# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
 | 
				
			||||||
 | 
					.PHONY: clean coverage doc docserve help inplace install install-req release-test sdist test upload upload-test
 | 
				
			||||||
help:
 | 
					 | 
				
			||||||
	@echo "Please use \`make <target>' where <target> is one of"
 | 
					 | 
				
			||||||
	@echo "  html       to make standalone HTML files"
 | 
					 | 
				
			||||||
	@echo "  clean		remove build products"
 | 
					 | 
				
			||||||
	@echo "  install	make and install"
 | 
					 | 
				
			||||||
	@echo "  test		run tests on installed pillow"
 | 
					 | 
				
			||||||
	@echo "  inplace	make inplace extension" 
 | 
					 | 
				
			||||||
	@echo "  coverage	run coverage test (in progress)"
 | 
					 | 
				
			||||||
	@echo "  docs		make html docs"
 | 
					 | 
				
			||||||
	@echo "  docserver	run an http server on the docs directory"
 | 
					 | 
				
			||||||
	@echo "  test-dep	install coveraget and test dependencies"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pre:
 | 
					 | 
				
			||||||
	virtualenv .
 | 
					 | 
				
			||||||
	bin/pip install -r requirements.txt
 | 
					 | 
				
			||||||
	bin/python setup.py develop
 | 
					 | 
				
			||||||
	bin/python selftest.py
 | 
					 | 
				
			||||||
	bin/nosetests Tests/test_*.py
 | 
					 | 
				
			||||||
	bin/python setup.py install
 | 
					 | 
				
			||||||
	bin/python test-installed.py
 | 
					 | 
				
			||||||
	check-manifest
 | 
					 | 
				
			||||||
	pyroma .
 | 
					 | 
				
			||||||
	viewdoc
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	python setup.py clean
 | 
						python setup.py clean
 | 
				
			||||||
| 
						 | 
					@ -30,32 +7,70 @@ clean:
 | 
				
			||||||
	rm -r build || true
 | 
						rm -r build || true
 | 
				
			||||||
	find . -name __pycache__ | xargs rm -r || true
 | 
						find . -name __pycache__ | xargs rm -r || true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install:
 | 
					 | 
				
			||||||
	python setup.py install
 | 
					 | 
				
			||||||
	python selftest.py --installed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test:
 | 
					 | 
				
			||||||
	python test-installed.py
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
inplace: clean
 | 
					 | 
				
			||||||
	python setup.py build_ext --inplace
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
coverage: 
 | 
					coverage: 
 | 
				
			||||||
# requires nose-cov
 | 
					 | 
				
			||||||
	coverage erase
 | 
						coverage erase
 | 
				
			||||||
	coverage run --parallel-mode --include=PIL/* selftest.py
 | 
						coverage run --parallel-mode --include=PIL/* selftest.py
 | 
				
			||||||
	nosetests --with-cov --cov='PIL/' --cov-report=html Tests/test_*.py
 | 
						nosetests --with-cov --cov='PIL/' --cov-report=html Tests/test_*.py
 | 
				
			||||||
# doesn't combine properly before report, 
 | 
					# Doesn't combine properly before report, writing report instead of displaying invalid report.
 | 
				
			||||||
# writing report instead of displaying invalid report
 | 
					 | 
				
			||||||
	rm -r htmlcov || true
 | 
						rm -r htmlcov || true
 | 
				
			||||||
	coverage combine
 | 
						coverage combine
 | 
				
			||||||
	coverage report
 | 
						coverage report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test-dep:
 | 
					doc:
 | 
				
			||||||
	pip install coveralls nose nose-cov pep8 pyflakes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
docs:
 | 
					 | 
				
			||||||
	$(MAKE) -C docs html
 | 
						$(MAKE) -C docs html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
docserver:
 | 
					docserve:
 | 
				
			||||||
	cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null&
 | 
						cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null&
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					help:
 | 
				
			||||||
 | 
						@echo "Welcome to Pillow development. Please use \`make <target>' where <target> is one of"
 | 
				
			||||||
 | 
						@echo "  clean          remove build products"
 | 
				
			||||||
 | 
						@echo "  coverage       run coverage test (in progress)"
 | 
				
			||||||
 | 
						@echo "  doc            make html docs"
 | 
				
			||||||
 | 
						@echo "  docserve       run an http server on the docs directory"
 | 
				
			||||||
 | 
						@echo "  html           to make standalone HTML files"
 | 
				
			||||||
 | 
						@echo "  inplace        make inplace extension" 
 | 
				
			||||||
 | 
						@echo "  install        make and install"
 | 
				
			||||||
 | 
						@echo "  install-req    install documentation and test dependencies"
 | 
				
			||||||
 | 
						@echo "  release-test   run code and package tests before release"
 | 
				
			||||||
 | 
						@echo "  test           run tests on installed pillow"
 | 
				
			||||||
 | 
						@echo "  upload         build and upload sdists to PyPI" 
 | 
				
			||||||
 | 
						@echo "  upload-test    build and upload sdists to test.pythonpackages.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inplace: clean
 | 
				
			||||||
 | 
						python setup.py build_ext --inplace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install:
 | 
				
			||||||
 | 
						python setup.py install
 | 
				
			||||||
 | 
						python selftest.py --installed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-req:
 | 
				
			||||||
 | 
						pip install -r requirements.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					release-test:
 | 
				
			||||||
 | 
						$(MAKE) install-req
 | 
				
			||||||
 | 
						python setup.py develop
 | 
				
			||||||
 | 
						python selftest.py
 | 
				
			||||||
 | 
						nosetests Tests/test_*.py
 | 
				
			||||||
 | 
						python setup.py install
 | 
				
			||||||
 | 
						python test-installed.py
 | 
				
			||||||
 | 
						check-manifest
 | 
				
			||||||
 | 
						pyroma .
 | 
				
			||||||
 | 
						viewdoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sdist:
 | 
				
			||||||
 | 
						python setup.py sdist --format=gztar,zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test:
 | 
				
			||||||
 | 
						python test-installed.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# https://docs.python.org/2/distutils/packageindex.html#the-pypirc-file
 | 
				
			||||||
 | 
					upload-test:
 | 
				
			||||||
 | 
					#       [test]
 | 
				
			||||||
 | 
					#       username:
 | 
				
			||||||
 | 
					#       password:
 | 
				
			||||||
 | 
					#       repository = http://test.pythonpackages.com
 | 
				
			||||||
 | 
						python setup.py sdist --format=gztar,zip upload -r test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					upload:
 | 
				
			||||||
 | 
						python setup.py sdist --format=gztar,zip upload
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,8 +40,8 @@ bdf_spacing = {
 | 
				
			||||||
    "C": "Cell"
 | 
					    "C": "Cell"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def bdf_char(f):
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def bdf_char(f):
 | 
				
			||||||
    # skip to STARTCHAR
 | 
					    # skip to STARTCHAR
 | 
				
			||||||
    while True:
 | 
					    while True:
 | 
				
			||||||
        s = f.readline()
 | 
					        s = f.readline()
 | 
				
			||||||
| 
						 | 
					@ -69,8 +69,8 @@ def bdf_char(f):
 | 
				
			||||||
        bitmap.append(s[:-1])
 | 
					        bitmap.append(s[:-1])
 | 
				
			||||||
    bitmap = b"".join(bitmap)
 | 
					    bitmap = b"".join(bitmap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [x, y, l, d] = [int(s) for s in props["BBX"].split()]
 | 
					    [x, y, l, d] = [int(p) for p in props["BBX"].split()]
 | 
				
			||||||
    [dx, dy] = [int(s) for s in props["DWIDTH"].split()]
 | 
					    [dx, dy] = [int(p) for p in props["DWIDTH"].split()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bbox = (dx, dy), (l, -d-y, x+l, -d), (0, 0, x, y)
 | 
					    bbox = (dx, dy), (l, -d-y, x+l, -d), (0, 0, x, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,6 +82,7 @@ def bdf_char(f):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return id, int(props["ENCODING"]), bbox, im
 | 
					    return id, int(props["ENCODING"]), bbox, im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Font file plugin for the X11 BDF format.
 | 
					# Font file plugin for the X11 BDF format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,10 +114,10 @@ class BdfFontFile(FontFile.FontFile):
 | 
				
			||||||
        font[4] = bdf_slant[font[4].upper()]
 | 
					        font[4] = bdf_slant[font[4].upper()]
 | 
				
			||||||
        font[11] = bdf_spacing[font[11].upper()]
 | 
					        font[11] = bdf_spacing[font[11].upper()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ascent = int(props["FONT_ASCENT"])
 | 
					        # ascent = int(props["FONT_ASCENT"])
 | 
				
			||||||
        descent = int(props["FONT_DESCENT"])
 | 
					        # descent = int(props["FONT_DESCENT"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fontname = ";".join(font[1:])
 | 
					        # fontname = ";".join(font[1:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # print "#", fontname
 | 
					        # print "#", fontname
 | 
				
			||||||
        # for i in comments:
 | 
					        # for i in comments:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ __version__ = "0.7"
 | 
				
			||||||
from PIL import Image, ImageFile, ImagePalette, _binary
 | 
					from PIL import Image, ImageFile, ImagePalette, _binary
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i8 = _binary.i8
 | 
					i8 = _binary.i8
 | 
				
			||||||
i16 = _binary.i16le
 | 
					i16 = _binary.i16le
 | 
				
			||||||
i32 = _binary.i32le
 | 
					i32 = _binary.i32le
 | 
				
			||||||
| 
						 | 
					@ -48,136 +49,154 @@ BIT2MODE = {
 | 
				
			||||||
    8: ("P", "P"),
 | 
					    8: ("P", "P"),
 | 
				
			||||||
    16: ("RGB", "BGR;15"),
 | 
					    16: ("RGB", "BGR;15"),
 | 
				
			||||||
    24: ("RGB", "BGR"),
 | 
					    24: ("RGB", "BGR"),
 | 
				
			||||||
    32: ("RGB", "BGRX")
 | 
					    32: ("RGB", "BGRX"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:2] == b"BM"
 | 
					    return prefix[:2] == b"BM"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
# Image plugin for the Windows BMP format.
 | 
					# Image plugin for the Windows BMP format.
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
class BmpImageFile(ImageFile.ImageFile):
 | 
					class BmpImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					    """ Image plugin for the Windows Bitmap format (BMP) """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "BMP"
 | 
					    # -------------------------------------------------------------- Description
 | 
				
			||||||
    format_description = "Windows Bitmap"
 | 
					    format_description = "Windows Bitmap"
 | 
				
			||||||
 | 
					    format = "BMP"
 | 
				
			||||||
 | 
					    # --------------------------------------------------- BMP Compression values
 | 
				
			||||||
 | 
					    COMPRESSIONS = {'RAW': 0, 'RLE8': 1, 'RLE4': 2, 'BITFIELDS': 3, 'JPEG': 4, 'PNG': 5}
 | 
				
			||||||
 | 
					    RAW, RLE8, RLE4, BITFIELDS, JPEG, PNG = 0, 1, 2, 3, 4, 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _bitmap(self, header = 0, offset = 0):
 | 
					    def _bitmap(self, header=0, offset=0):
 | 
				
			||||||
 | 
					        """ Read relevant info about the BMP """
 | 
				
			||||||
 | 
					        read, seek = self.fp.read, self.fp.seek
 | 
				
			||||||
        if header:
 | 
					        if header:
 | 
				
			||||||
            self.fp.seek(header)
 | 
					            seek(header)
 | 
				
			||||||
 | 
					        file_info = dict()
 | 
				
			||||||
        read = self.fp.read
 | 
					        file_info['header_size'] = i32(read(4))  # read bmp header size @offset 14 (this is part of the header size)
 | 
				
			||||||
 | 
					        file_info['direction'] = -1
 | 
				
			||||||
        # CORE/INFO
 | 
					        # --------------------- If requested, read header at a specific position
 | 
				
			||||||
        s = read(4)
 | 
					        header_data = ImageFile._safe_read(self.fp, file_info['header_size'] - 4)  # read the rest of the bmp header, without its size
 | 
				
			||||||
        s = s + ImageFile._safe_read(self.fp, i32(s)-4)
 | 
					        # --------------------------------------------------- IBM OS/2 Bitmap v1
 | 
				
			||||||
 | 
					        # ------ This format has different offsets because of width/height types
 | 
				
			||||||
        if len(s) == 12:
 | 
					        if file_info['header_size'] == 12:
 | 
				
			||||||
 | 
					            file_info['width'] = i16(header_data[0:2])
 | 
				
			||||||
            # OS/2 1.0 CORE
 | 
					            file_info['height'] = i16(header_data[2:4])
 | 
				
			||||||
            bits = i16(s[10:])
 | 
					            file_info['planes'] = i16(header_data[4:6])
 | 
				
			||||||
            self.size = i16(s[4:]), i16(s[6:])
 | 
					            file_info['bits'] = i16(header_data[6:8])
 | 
				
			||||||
            compression = 0
 | 
					            file_info['compression'] = self.RAW
 | 
				
			||||||
            lutsize = 3
 | 
					            file_info['palette_padding'] = 3
 | 
				
			||||||
            colors = 0
 | 
					        # ---------------------------------------------- Windows Bitmap v2 to v5
 | 
				
			||||||
            direction = -1
 | 
					        elif file_info['header_size'] in (40, 64, 108, 124):  # v3, OS/2 v2, v4, v5
 | 
				
			||||||
 | 
					            if file_info['header_size'] >= 40:  # v3 and OS/2
 | 
				
			||||||
        elif len(s) in [40, 64, 108, 124]:
 | 
					                file_info['y_flip'] = i8(header_data[7]) == 0xff
 | 
				
			||||||
 | 
					                file_info['direction'] = 1 if file_info['y_flip'] else -1
 | 
				
			||||||
            # WIN 3.1 or OS/2 2.0 INFO
 | 
					                file_info['width'] = i32(header_data[0:4])
 | 
				
			||||||
            bits = i16(s[14:])
 | 
					                file_info['height'] = i32(header_data[4:8]) if not file_info['y_flip'] else 2**32 - i32(header_data[4:8])
 | 
				
			||||||
            self.size = i32(s[4:]), i32(s[8:])
 | 
					                file_info['planes'] = i16(header_data[8:10])
 | 
				
			||||||
            compression = i32(s[16:])
 | 
					                file_info['bits'] = i16(header_data[10:12])
 | 
				
			||||||
            pxperm = (i32(s[24:]), i32(s[28:]))  # Pixels per meter
 | 
					                file_info['compression'] = i32(header_data[12:16])
 | 
				
			||||||
            lutsize = 4
 | 
					                file_info['data_size'] = i32(header_data[16:20])  # byte size of pixel data
 | 
				
			||||||
            colors = i32(s[32:])
 | 
					                file_info['pixels_per_meter'] = (i32(header_data[20:24]), i32(header_data[24:28]))
 | 
				
			||||||
            direction = -1
 | 
					                file_info['colors'] = i32(header_data[28:32])
 | 
				
			||||||
            if i8(s[11]) == 0xff:
 | 
					                file_info['palette_padding'] = 4
 | 
				
			||||||
                # upside-down storage
 | 
					                self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701), file_info['pixels_per_meter']))
 | 
				
			||||||
                self.size = self.size[0], 2**32 - self.size[1]
 | 
					                if file_info['compression'] == self.BITFIELDS:
 | 
				
			||||||
                direction = 0
 | 
					                    if len(header_data) >= 52:
 | 
				
			||||||
            
 | 
					                        for idx, mask in enumerate(['r_mask', 'g_mask', 'b_mask', 'a_mask']):
 | 
				
			||||||
            self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701), pxperm))
 | 
					                            file_info[mask] = i32(header_data[36+idx*4:40+idx*4])
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
            raise IOError("Unsupported BMP header type (%d)" % len(s))
 | 
					                        for mask in ['r_mask', 'g_mask', 'b_mask', 'a_mask']:
 | 
				
			||||||
 | 
					                            file_info[mask] = i32(read(4))
 | 
				
			||||||
        if (self.size[0]*self.size[1]) > 2**31:
 | 
					                    file_info['rgb_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask'])
 | 
				
			||||||
            # Prevent DOS for > 2gb images
 | 
					                    file_info['rgba_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask'], file_info['a_mask'])
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            raise IOError("Unsupported BMP header type (%d)" % file_info['header_size'])
 | 
				
			||||||
 | 
					        # ------------------ Special case : header is reported 40, which
 | 
				
			||||||
 | 
					        # ---------------------- is shorter than real size for bpp >= 16
 | 
				
			||||||
 | 
					        self.size = file_info['width'], file_info['height']
 | 
				
			||||||
 | 
					        # -------- If color count was not found in the header, compute from bits
 | 
				
			||||||
 | 
					        file_info['colors'] = file_info['colors'] if file_info.get('colors', 0) else (1 << file_info['bits'])
 | 
				
			||||||
 | 
					        # -------------------------------- Check abnormal values for DOS attacks
 | 
				
			||||||
 | 
					        if file_info['width'] * file_info['height'] > 2**31:
 | 
				
			||||||
            raise IOError("Unsupported BMP Size: (%dx%d)" % self.size)
 | 
					            raise IOError("Unsupported BMP Size: (%dx%d)" % self.size)
 | 
				
			||||||
 | 
					        # ----------------------- Check bit depth for unusual unsupported values
 | 
				
			||||||
        if not colors:
 | 
					        self.mode, raw_mode = BIT2MODE.get(file_info['bits'], (None, None))
 | 
				
			||||||
            colors = 1 << bits
 | 
					        if self.mode is None:
 | 
				
			||||||
 | 
					            raise IOError("Unsupported BMP pixel depth (%d)" % file_info['bits'])
 | 
				
			||||||
        # MODE
 | 
					        # ----------------- Process BMP with Bitfields compression (not palette)
 | 
				
			||||||
        try:
 | 
					        if file_info['compression'] == self.BITFIELDS:
 | 
				
			||||||
            self.mode, rawmode = BIT2MODE[bits]
 | 
					            SUPPORTED = {
 | 
				
			||||||
        except KeyError:
 | 
					            32: [(0xff0000, 0xff00, 0xff, 0x0), (0xff0000, 0xff00, 0xff, 0xff000000), (0x0, 0x0, 0x0, 0x0)],
 | 
				
			||||||
            raise IOError("Unsupported BMP pixel depth (%d)" % bits)
 | 
					            24: [(0xff0000, 0xff00, 0xff)],
 | 
				
			||||||
 | 
					            16: [(0xf800, 0x7e0, 0x1f), (0x7c00, 0x3e0, 0x1f)]}
 | 
				
			||||||
        if compression == 3:
 | 
					            MASK_MODES = {
 | 
				
			||||||
            # BI_BITFIELDS compression
 | 
					            (32, (0xff0000, 0xff00, 0xff, 0x0)): "BGRX", (32, (0xff0000, 0xff00, 0xff, 0xff000000)): "BGRA", (32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
 | 
				
			||||||
            mask = i32(read(4)), i32(read(4)), i32(read(4))
 | 
					            (24, (0xff0000, 0xff00, 0xff)): "BGR",
 | 
				
			||||||
            if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
 | 
					            (16, (0xf800, 0x7e0, 0x1f)): "BGR;16", (16, (0x7c00, 0x3e0, 0x1f)): "BGR;15"}
 | 
				
			||||||
                rawmode = "BGRX"
 | 
					            if file_info['bits'] in SUPPORTED:
 | 
				
			||||||
            elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
 | 
					                if file_info['bits'] == 32 and file_info['rgba_mask'] in SUPPORTED[file_info['bits']]:
 | 
				
			||||||
                rawmode = "BGR;16"
 | 
					                    raw_mode = MASK_MODES[(file_info['bits'], file_info['rgba_mask'])]
 | 
				
			||||||
            elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
 | 
					                    self.mode = "RGBA" if raw_mode in ("BGRA",) else self.mode
 | 
				
			||||||
                rawmode = "BGR;15"
 | 
					                elif file_info['bits'] in (24, 16) and file_info['rgb_mask'] in SUPPORTED[file_info['bits']]:
 | 
				
			||||||
 | 
					                    raw_mode = MASK_MODES[(file_info['bits'], file_info['rgb_mask'])]
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                # print bits, map(hex, mask)
 | 
					 | 
				
			||||||
                    raise IOError("Unsupported BMP bitfields layout")
 | 
					                    raise IOError("Unsupported BMP bitfields layout")
 | 
				
			||||||
        elif compression != 0:
 | 
					 | 
				
			||||||
            raise IOError("Unsupported BMP compression (%d)" % compression)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # LUT
 | 
					 | 
				
			||||||
        if self.mode == "P":
 | 
					 | 
				
			||||||
            palette = []
 | 
					 | 
				
			||||||
            greyscale = 1
 | 
					 | 
				
			||||||
            if colors == 2:
 | 
					 | 
				
			||||||
                indices = (0, 255)
 | 
					 | 
				
			||||||
            elif colors > 2**16 or colors <=0: #We're reading a i32. 
 | 
					 | 
				
			||||||
                raise IOError("Unsupported BMP Palette size (%d)" % colors)
 | 
					 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                indices = list(range(colors))
 | 
					                raise IOError("Unsupported BMP bitfields layout")
 | 
				
			||||||
            for i in indices:
 | 
					        elif file_info['compression'] == self.RAW:
 | 
				
			||||||
                rgb = read(lutsize)[:3]
 | 
					            if file_info['bits'] == 32 and header == 22:  # 32-bit .cur offset
 | 
				
			||||||
                if rgb != o8(i)*3:
 | 
					                raw_mode, self.mode = "BGRA", "RGBA"
 | 
				
			||||||
                    greyscale = 0
 | 
					        else:
 | 
				
			||||||
                palette.append(rgb)
 | 
					            raise IOError("Unsupported BMP compression (%d)" % file_info['compression'])
 | 
				
			||||||
 | 
					        # ---------------- Once the header is processed, process the palette/LUT
 | 
				
			||||||
 | 
					        if self.mode == "P":  # Paletted for 1, 4 and 8 bit images
 | 
				
			||||||
 | 
					            # ----------------------------------------------------- 1-bit images
 | 
				
			||||||
 | 
					            if not (0 < file_info['colors'] <= 65536):
 | 
				
			||||||
 | 
					                raise IOError("Unsupported BMP Palette size (%d)" % file_info['colors'])
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                padding = file_info['palette_padding']
 | 
				
			||||||
 | 
					                palette = read(padding * file_info['colors'])
 | 
				
			||||||
 | 
					                greyscale = True
 | 
				
			||||||
 | 
					                indices = (0, 255) if file_info['colors'] == 2 else list(range(file_info['colors']))
 | 
				
			||||||
 | 
					                # ------------------ Check if greyscale and ignore palette if so
 | 
				
			||||||
 | 
					                for ind, val in enumerate(indices):
 | 
				
			||||||
 | 
					                    rgb = palette[ind*padding:ind*padding + 3]
 | 
				
			||||||
 | 
					                    if rgb != o8(val) * 3:
 | 
				
			||||||
 | 
					                        greyscale = False
 | 
				
			||||||
 | 
					                # -------- If all colors are grey, white or black, ditch palette
 | 
				
			||||||
                if greyscale:
 | 
					                if greyscale:
 | 
				
			||||||
                if colors == 2:
 | 
					                    self.mode = "1" if file_info['colors'] == 2 else "L"
 | 
				
			||||||
                    self.mode = rawmode = "1"
 | 
					                    raw_mode = self.mode
 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    self.mode = rawmode = "L"
 | 
					 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    self.mode = "P"
 | 
					                    self.mode = "P"
 | 
				
			||||||
                self.palette = ImagePalette.raw(
 | 
					                    self.palette = ImagePalette.raw("BGRX" if padding == 4 else "BGR", palette)
 | 
				
			||||||
                    "BGR", b"".join(palette)
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not offset:
 | 
					        # ----------------------------- Finally set the tile data for the plugin
 | 
				
			||||||
            offset = self.fp.tell()
 | 
					        self.info['compression'] = file_info['compression']
 | 
				
			||||||
 | 
					        self.tile = [('raw', (0, 0, file_info['width'], file_info['height']), offset or self.fp.tell(),
 | 
				
			||||||
        self.tile = [("raw",
 | 
					                      (raw_mode, ((file_info['width'] * file_info['bits'] + 31) >> 3) & (~3), file_info['direction'])
 | 
				
			||||||
                     (0, 0) + self.size,
 | 
					                      )]
 | 
				
			||||||
                     offset,
 | 
					 | 
				
			||||||
                     (rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.info["compression"] = compression
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open(self):
 | 
					    def _open(self):
 | 
				
			||||||
 | 
					        """ Open file, check magic number and read header """
 | 
				
			||||||
        # HEAD
 | 
					        # read 14 bytes: magic number, filesize, reserved, header final offset
 | 
				
			||||||
        s = self.fp.read(14)
 | 
					        head_data = self.fp.read(14)
 | 
				
			||||||
        if s[:2] != b"BM":
 | 
					        # choke if the file does not have the required magic bytes
 | 
				
			||||||
 | 
					        if head_data[0:2] != b"BM":
 | 
				
			||||||
            raise SyntaxError("Not a BMP file")
 | 
					            raise SyntaxError("Not a BMP file")
 | 
				
			||||||
        offset = i32(s[10:])
 | 
					        # read the start position of the BMP image data (u32)
 | 
				
			||||||
 | 
					        offset = i32(head_data[10:14])
 | 
				
			||||||
 | 
					        # load bitmap information (offset=raster info)
 | 
				
			||||||
        self._bitmap(offset=offset)
 | 
					        self._bitmap(offset=offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					# Image plugin for the DIB format (BMP alias)
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
class DibImageFile(BmpImageFile):
 | 
					class DibImageFile(BmpImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "DIB"
 | 
					    format = "DIB"
 | 
				
			||||||
| 
						 | 
					@ -195,10 +214,11 @@ SAVE = {
 | 
				
			||||||
    "L": ("L", 8, 256),
 | 
					    "L": ("L", 8, 256),
 | 
				
			||||||
    "P": ("P", 8, 256),
 | 
					    "P": ("P", 8, 256),
 | 
				
			||||||
    "RGB": ("BGR", 24, 0),
 | 
					    "RGB": ("BGR", 24, 0),
 | 
				
			||||||
 | 
					    "RGBA": ("BGRA", 32, 0),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename, check=0):
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _save(im, fp, filename, check=0):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        rawmode, bits, colors = SAVE[im.mode]
 | 
					        rawmode, bits, colors = SAVE[im.mode]
 | 
				
			||||||
    except KeyError:
 | 
					    except KeyError:
 | 
				
			||||||
| 
						 | 
					@ -214,7 +234,7 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    # 1 meter == 39.3701 inches
 | 
					    # 1 meter == 39.3701 inches
 | 
				
			||||||
    ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
 | 
					    ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stride = ((im.size[0]*bits+7)//8+3)&(~3)
 | 
					    stride = ((im.size[0]*bits+7)//8+3) & (~3)
 | 
				
			||||||
    header = 40  # or 64 for OS/2 version 2
 | 
					    header = 40  # or 64 for OS/2 version 2
 | 
				
			||||||
    offset = 14 + header + colors * 4
 | 
					    offset = 14 + header + colors * 4
 | 
				
			||||||
    image = stride * im.size[1]
 | 
					    image = stride * im.size[1]
 | 
				
			||||||
| 
						 | 
					@ -248,7 +268,8 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    elif im.mode == "P":
 | 
					    elif im.mode == "P":
 | 
				
			||||||
        fp.write(im.im.getpalette("RGB", "BGRX"))
 | 
					        fp.write(im.im.getpalette("RGB", "BGRX"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
 | 
					    ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0,
 | 
				
			||||||
 | 
					                    (rawmode, stride, -1))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_handler = None
 | 
					_handler = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Install application-specific BUFR image handler.
 | 
					# Install application-specific BUFR image handler.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -22,12 +23,14 @@ def register_handler(handler):
 | 
				
			||||||
    global _handler
 | 
					    global _handler
 | 
				
			||||||
    _handler = handler
 | 
					    _handler = handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Image adapter
 | 
					# Image adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
 | 
					    return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BufrStubImageFile(ImageFile.StubImageFile):
 | 
					class BufrStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "BUFR"
 | 
					    format = "BUFR"
 | 
				
			||||||
| 
						 | 
					@ -53,6 +56,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
    def _load(self):
 | 
					    def _load(self):
 | 
				
			||||||
        return _handler
 | 
					        return _handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename):
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
    if _handler is None or not hasattr("_handler", "save"):
 | 
					    if _handler is None or not hasattr("_handler", "save"):
 | 
				
			||||||
        raise IOError("BUFR save handler not installed")
 | 
					        raise IOError("BUFR save handler not installed")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,8 @@
 | 
				
			||||||
# A file object that provides read access to a part of an existing
 | 
					# A file object that provides read access to a part of an existing
 | 
				
			||||||
# file (for example a TAR file).
 | 
					# file (for example a TAR file).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ContainerIO:
 | 
					
 | 
				
			||||||
 | 
					class ContainerIO(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ##
 | 
					    ##
 | 
				
			||||||
    # Create file object.
 | 
					    # Create file object.
 | 
				
			||||||
| 
						 | 
					@ -48,7 +49,7 @@ class ContainerIO:
 | 
				
			||||||
    #    for current offset, and 2 for end of region.  You cannot move
 | 
					    #    for current offset, and 2 for end of region.  You cannot move
 | 
				
			||||||
    #    the pointer outside the defined region.
 | 
					    #    the pointer outside the defined region.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, offset, mode = 0):
 | 
					    def seek(self, offset, mode=0):
 | 
				
			||||||
        if mode == 1:
 | 
					        if mode == 1:
 | 
				
			||||||
            self.pos = self.pos + offset
 | 
					            self.pos = self.pos + offset
 | 
				
			||||||
        elif mode == 2:
 | 
					        elif mode == 2:
 | 
				
			||||||
| 
						 | 
					@ -75,7 +76,7 @@ class ContainerIO:
 | 
				
			||||||
    #     read until end of region.
 | 
					    #     read until end of region.
 | 
				
			||||||
    # @return An 8-bit string.
 | 
					    # @return An 8-bit string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def read(self, n = 0):
 | 
					    def read(self, n=0):
 | 
				
			||||||
        if n:
 | 
					        if n:
 | 
				
			||||||
            n = min(n, self.length - self.pos)
 | 
					            n = min(n, self.length - self.pos)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,10 @@ class DcxImageFile(PcxImageFile):
 | 
				
			||||||
        self.__fp = self.fp
 | 
					        self.__fp = self.fp
 | 
				
			||||||
        self.seek(0)
 | 
					        self.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return len(self._offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
        if frame >= len(self._offset):
 | 
					        if frame >= len(self._offset):
 | 
				
			||||||
            raise EOFError("attempt to seek outside DCX directory")
 | 
					            raise EOFError("attempt to seek outside DCX directory")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,8 @@
 | 
				
			||||||
# 1996-08-23 fl   Handle files from Macintosh (0.3)
 | 
					# 1996-08-23 fl   Handle files from Macintosh (0.3)
 | 
				
			||||||
# 2001-02-17 fl   Use 're' instead of 'regex' (Python 2.1) (0.4)
 | 
					# 2001-02-17 fl   Use 're' instead of 'regex' (Python 2.1) (0.4)
 | 
				
			||||||
# 2003-09-07 fl   Check gs.close status (from Federico Di Gregorio) (0.5)
 | 
					# 2003-09-07 fl   Check gs.close status (from Federico Di Gregorio) (0.5)
 | 
				
			||||||
# 2014-05-07 e    Handling of EPS with binary preview and fixed resolution resizing
 | 
					# 2014-05-07 e    Handling of EPS with binary preview and fixed resolution
 | 
				
			||||||
 | 
					#                 resizing
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Copyright (c) 1997-2003 by Secret Labs AB.
 | 
					# Copyright (c) 1997-2003 by Secret Labs AB.
 | 
				
			||||||
# Copyright (c) 1995-2003 by Fredrik Lundh
 | 
					# Copyright (c) 1995-2003 by Fredrik Lundh
 | 
				
			||||||
| 
						 | 
					@ -51,13 +52,14 @@ if sys.platform.startswith('win'):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        gs_windows_binary = False
 | 
					        gs_windows_binary = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def has_ghostscript():
 | 
					def has_ghostscript():
 | 
				
			||||||
    if gs_windows_binary:
 | 
					    if gs_windows_binary:
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
    if not sys.platform.startswith('win'):
 | 
					    if not sys.platform.startswith('win'):
 | 
				
			||||||
        import subprocess
 | 
					        import subprocess
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            gs = subprocess.Popen(['gs','--version'], stdout=subprocess.PIPE)
 | 
					            gs = subprocess.Popen(['gs', '--version'], stdout=subprocess.PIPE)
 | 
				
			||||||
            gs.stdout.read()
 | 
					            gs.stdout.read()
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        except OSError:
 | 
					        except OSError:
 | 
				
			||||||
| 
						 | 
					@ -73,26 +75,35 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
    decoder, tile, offset, data = tile[0]
 | 
					    decoder, tile, offset, data = tile[0]
 | 
				
			||||||
    length, bbox = data
 | 
					    length, bbox = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Hack to support hi-res rendering
 | 
					    # Hack to support hi-res rendering
 | 
				
			||||||
    scale = int(scale) or 1
 | 
					    scale = int(scale) or 1
 | 
				
			||||||
    orig_size = size
 | 
					    # orig_size = size
 | 
				
			||||||
    orig_bbox = bbox
 | 
					    # orig_bbox = bbox
 | 
				
			||||||
    size = (size[0] * scale, size[1] * scale)
 | 
					    size = (size[0] * scale, size[1] * scale)
 | 
				
			||||||
    # resolution is dependend on bbox and size
 | 
					    # resolution is dependent on bbox and size
 | 
				
			||||||
    res = ( float((72.0 * size[0]) / (bbox[2]-bbox[0])), float((72.0 * size[1]) / (bbox[3]-bbox[1])) )
 | 
					    res = (float((72.0 * size[0]) / (bbox[2]-bbox[0])),
 | 
				
			||||||
    #print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
 | 
					           float((72.0 * size[1]) / (bbox[3]-bbox[1])))
 | 
				
			||||||
 | 
					    # print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    import tempfile, os, subprocess
 | 
					    import os
 | 
				
			||||||
 | 
					    import subprocess
 | 
				
			||||||
 | 
					    import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out_fd, outfile = tempfile.mkstemp()
 | 
					    out_fd, outfile = tempfile.mkstemp()
 | 
				
			||||||
    os.close(out_fd)
 | 
					    os.close(out_fd)
 | 
				
			||||||
    in_fd, infile = tempfile.mkstemp()
 | 
					
 | 
				
			||||||
 | 
					    infile_temp = None
 | 
				
			||||||
 | 
					    if hasattr(fp, 'name') and os.path.exists(fp.name):
 | 
				
			||||||
 | 
					        infile = fp.name
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        in_fd, infile_temp = tempfile.mkstemp()
 | 
				
			||||||
        os.close(in_fd)
 | 
					        os.close(in_fd)
 | 
				
			||||||
 | 
					        infile = infile_temp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # ignore length and offset!
 | 
					        # ignore length and offset!
 | 
				
			||||||
        # ghostscript can read it
 | 
					        # ghostscript can read it
 | 
				
			||||||
        # copy whole file to read in ghostscript
 | 
					        # copy whole file to read in ghostscript
 | 
				
			||||||
    with open(infile, 'wb') as f:
 | 
					        with open(infile_temp, 'wb') as f:
 | 
				
			||||||
            # fetch length of fp
 | 
					            # fetch length of fp
 | 
				
			||||||
            fp.seek(0, 2)
 | 
					            fp.seek(0, 2)
 | 
				
			||||||
            fsize = fp.tell()
 | 
					            fsize = fp.tell()
 | 
				
			||||||
| 
						 | 
					@ -104,7 +115,7 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
                s = fp.read(min(lengthfile, 100*1024))
 | 
					                s = fp.read(min(lengthfile, 100*1024))
 | 
				
			||||||
                if not s:
 | 
					                if not s:
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
            length -= len(s)
 | 
					                lengthfile -= len(s)
 | 
				
			||||||
                f.write(s)
 | 
					                f.write(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Build ghostscript command
 | 
					    # Build ghostscript command
 | 
				
			||||||
| 
						 | 
					@ -112,7 +123,8 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
               "-q",                         # quiet mode
 | 
					               "-q",                         # quiet mode
 | 
				
			||||||
               "-g%dx%d" % size,             # set output geometry (pixels)
 | 
					               "-g%dx%d" % size,             # set output geometry (pixels)
 | 
				
			||||||
               "-r%fx%f" % res,              # set input DPI (dots per inch)
 | 
					               "-r%fx%f" % res,              # set input DPI (dots per inch)
 | 
				
			||||||
               "-dNOPAUSE -dSAFER",         # don't pause between pages, safe mode
 | 
					               "-dNOPAUSE -dSAFER",          # don't pause between pages,
 | 
				
			||||||
 | 
					                                             # safe mode
 | 
				
			||||||
               "-sDEVICE=ppmraw",            # ppm driver
 | 
					               "-sDEVICE=ppmraw",            # ppm driver
 | 
				
			||||||
               "-sOutputFile=%s" % outfile,  # output file
 | 
					               "-sOutputFile=%s" % outfile,  # output file
 | 
				
			||||||
               "-c", "%d %d translate" % (-bbox[0], -bbox[1]),
 | 
					               "-c", "%d %d translate" % (-bbox[0], -bbox[1]),
 | 
				
			||||||
| 
						 | 
					@ -127,7 +139,8 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # push data through ghostscript
 | 
					    # push data through ghostscript
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        gs = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
 | 
					        gs = subprocess.Popen(command, stdin=subprocess.PIPE,
 | 
				
			||||||
 | 
					                              stdout=subprocess.PIPE)
 | 
				
			||||||
        gs.stdin.close()
 | 
					        gs.stdin.close()
 | 
				
			||||||
        status = gs.wait()
 | 
					        status = gs.wait()
 | 
				
			||||||
        if status:
 | 
					        if status:
 | 
				
			||||||
| 
						 | 
					@ -136,48 +149,41 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
    finally:
 | 
					    finally:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            os.unlink(outfile)
 | 
					            os.unlink(outfile)
 | 
				
			||||||
            os.unlink(infile)
 | 
					            if infile_temp:
 | 
				
			||||||
        except: pass
 | 
					                os.unlink(infile_temp)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return im
 | 
					    return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PSFile:
 | 
					class PSFile(object):
 | 
				
			||||||
    """Wrapper that treats either CR or LF as end of line."""
 | 
					    """
 | 
				
			||||||
 | 
					    Wrapper for bytesio object that treats either CR or LF as end of line.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    def __init__(self, fp):
 | 
					    def __init__(self, fp):
 | 
				
			||||||
        self.fp = fp
 | 
					        self.fp = fp
 | 
				
			||||||
        self.char = None
 | 
					        self.char = None
 | 
				
			||||||
    def __getattr__(self, id):
 | 
					
 | 
				
			||||||
        v = getattr(self.fp, id)
 | 
					 | 
				
			||||||
        setattr(self, id, v)
 | 
					 | 
				
			||||||
        return v
 | 
					 | 
				
			||||||
    def seek(self, offset, whence=0):
 | 
					    def seek(self, offset, whence=0):
 | 
				
			||||||
        self.char = None
 | 
					        self.char = None
 | 
				
			||||||
        self.fp.seek(offset, whence)
 | 
					        self.fp.seek(offset, whence)
 | 
				
			||||||
    def read(self, count):
 | 
					
 | 
				
			||||||
        return self.fp.read(count).decode('latin-1')
 | 
					 | 
				
			||||||
    def readbinary(self, count):
 | 
					 | 
				
			||||||
        return self.fp.read(count)
 | 
					 | 
				
			||||||
    def tell(self):
 | 
					 | 
				
			||||||
        pos = self.fp.tell()
 | 
					 | 
				
			||||||
        if self.char:
 | 
					 | 
				
			||||||
            pos -= 1
 | 
					 | 
				
			||||||
        return pos
 | 
					 | 
				
			||||||
    def readline(self):
 | 
					    def readline(self):
 | 
				
			||||||
        s = b""
 | 
					        s = self.char or b""
 | 
				
			||||||
        if self.char:
 | 
					 | 
				
			||||||
            c = self.char
 | 
					 | 
				
			||||||
        self.char = None
 | 
					        self.char = None
 | 
				
			||||||
        else:
 | 
					
 | 
				
			||||||
        c = self.fp.read(1)
 | 
					        c = self.fp.read(1)
 | 
				
			||||||
        while c not in b"\r\n":
 | 
					        while c not in b"\r\n":
 | 
				
			||||||
            s = s + c
 | 
					            s = s + c
 | 
				
			||||||
            c = self.fp.read(1)
 | 
					            c = self.fp.read(1)
 | 
				
			||||||
        if c == b"\r":
 | 
					
 | 
				
			||||||
        self.char = self.fp.read(1)
 | 
					        self.char = self.fp.read(1)
 | 
				
			||||||
            if self.char == b"\n":
 | 
					        # line endings can be 1 or 2 of \r \n, in either order
 | 
				
			||||||
 | 
					        if self.char in b"\r\n":
 | 
				
			||||||
            self.char = None
 | 
					            self.char = None
 | 
				
			||||||
        return s.decode('latin-1') + "\n"
 | 
					
 | 
				
			||||||
 | 
					        return s.decode('latin-1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
| 
						 | 
					@ -187,38 +193,30 @@ def _accept(prefix):
 | 
				
			||||||
# Image plugin for Encapsulated Postscript.  This plugin supports only
 | 
					# Image plugin for Encapsulated Postscript.  This plugin supports only
 | 
				
			||||||
# a few variants of this format.
 | 
					# a few variants of this format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EpsImageFile(ImageFile.ImageFile):
 | 
					class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    """EPS File Parser for the Python Imaging Library"""
 | 
					    """EPS File Parser for the Python Imaging Library"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "EPS"
 | 
					    format = "EPS"
 | 
				
			||||||
    format_description = "Encapsulated Postscript"
 | 
					    format_description = "Encapsulated Postscript"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mode_map = {1: "L", 2: "LAB", 3: "RGB"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open(self):
 | 
					    def _open(self):
 | 
				
			||||||
 | 
					        (length, offset) = self._find_offset(self.fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fp = PSFile(self.fp)
 | 
					        # Rewrap the open file pointer in something that will
 | 
				
			||||||
 | 
					        # convert line endings and decode to latin-1.
 | 
				
			||||||
        # FIX for: Some EPS file not handled correctly / issue #302 
 | 
					        try:
 | 
				
			||||||
        # EPS can contain binary data
 | 
					            if bytes is str:
 | 
				
			||||||
        # or start directly with latin coding
 | 
					                # Python2, no encoding conversion necessary
 | 
				
			||||||
        # read header in both ways to handle both
 | 
					                fp = open(self.fp.name, "Ur")
 | 
				
			||||||
        # file types
 | 
					 | 
				
			||||||
        # more info see http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        # for HEAD without binary preview
 | 
					 | 
				
			||||||
        s = fp.read(4)
 | 
					 | 
				
			||||||
        # for HEAD with binary preview
 | 
					 | 
				
			||||||
        fp.seek(0)
 | 
					 | 
				
			||||||
        sb = fp.readbinary(160)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if s[:4] == "%!PS":
 | 
					 | 
				
			||||||
            fp.seek(0, 2)
 | 
					 | 
				
			||||||
            length = fp.tell()
 | 
					 | 
				
			||||||
            offset = 0
 | 
					 | 
				
			||||||
        elif i32(sb[0:4]) == 0xC6D3D0C5:
 | 
					 | 
				
			||||||
            offset = i32(sb[4:8])
 | 
					 | 
				
			||||||
            length = i32(sb[8:12])
 | 
					 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
            raise SyntaxError("not an EPS file")
 | 
					                # Python3, can use bare open command.
 | 
				
			||||||
 | 
					                fp = open(self.fp.name, "Ur", encoding='latin-1')
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            # Expect this for bytesio/stringio
 | 
				
			||||||
 | 
					            fp = PSFile(self.fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # go to offset - start of "%!PS"
 | 
					        # go to offset - start of "%!PS"
 | 
				
			||||||
        fp.seek(offset)
 | 
					        fp.seek(offset)
 | 
				
			||||||
| 
						 | 
					@ -231,18 +229,12 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        # Load EPS header
 | 
					        # Load EPS header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = fp.readline()
 | 
					        s = fp.readline().strip('\r\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while s:
 | 
					        while s:
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if len(s) > 255:
 | 
					            if len(s) > 255:
 | 
				
			||||||
                raise SyntaxError("not an EPS file")
 | 
					                raise SyntaxError("not an EPS file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if s[-2:] == '\r\n':
 | 
					 | 
				
			||||||
                s = s[:-2]
 | 
					 | 
				
			||||||
            elif s[-1:] == '\n':
 | 
					 | 
				
			||||||
                s = s[:-1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                m = split.match(s)
 | 
					                m = split.match(s)
 | 
				
			||||||
            except re.error as v:
 | 
					            except re.error as v:
 | 
				
			||||||
| 
						 | 
					@ -256,17 +248,15 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                        # Note: The DSC spec says that BoundingBox
 | 
					                        # Note: The DSC spec says that BoundingBox
 | 
				
			||||||
                        # fields should be integers, but some drivers
 | 
					                        # fields should be integers, but some drivers
 | 
				
			||||||
                        # put floating point values there anyway.
 | 
					                        # put floating point values there anyway.
 | 
				
			||||||
                        box = [int(float(s)) for s in v.split()]
 | 
					                        box = [int(float(i)) for i in v.split()]
 | 
				
			||||||
                        self.size = box[2] - box[0], box[3] - box[1]
 | 
					                        self.size = box[2] - box[0], box[3] - box[1]
 | 
				
			||||||
                        self.tile = [("eps", (0,0) + self.size, offset,
 | 
					                        self.tile = [("eps", (0, 0) + self.size, offset,
 | 
				
			||||||
                                      (length, box))]
 | 
					                                      (length, box))]
 | 
				
			||||||
                    except:
 | 
					                    except:
 | 
				
			||||||
                        pass
 | 
					                        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
 | 
					 | 
				
			||||||
                m = field.match(s)
 | 
					                m = field.match(s)
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if m:
 | 
					                if m:
 | 
				
			||||||
                    k = m.group(1)
 | 
					                    k = m.group(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,84 +266,69 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                        self.info[k[:8]] = k[9:]
 | 
					                        self.info[k[:8]] = k[9:]
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        self.info[k] = ""
 | 
					                        self.info[k] = ""
 | 
				
			||||||
                elif s[0:1] == '%':
 | 
					                elif s[0] == '%':
 | 
				
			||||||
                    # handle non-DSC Postscript comments that some
 | 
					                    # handle non-DSC Postscript comments that some
 | 
				
			||||||
                    # tools mistakenly put in the Comments section
 | 
					                    # tools mistakenly put in the Comments section
 | 
				
			||||||
                    pass
 | 
					                    pass
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    raise IOError("bad EPS header")
 | 
					                    raise IOError("bad EPS header")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            s = fp.readline()
 | 
					            s = fp.readline().strip('\r\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if s[:1] != "%":
 | 
					            if s[:1] != "%":
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        # Scan for an "ImageData" descriptor
 | 
					        # Scan for an "ImageData" descriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while s[0] == "%":
 | 
					        while s[:1] == "%":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if len(s) > 255:
 | 
					            if len(s) > 255:
 | 
				
			||||||
                raise SyntaxError("not an EPS file")
 | 
					                raise SyntaxError("not an EPS file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if s[-2:] == '\r\n':
 | 
					 | 
				
			||||||
                s = s[:-2]
 | 
					 | 
				
			||||||
            elif s[-1:] == '\n':
 | 
					 | 
				
			||||||
                s = s[:-1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if s[:11] == "%ImageData:":
 | 
					            if s[:11] == "%ImageData:":
 | 
				
			||||||
 | 
					                # Encoded bitmapped image.
 | 
				
			||||||
 | 
					                x, y, bi, mo = s[11:].split(None, 7)[:4]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                [x, y, bi, mo, z3, z4, en, id] =\
 | 
					                if int(bi) != 8:
 | 
				
			||||||
                    s[11:].split(None, 7)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                x = int(x); y = int(y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                bi = int(bi)
 | 
					 | 
				
			||||||
                mo = int(mo)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                en = int(en)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if en == 1:
 | 
					 | 
				
			||||||
                    decoder = "eps_binary"
 | 
					 | 
				
			||||||
                elif en == 2:
 | 
					 | 
				
			||||||
                    decoder = "eps_hex"
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
                if bi != 8:
 | 
					                try:
 | 
				
			||||||
                    break
 | 
					                    self.mode = self.mode_map[int(mo)]
 | 
				
			||||||
                if mo == 1:
 | 
					                except:
 | 
				
			||||||
                    self.mode = "L"
 | 
					 | 
				
			||||||
                elif mo == 2:
 | 
					 | 
				
			||||||
                    self.mode = "LAB"
 | 
					 | 
				
			||||||
                elif mo == 3:
 | 
					 | 
				
			||||||
                    self.mode = "RGB"
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if id[:1] == id[-1:] == '"':
 | 
					                self.size = int(x), int(y)
 | 
				
			||||||
                    id = id[1:-1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Scan forward to the actual image data
 | 
					 | 
				
			||||||
                while True:
 | 
					 | 
				
			||||||
                    s = fp.readline()
 | 
					 | 
				
			||||||
                    if not s:
 | 
					 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
                    if s[:len(id)] == id:
 | 
					 | 
				
			||||||
                        self.size = x, y
 | 
					 | 
				
			||||||
                        self.tile2 = [(decoder,
 | 
					 | 
				
			||||||
                                       (0, 0, x, y),
 | 
					 | 
				
			||||||
                                       fp.tell(),
 | 
					 | 
				
			||||||
                                       0)]
 | 
					 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            s = fp.readline()
 | 
					            s = fp.readline().strip('\r\n')
 | 
				
			||||||
            if not s:
 | 
					            if not s:
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not box:
 | 
					        if not box:
 | 
				
			||||||
            raise IOError("cannot determine EPS bounding box")
 | 
					            raise IOError("cannot determine EPS bounding box")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _find_offset(self, fp):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s = fp.read(160)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if s[:4] == b"%!PS":
 | 
				
			||||||
 | 
					            # for HEAD without binary preview
 | 
				
			||||||
 | 
					            fp.seek(0, 2)
 | 
				
			||||||
 | 
					            length = fp.tell()
 | 
				
			||||||
 | 
					            offset = 0
 | 
				
			||||||
 | 
					        elif i32(s[0:4]) == 0xC6D3D0C5:
 | 
				
			||||||
 | 
					            # FIX for: Some EPS file not handled correctly / issue #302
 | 
				
			||||||
 | 
					            # EPS can contain binary data
 | 
				
			||||||
 | 
					            # or start directly with latin coding
 | 
				
			||||||
 | 
					            # more info see:
 | 
				
			||||||
 | 
					            # http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
 | 
				
			||||||
 | 
					            offset = i32(s[4:8])
 | 
				
			||||||
 | 
					            length = i32(s[8:12])
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            raise SyntaxError("not an EPS file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (length, offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def load(self, scale=1):
 | 
					    def load(self, scale=1):
 | 
				
			||||||
        # Load EPS via Ghostscript
 | 
					        # Load EPS via Ghostscript
 | 
				
			||||||
        if not self.tile:
 | 
					        if not self.tile:
 | 
				
			||||||
| 
						 | 
					@ -363,11 +338,12 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.size = self.im.size
 | 
					        self.size = self.im.size
 | 
				
			||||||
        self.tile = []
 | 
					        self.tile = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def load_seek(self,*args,**kwargs):
 | 
					    def load_seek(self, *args, **kwargs):
 | 
				
			||||||
        # we can't incrementally load, so force ImageFile.parser to
 | 
					        # we can't incrementally load, so force ImageFile.parser to
 | 
				
			||||||
        # use our custom load method by defining this method.
 | 
					        # use our custom load method by defining this method.
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -389,11 +365,13 @@ def _save(im, fp, filename, eps=1):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        raise ValueError("image mode is not supported")
 | 
					        raise ValueError("image mode is not supported")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class NoCloseStream:
 | 
					    class NoCloseStream(object):
 | 
				
			||||||
        def __init__(self, fp):
 | 
					        def __init__(self, fp):
 | 
				
			||||||
            self.fp = fp
 | 
					            self.fp = fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def __getattr__(self, name):
 | 
					        def __getattr__(self, name):
 | 
				
			||||||
            return getattr(self.fp, name)
 | 
					            return getattr(self.fp, name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def close(self):
 | 
					        def close(self):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,7 +385,7 @@ def _save(im, fp, filename, eps=1):
 | 
				
			||||||
        # write EPS header
 | 
					        # write EPS header
 | 
				
			||||||
        fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
 | 
					        fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
 | 
				
			||||||
        fp.write("%%Creator: PIL 0.1 EpsEncode\n")
 | 
					        fp.write("%%Creator: PIL 0.1 EpsEncode\n")
 | 
				
			||||||
        #fp.write("%%CreationDate: %s"...)
 | 
					        # fp.write("%%CreationDate: %s"...)
 | 
				
			||||||
        fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
 | 
					        fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
 | 
				
			||||||
        fp.write("%%Pages: 1\n")
 | 
					        fp.write("%%Pages: 1\n")
 | 
				
			||||||
        fp.write("%%EndComments\n")
 | 
					        fp.write("%%EndComments\n")
 | 
				
			||||||
| 
						 | 
					@ -427,7 +405,7 @@ def _save(im, fp, filename, eps=1):
 | 
				
			||||||
    fp.write(operator[2] + "\n")
 | 
					    fp.write(operator[2] + "\n")
 | 
				
			||||||
    fp.flush()
 | 
					    fp.flush()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, base_fp, [("eps", (0,0)+im.size, 0, None)])
 | 
					    ImageFile._save(im, base_fp, [("eps", (0, 0)+im.size, 0, None)])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fp.write("\n%%%%EndBinary\n")
 | 
					    fp.write("\n%%%%EndBinary\n")
 | 
				
			||||||
    fp.write("grestore end\n")
 | 
					    fp.write("grestore end\n")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,8 +67,8 @@ TAGS = {
 | 
				
			||||||
    0x0213: "YCbCrPositioning",
 | 
					    0x0213: "YCbCrPositioning",
 | 
				
			||||||
    0x0214: "ReferenceBlackWhite",
 | 
					    0x0214: "ReferenceBlackWhite",
 | 
				
			||||||
    0x1000: "RelatedImageFileFormat",
 | 
					    0x1000: "RelatedImageFileFormat",
 | 
				
			||||||
    0x1001: "RelatedImageLength",  # FIXME / Dictionary contains duplicate keys
 | 
					    0x1001: "RelatedImageWidth",
 | 
				
			||||||
    0x1001: "RelatedImageWidth",   # FIXME \ Dictionary contains duplicate keys
 | 
					    0x1002: "RelatedImageLength",
 | 
				
			||||||
    0x828d: "CFARepeatPatternDim",
 | 
					    0x828d: "CFARepeatPatternDim",
 | 
				
			||||||
    0x828e: "CFAPattern",
 | 
					    0x828e: "CFAPattern",
 | 
				
			||||||
    0x828f: "BatteryLevel",
 | 
					    0x828f: "BatteryLevel",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ _handler = None
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# @param handler Handler object.
 | 
					# @param handler Handler object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def register_handler(handler):
 | 
					def register_handler(handler):
 | 
				
			||||||
    global _handler
 | 
					    global _handler
 | 
				
			||||||
    _handler = handler
 | 
					    _handler = handler
 | 
				
			||||||
| 
						 | 
					@ -25,9 +26,11 @@ def register_handler(handler):
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Image adapter
 | 
					# Image adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:6] == b"SIMPLE"
 | 
					    return prefix[:6] == b"SIMPLE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FITSStubImageFile(ImageFile.StubImageFile):
 | 
					class FITSStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "FITS"
 | 
					    format = "FITS"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,12 +25,14 @@ i16 = _binary.i16le
 | 
				
			||||||
i32 = _binary.i32le
 | 
					i32 = _binary.i32le
 | 
				
			||||||
o8 = _binary.o8
 | 
					o8 = _binary.o8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# decoder
 | 
					# decoder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return i16(prefix[4:6]) in [0xAF11, 0xAF12]
 | 
					    return i16(prefix[4:6]) in [0xAF11, 0xAF12]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for the FLI/FLC animation format.  Use the <b>seek</b>
 | 
					# Image plugin for the FLI/FLC animation format.  Use the <b>seek</b>
 | 
				
			||||||
# method to load individual frames.
 | 
					# method to load individual frames.
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,7 @@ class FliImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.info["duration"] = duration
 | 
					        self.info["duration"] = duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # look for palette
 | 
					        # look for palette
 | 
				
			||||||
        palette = [(a,a,a) for a in range(256)]
 | 
					        palette = [(a, a, a) for a in range(256)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = self.fp.read(16)
 | 
					        s = self.fp.read(16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,13 +82,14 @@ class FliImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            elif i16(s[4:6]) == 4:
 | 
					            elif i16(s[4:6]) == 4:
 | 
				
			||||||
                self._palette(palette, 0)
 | 
					                self._palette(palette, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        palette = [o8(r)+o8(g)+o8(b) for (r,g,b) in palette]
 | 
					        palette = [o8(r)+o8(g)+o8(b) for (r, g, b) in palette]
 | 
				
			||||||
        self.palette = ImagePalette.raw("RGB", b"".join(palette))
 | 
					        self.palette = ImagePalette.raw("RGB", b"".join(palette))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # set things up to decode first frame
 | 
					        # set things up to decode first frame
 | 
				
			||||||
        self.frame = -1
 | 
					        self.__frame = -1
 | 
				
			||||||
        self.__fp = self.fp
 | 
					        self.__fp = self.fp
 | 
				
			||||||
 | 
					        self.__rewind = self.fp.tell()
 | 
				
			||||||
 | 
					        self._n_frames = None
 | 
				
			||||||
        self.seek(0)
 | 
					        self.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _palette(self, palette, shift):
 | 
					    def _palette(self, palette, shift):
 | 
				
			||||||
| 
						 | 
					@ -107,11 +110,35 @@ class FliImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                palette[i] = (r, g, b)
 | 
					                palette[i] = (r, g, b)
 | 
				
			||||||
                i += 1
 | 
					                i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        if self._n_frames is None:
 | 
				
			||||||
 | 
					            current = self.tell()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                while True:
 | 
				
			||||||
 | 
					                    self.seek(self.tell() + 1)
 | 
				
			||||||
 | 
					            except EOFError:
 | 
				
			||||||
 | 
					                self._n_frames = self.tell() + 1
 | 
				
			||||||
 | 
					            self.seek(current)
 | 
				
			||||||
 | 
					        return self._n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if frame != self.frame + 1:
 | 
					    def seek(self, frame):
 | 
				
			||||||
 | 
					        if frame == self.__frame:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        if frame < self.__frame:
 | 
				
			||||||
 | 
					            self._seek(0)
 | 
				
			||||||
 | 
					        for f in range(self.__frame + 1, frame + 1):
 | 
				
			||||||
 | 
					            self._seek(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _seek(self, frame):
 | 
				
			||||||
 | 
					        if frame == 0:
 | 
				
			||||||
 | 
					            self.__frame = -1
 | 
				
			||||||
 | 
					            self.__fp.seek(self.__rewind)
 | 
				
			||||||
 | 
					            self.__offset = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if frame != self.__frame + 1:
 | 
				
			||||||
            raise ValueError("cannot seek to frame %d" % frame)
 | 
					            raise ValueError("cannot seek to frame %d" % frame)
 | 
				
			||||||
        self.frame = frame
 | 
					        self.__frame = frame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # move to next frame
 | 
					        # move to next frame
 | 
				
			||||||
        self.fp = self.__fp
 | 
					        self.fp = self.__fp
 | 
				
			||||||
| 
						 | 
					@ -124,13 +151,12 @@ class FliImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        framesize = i32(s)
 | 
					        framesize = i32(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.decodermaxblock = framesize
 | 
					        self.decodermaxblock = framesize
 | 
				
			||||||
        self.tile = [("fli", (0,0)+self.size, self.__offset, None)]
 | 
					        self.tile = [("fli", (0, 0)+self.size, self.__offset, None)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__offset = self.__offset + framesize
 | 
					        self.__offset += framesize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tell(self):
 | 
					    def tell(self):
 | 
				
			||||||
 | 
					        return self.__frame
 | 
				
			||||||
        return self.frame
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# registry
 | 
					# registry
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,11 +17,6 @@
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from PIL import Image, _binary
 | 
					from PIL import Image, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					 | 
				
			||||||
    import zlib
 | 
					 | 
				
			||||||
except ImportError:
 | 
					 | 
				
			||||||
    zlib = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WIDTH = 800
 | 
					WIDTH = 800
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +31,7 @@ def puti16(fp, values):
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Base class for raster font file handlers.
 | 
					# Base class for raster font file handlers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FontFile:
 | 
					class FontFile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bitmap = None
 | 
					    bitmap = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +78,8 @@ class FontFile:
 | 
				
			||||||
            glyph = self[i]
 | 
					            glyph = self[i]
 | 
				
			||||||
            if glyph:
 | 
					            if glyph:
 | 
				
			||||||
                d, dst, src, im = glyph
 | 
					                d, dst, src, im = glyph
 | 
				
			||||||
                xx, yy = src[2] - src[0], src[3] - src[1]
 | 
					                xx = src[2] - src[0]
 | 
				
			||||||
 | 
					                # yy = src[3] - src[1]
 | 
				
			||||||
                x0, y0 = x, y
 | 
					                x0, y0 = x, y
 | 
				
			||||||
                x = x + xx
 | 
					                x = x + xx
 | 
				
			||||||
                if x > WIDTH:
 | 
					                if x > WIDTH:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ __version__ = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile
 | 
					from PIL import Image, ImageFile
 | 
				
			||||||
from PIL.OleFileIO import *
 | 
					from PIL.OleFileIO import i8, i32, MAGIC, OleFileIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# we map from colour field tuples to (mode, rawmode) descriptors
 | 
					# we map from colour field tuples to (mode, rawmode) descriptors
 | 
				
			||||||
| 
						 | 
					@ -34,16 +34,18 @@ MODES = {
 | 
				
			||||||
    (0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
 | 
					    (0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
 | 
				
			||||||
    (0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
 | 
					    (0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
 | 
				
			||||||
    # standard RGB (NIFRGB)
 | 
					    # standard RGB (NIFRGB)
 | 
				
			||||||
    (0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"),
 | 
					    (0x00030000, 0x00030001, 0x00030002): ("RGB", "RGB"),
 | 
				
			||||||
    (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA","RGBA"),
 | 
					    (0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:8] == MAGIC
 | 
					    return prefix[:8] == MAGIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for the FlashPix images.
 | 
					# Image plugin for the FlashPix images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +69,7 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._open_index(1)
 | 
					        self._open_index(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open_index(self, index = 1):
 | 
					    def _open_index(self, index=1):
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        # get the Image Contents Property Set
 | 
					        # get the Image Contents Property Set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +97,7 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        id = self.maxid << 16
 | 
					        id = self.maxid << 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = prop[0x2000002|id]
 | 
					        s = prop[0x2000002 | id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        colors = []
 | 
					        colors = []
 | 
				
			||||||
        for i in range(i32(s, 4)):
 | 
					        for i in range(i32(s, 4)):
 | 
				
			||||||
| 
						 | 
					@ -107,7 +109,7 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # load JPEG tables, if any
 | 
					        # load JPEG tables, if any
 | 
				
			||||||
        self.jpeg = {}
 | 
					        self.jpeg = {}
 | 
				
			||||||
        for i in range(256):
 | 
					        for i in range(256):
 | 
				
			||||||
            id = 0x3000001|(i << 16)
 | 
					            id = 0x3000001 | (i << 16)
 | 
				
			||||||
            if id in prop:
 | 
					            if id in prop:
 | 
				
			||||||
                self.jpeg[i] = prop[id]
 | 
					                self.jpeg[i] = prop[id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,7 +117,7 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._open_subimage(1, self.maxid)
 | 
					        self._open_subimage(1, self.maxid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open_subimage(self, index = 1, subimage = 0):
 | 
					    def _open_subimage(self, index=1, subimage=0):
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        # setup tile descriptors for a given subimage
 | 
					        # setup tile descriptors for a given subimage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,15 +130,15 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        fp = self.ole.openstream(stream)
 | 
					        fp = self.ole.openstream(stream)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # skip prefix
 | 
					        # skip prefix
 | 
				
			||||||
        p = fp.read(28)
 | 
					        fp.read(28)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # header stream
 | 
					        # header stream
 | 
				
			||||||
        s = fp.read(36)
 | 
					        s = fp.read(36)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size = i32(s, 4), i32(s, 8)
 | 
					        size = i32(s, 4), i32(s, 8)
 | 
				
			||||||
        tilecount = i32(s, 12)
 | 
					        # tilecount = i32(s, 12)
 | 
				
			||||||
        tilesize = i32(s, 16), i32(s, 20)
 | 
					        tilesize = i32(s, 16), i32(s, 20)
 | 
				
			||||||
        channels = i32(s, 24)
 | 
					        # channels = i32(s, 24)
 | 
				
			||||||
        offset = i32(s, 28)
 | 
					        offset = i32(s, 28)
 | 
				
			||||||
        length = i32(s, 32)
 | 
					        length = i32(s, 32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,13 +161,13 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            compression = i32(s, i+8)
 | 
					            compression = i32(s, i+8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if compression == 0:
 | 
					            if compression == 0:
 | 
				
			||||||
                self.tile.append(("raw", (x,y,x+xtile,y+ytile),
 | 
					                self.tile.append(("raw", (x, y, x+xtile, y+ytile),
 | 
				
			||||||
                                 i32(s, i) + 28, (self.rawmode)))
 | 
					                                 i32(s, i) + 28, (self.rawmode)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elif compression == 1:
 | 
					            elif compression == 1:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # FIXME: the fill decoder is not implemented
 | 
					                # FIXME: the fill decoder is not implemented
 | 
				
			||||||
                self.tile.append(("fill", (x,y,x+xtile,y+ytile),
 | 
					                self.tile.append(("fill", (x, y, x+xtile, y+ytile),
 | 
				
			||||||
                                 i32(s, i) + 28, (self.rawmode, s[12:16])))
 | 
					                                 i32(s, i) + 28, (self.rawmode, s[12:16])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elif compression == 2:
 | 
					            elif compression == 2:
 | 
				
			||||||
| 
						 | 
					@ -188,7 +190,7 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                    # The image is stored as defined by rawmode
 | 
					                    # The image is stored as defined by rawmode
 | 
				
			||||||
                    jpegmode = rawmode
 | 
					                    jpegmode = rawmode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                self.tile.append(("jpeg", (x,y,x+xtile,y+ytile),
 | 
					                self.tile.append(("jpeg", (x, y, x+xtile, y+ytile),
 | 
				
			||||||
                                 i32(s, i) + 28, (rawmode, jpegmode)))
 | 
					                                 i32(s, i) + 28, (rawmode, jpegmode)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # FIXME: jpeg tables are tile dependent; the prefix
 | 
					                # FIXME: jpeg tables are tile dependent; the prefix
 | 
				
			||||||
| 
						 | 
					@ -212,7 +214,8 @@ class FpxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    def load(self):
 | 
					    def load(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not self.fp:
 | 
					        if not self.fp:
 | 
				
			||||||
            self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
 | 
					            self.fp = self.ole.openstream(self.stream[:2] +
 | 
				
			||||||
 | 
					                                          ["Subimage 0000 Data"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImageFile.ImageFile.load(self)
 | 
					        ImageFile.ImageFile.load(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,9 +17,11 @@ from PIL import Image, ImageFile, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i32 = _binary.i32be
 | 
					i32 = _binary.i32be
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
 | 
					    return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for the GIMP brush format.
 | 
					# Image plugin for the GIMP brush format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,8 +39,8 @@ class GbrImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        width = i32(self.fp.read(4))
 | 
					        width = i32(self.fp.read(4))
 | 
				
			||||||
        height = i32(self.fp.read(4))
 | 
					        height = i32(self.fp.read(4))
 | 
				
			||||||
        bytes = i32(self.fp.read(4))
 | 
					        color_depth = i32(self.fp.read(4))
 | 
				
			||||||
        if width <= 0 or height <= 0 or bytes != 1:
 | 
					        if width <= 0 or height <= 0 or color_depth != 1:
 | 
				
			||||||
            raise SyntaxError("not a GIMP brush")
 | 
					            raise SyntaxError("not a GIMP brush")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        comment = self.fp.read(header_size - 20)[:-1]
 | 
					        comment = self.fp.read(header_size - 20)[:-1]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i16 = _binary.i16be
 | 
					i16 = _binary.i16be
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for the GD uncompressed format.  Note that this format
 | 
					# Image plugin for the GD uncompressed format.  Note that this format
 | 
				
			||||||
# is not supported by the standard <b>Image.open</b> function.  To use
 | 
					# is not supported by the standard <b>Image.open</b> function.  To use
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,8 @@ class GdImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.palette = ImagePalette.raw("RGB", s[7:])
 | 
					        self.palette = ImagePalette.raw("RGB", s[7:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))]
 | 
					        self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Load texture from a GD image file.
 | 
					# Load texture from a GD image file.
 | 
				
			||||||
| 
						 | 
					@ -73,7 +75,7 @@ class GdImageFile(ImageFile.ImageFile):
 | 
				
			||||||
# @return An image instance.
 | 
					# @return An image instance.
 | 
				
			||||||
# @exception IOError If the image could not be read.
 | 
					# @exception IOError If the image could not be read.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def open(fp, mode = "r"):
 | 
					def open(fp, mode="r"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if mode != "r":
 | 
					    if mode != "r":
 | 
				
			||||||
        raise ValueError("bad mode")
 | 
					        raise ValueError("bad mode")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,13 +24,11 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from PIL import Image, ImageFile, ImagePalette, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = "0.9"
 | 
					__version__ = "0.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, ImagePalette, _binary
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Helpers
 | 
					# Helpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +44,7 @@ o16 = _binary.o16le
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:6] in [b"GIF87a", b"GIF89a"]
 | 
					    return prefix[:6] in [b"GIF87a", b"GIF89a"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for GIF images.  This plugin supports both GIF87 and
 | 
					# Image plugin for GIF images.  This plugin supports both GIF87 and
 | 
				
			||||||
# GIF89 images.
 | 
					# GIF89 images.
 | 
				
			||||||
| 
						 | 
					@ -79,7 +78,7 @@ class GifImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            # get global palette
 | 
					            # get global palette
 | 
				
			||||||
            self.info["background"] = i8(s[11])
 | 
					            self.info["background"] = i8(s[11])
 | 
				
			||||||
            # check if palette contains colour indices
 | 
					            # check if palette contains colour indices
 | 
				
			||||||
            p = self.fp.read(3<<bits)
 | 
					            p = self.fp.read(3 << bits)
 | 
				
			||||||
            for i in range(0, len(p), 3):
 | 
					            for i in range(0, len(p), 3):
 | 
				
			||||||
                if not (i//3 == i8(p[i]) == i8(p[i+1]) == i8(p[i+2])):
 | 
					                if not (i//3 == i8(p[i]) == i8(p[i+1]) == i8(p[i+2])):
 | 
				
			||||||
                    p = ImagePalette.raw("RGB", p)
 | 
					                    p = ImagePalette.raw("RGB", p)
 | 
				
			||||||
| 
						 | 
					@ -88,15 +87,36 @@ class GifImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__fp = self.fp  # FIXME: hack
 | 
					        self.__fp = self.fp  # FIXME: hack
 | 
				
			||||||
        self.__rewind = self.fp.tell()
 | 
					        self.__rewind = self.fp.tell()
 | 
				
			||||||
        self.seek(0) # get ready to read first frame
 | 
					        self._n_frames = None
 | 
				
			||||||
 | 
					        self._seek(0)  # get ready to read first frame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        if self._n_frames is None:
 | 
				
			||||||
 | 
					            current = self.tell()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                while True:
 | 
				
			||||||
 | 
					                    self.seek(self.tell() + 1)
 | 
				
			||||||
 | 
					            except EOFError:
 | 
				
			||||||
 | 
					                self._n_frames = self.tell() + 1
 | 
				
			||||||
 | 
					            self.seek(current)
 | 
				
			||||||
 | 
					        return self._n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
 | 
					        if frame == self.__frame:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        if frame < self.__frame:
 | 
				
			||||||
 | 
					            self._seek(0)
 | 
				
			||||||
 | 
					        for f in range(self.__frame + 1, frame + 1):
 | 
				
			||||||
 | 
					            self._seek(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _seek(self, frame):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if frame == 0:
 | 
					        if frame == 0:
 | 
				
			||||||
            # rewind
 | 
					            # rewind
 | 
				
			||||||
            self.__offset = 0
 | 
					            self.__offset = 0
 | 
				
			||||||
            self.dispose = None
 | 
					            self.dispose = None
 | 
				
			||||||
            self.dispose_extent = [0, 0, 0, 0] #x0, y0, x1, y1
 | 
					            self.dispose_extent = [0, 0, 0, 0]  # x0, y0, x1, y1
 | 
				
			||||||
            self.__frame = -1
 | 
					            self.__frame = -1
 | 
				
			||||||
            self.__fp.seek(self.__rewind)
 | 
					            self.__fp.seek(self.__rewind)
 | 
				
			||||||
            self._prev_im = None
 | 
					            self._prev_im = None
 | 
				
			||||||
| 
						 | 
					@ -185,7 +205,7 @@ class GifImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                if flags & 128:
 | 
					                if flags & 128:
 | 
				
			||||||
                    bits = (flags & 7) + 1
 | 
					                    bits = (flags & 7) + 1
 | 
				
			||||||
                    self.palette =\
 | 
					                    self.palette =\
 | 
				
			||||||
                        ImagePalette.raw("RGB", self.fp.read(3<<bits))
 | 
					                        ImagePalette.raw("RGB", self.fp.read(3 << bits))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # image data
 | 
					                # image data
 | 
				
			||||||
                bits = i8(self.fp.read(1))
 | 
					                bits = i8(self.fp.read(1))
 | 
				
			||||||
| 
						 | 
					@ -219,7 +239,6 @@ class GifImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        except (AttributeError, KeyError):
 | 
					        except (AttributeError, KeyError):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if not self.tile:
 | 
					        if not self.tile:
 | 
				
			||||||
            # self.__fp = None
 | 
					            # self.__fp = None
 | 
				
			||||||
            raise EOFError("no more images in GIF file")
 | 
					            raise EOFError("no more images in GIF file")
 | 
				
			||||||
| 
						 | 
					@ -240,7 +259,8 @@ class GifImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            # we do this by pasting the updated area onto the previous
 | 
					            # we do this by pasting the updated area onto the previous
 | 
				
			||||||
            # frame which we then use as the current image content
 | 
					            # frame which we then use as the current image content
 | 
				
			||||||
            updated = self.im.crop(self.dispose_extent)
 | 
					            updated = self.im.crop(self.dispose_extent)
 | 
				
			||||||
            self._prev_im.paste(updated, self.dispose_extent, updated.convert('RGBA'))
 | 
					            self._prev_im.paste(updated, self.dispose_extent,
 | 
				
			||||||
 | 
					                                updated.convert('RGBA'))
 | 
				
			||||||
            self.im = self._prev_im
 | 
					            self.im = self._prev_im
 | 
				
			||||||
        self._prev_im = self.im.copy()
 | 
					        self._prev_im = self.im.copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,6 +278,7 @@ RAWMODE = {
 | 
				
			||||||
    "P": "P",
 | 
					    "P": "P",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename):
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if _imaging_gif:
 | 
					    if _imaging_gif:
 | 
				
			||||||
| 
						 | 
					@ -269,7 +290,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
            pass  # write uncompressed file
 | 
					            pass  # write uncompressed file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if im.mode in RAWMODE:
 | 
					    if im.mode in RAWMODE:
 | 
				
			||||||
        imOut = im
 | 
					        im_out = im
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # convert on the fly (EXPERIMENTAL -- I'm not sure PIL
 | 
					        # convert on the fly (EXPERIMENTAL -- I'm not sure PIL
 | 
				
			||||||
        # should automatically convert images on save...)
 | 
					        # should automatically convert images on save...)
 | 
				
			||||||
| 
						 | 
					@ -277,9 +298,9 @@ def _save(im, fp, filename):
 | 
				
			||||||
            palette_size = 256
 | 
					            palette_size = 256
 | 
				
			||||||
            if im.palette:
 | 
					            if im.palette:
 | 
				
			||||||
                palette_size = len(im.palette.getdata()[1]) // 3
 | 
					                palette_size = len(im.palette.getdata()[1]) // 3
 | 
				
			||||||
            imOut = im.convert("P", palette=1, colors=palette_size)
 | 
					            im_out = im.convert("P", palette=1, colors=palette_size)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            imOut = im.convert("L")
 | 
					            im_out = im.convert("L")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # header
 | 
					    # header
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -288,12 +309,33 @@ def _save(im, fp, filename):
 | 
				
			||||||
        palette = None
 | 
					        palette = None
 | 
				
			||||||
        im.encoderinfo["optimize"] = im.encoderinfo.get("optimize", True)
 | 
					        im.encoderinfo["optimize"] = im.encoderinfo.get("optimize", True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    header, usedPaletteColors = getheader(imOut, palette, im.encoderinfo)
 | 
					    header, used_palette_colors = getheader(im_out, palette, im.encoderinfo)
 | 
				
			||||||
    for s in header:
 | 
					    for s in header:
 | 
				
			||||||
        fp.write(s)
 | 
					        fp.write(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flags = 0
 | 
					    flags = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if get_interlace(im):
 | 
				
			||||||
 | 
					        flags = flags | 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # local image header
 | 
				
			||||||
 | 
					    get_local_header(fp, im, (0, 0), flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    im_out.encoderconfig = (8, get_interlace(im))
 | 
				
			||||||
 | 
					    ImageFile._save(im_out, fp, [("gif", (0, 0)+im.size, 0,
 | 
				
			||||||
 | 
					                                  RAWMODE[im_out.mode])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fp.write(b"\0")  # end of image data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fp.write(b";")  # end of file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        fp.flush()
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_interlace(im):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        interlace = im.encoderinfo["interlace"]
 | 
					        interlace = im.encoderinfo["interlace"]
 | 
				
			||||||
    except KeyError:
 | 
					    except KeyError:
 | 
				
			||||||
| 
						 | 
					@ -303,9 +345,11 @@ def _save(im, fp, filename):
 | 
				
			||||||
    if min(im.size) < 16:
 | 
					    if min(im.size) < 16:
 | 
				
			||||||
        interlace = 0
 | 
					        interlace = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if interlace:
 | 
					    return interlace
 | 
				
			||||||
        flags = flags | 64
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_local_header(fp, im, offset, flags):
 | 
				
			||||||
 | 
					    transparent_color_exists = False
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        transparency = im.encoderinfo["transparency"]
 | 
					        transparency = im.encoderinfo["transparency"]
 | 
				
			||||||
    except KeyError:
 | 
					    except KeyError:
 | 
				
			||||||
| 
						 | 
					@ -313,46 +357,56 @@ def _save(im, fp, filename):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        transparency = int(transparency)
 | 
					        transparency = int(transparency)
 | 
				
			||||||
        # optimize the block away if transparent color is not used
 | 
					        # optimize the block away if transparent color is not used
 | 
				
			||||||
        transparentColorExists = True
 | 
					        transparent_color_exists = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if _get_optimize(im, im.encoderinfo):
 | 
				
			||||||
 | 
					            used_palette_colors = _get_used_palette_colors(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # adjust the transparency index after optimize
 | 
					            # adjust the transparency index after optimize
 | 
				
			||||||
        if usedPaletteColors is not None and len(usedPaletteColors) < 256:
 | 
					            if len(used_palette_colors) < 256:
 | 
				
			||||||
            for i in range(len(usedPaletteColors)):
 | 
					                for i in range(len(used_palette_colors)):
 | 
				
			||||||
                if usedPaletteColors[i] == transparency:
 | 
					                    if used_palette_colors[i] == transparency:
 | 
				
			||||||
                        transparency = i
 | 
					                        transparency = i
 | 
				
			||||||
                    transparentColorExists = True
 | 
					                        transparent_color_exists = True
 | 
				
			||||||
                        break
 | 
					                        break
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                    transparentColorExists = False
 | 
					                        transparent_color_exists = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if "duration" in im.encoderinfo:
 | 
				
			||||||
 | 
					        duration = int(im.encoderinfo["duration"] / 10)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        duration = 0
 | 
				
			||||||
 | 
					    if transparent_color_exists or duration != 0:
 | 
				
			||||||
 | 
					        transparency_flag = 1 if transparent_color_exists else 0
 | 
				
			||||||
 | 
					        if not transparent_color_exists:
 | 
				
			||||||
 | 
					            transparency = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # transparency extension block
 | 
					 | 
				
			||||||
        if transparentColorExists:
 | 
					 | 
				
			||||||
        fp.write(b"!" +
 | 
					        fp.write(b"!" +
 | 
				
			||||||
                 o8(249) +                # extension intro
 | 
					                 o8(249) +                # extension intro
 | 
				
			||||||
                 o8(4) +                  # length
 | 
					                 o8(4) +                  # length
 | 
				
			||||||
                     o8(1) +                # transparency info present
 | 
					                 o8(transparency_flag) +  # transparency info present
 | 
				
			||||||
                     o16(0) +               # duration
 | 
					                 o16(duration) +          # duration
 | 
				
			||||||
                     o8(transparency)       # transparency index
 | 
					                 o8(transparency) +       # transparency index
 | 
				
			||||||
                     + o8(0))
 | 
					                 o8(0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # local image header
 | 
					    if "loop" in im.encoderinfo:
 | 
				
			||||||
 | 
					        number_of_loops = im.encoderinfo["loop"]
 | 
				
			||||||
 | 
					        fp.write(b"!" +
 | 
				
			||||||
 | 
					                 o8(255) +                # extension intro
 | 
				
			||||||
 | 
					                 o8(11) +
 | 
				
			||||||
 | 
					                 b"NETSCAPE2.0" +
 | 
				
			||||||
 | 
					                 o8(3) +
 | 
				
			||||||
 | 
					                 o8(1) +
 | 
				
			||||||
 | 
					                 o16(number_of_loops) +   # number of loops
 | 
				
			||||||
 | 
					                 o8(0))
 | 
				
			||||||
    fp.write(b"," +
 | 
					    fp.write(b"," +
 | 
				
			||||||
             o16(0) + o16(0) +          # bounding box
 | 
					             o16(offset[0]) +             # offset
 | 
				
			||||||
 | 
					             o16(offset[1]) +
 | 
				
			||||||
             o16(im.size[0]) +            # size
 | 
					             o16(im.size[0]) +            # size
 | 
				
			||||||
             o16(im.size[1]) +
 | 
					             o16(im.size[1]) +
 | 
				
			||||||
             o8(flags) +                  # flags
 | 
					             o8(flags) +                  # flags
 | 
				
			||||||
             o8(8))                       # bits
 | 
					             o8(8))                       # bits
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    imOut.encoderconfig = (8, interlace)
 | 
					 | 
				
			||||||
    ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, RAWMODE[imOut.mode])])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fp.write(b"\0") # end of image data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fp.write(b";") # end of file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        fp.flush()
 | 
					 | 
				
			||||||
    except: pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save_netpbm(im, fp, filename):
 | 
					def _save_netpbm(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -380,7 +434,8 @@ def _save_netpbm(im, fp, filename):
 | 
				
			||||||
            stderr = tempfile.TemporaryFile()
 | 
					            stderr = tempfile.TemporaryFile()
 | 
				
			||||||
            quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr)
 | 
					            quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr)
 | 
				
			||||||
            stderr = tempfile.TemporaryFile()
 | 
					            stderr = tempfile.TemporaryFile()
 | 
				
			||||||
            togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=stderr)
 | 
					            togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f,
 | 
				
			||||||
 | 
					                               stderr=stderr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Allow ppmquant to receive SIGPIPE if ppmtogif exits
 | 
					            # Allow ppmquant to receive SIGPIPE if ppmtogif exits
 | 
				
			||||||
            quant_proc.stdout.close()
 | 
					            quant_proc.stdout.close()
 | 
				
			||||||
| 
						 | 
					@ -402,11 +457,26 @@ def _save_netpbm(im, fp, filename):
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# GIF utilities
 | 
					# GIF utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _get_optimize(im, info):
 | 
				
			||||||
 | 
					    return im.mode in ("P", "L") and info and info.get("optimize", 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _get_used_palette_colors(im):
 | 
				
			||||||
 | 
					    used_palette_colors = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # check which colors are used
 | 
				
			||||||
 | 
					    i = 0
 | 
				
			||||||
 | 
					    for count in im.histogram():
 | 
				
			||||||
 | 
					        if count:
 | 
				
			||||||
 | 
					            used_palette_colors.append(i)
 | 
				
			||||||
 | 
					        i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return used_palette_colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getheader(im, palette=None, info=None):
 | 
					def getheader(im, palette=None, info=None):
 | 
				
			||||||
    """Return a list of strings representing a GIF header"""
 | 
					    """Return a list of strings representing a GIF header"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    optimize = info and info.get("optimize", 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Header Block
 | 
					    # Header Block
 | 
				
			||||||
    # http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
 | 
					    # http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
 | 
				
			||||||
    header = [
 | 
					    header = [
 | 
				
			||||||
| 
						 | 
					@ -417,100 +487,92 @@ def getheader(im, palette=None, info=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if im.mode == "P":
 | 
					    if im.mode == "P":
 | 
				
			||||||
        if palette and isinstance(palette, bytes):
 | 
					        if palette and isinstance(palette, bytes):
 | 
				
			||||||
            sourcePalette = palette[:768]
 | 
					            source_palette = palette[:768]
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            sourcePalette = im.im.getpalette("RGB")[:768]
 | 
					            source_palette = im.im.getpalette("RGB")[:768]
 | 
				
			||||||
    else:  # L-mode
 | 
					    else:  # L-mode
 | 
				
			||||||
        if palette and isinstance(palette, bytes):
 | 
					        if palette and isinstance(palette, bytes):
 | 
				
			||||||
            sourcePalette = palette[:768]
 | 
					            source_palette = palette[:768]
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            sourcePalette = bytearray([i//3 for i in range(768)])
 | 
					            source_palette = bytearray([i//3 for i in range(768)])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    usedPaletteColors = paletteBytes = None
 | 
					    used_palette_colors = palette_bytes = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if optimize:
 | 
					    if _get_optimize(im, info):
 | 
				
			||||||
        usedPaletteColors = []
 | 
					        used_palette_colors = _get_used_palette_colors(im)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        # check which colors are used
 | 
					 | 
				
			||||||
        i = 0
 | 
					 | 
				
			||||||
        for count in im.histogram():
 | 
					 | 
				
			||||||
            if count:
 | 
					 | 
				
			||||||
                usedPaletteColors.append(i)
 | 
					 | 
				
			||||||
            i += 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # create the new palette if not every color is used
 | 
					        # create the new palette if not every color is used
 | 
				
			||||||
        if len(usedPaletteColors) < 256:
 | 
					        if len(used_palette_colors) < 256:
 | 
				
			||||||
            paletteBytes = b""
 | 
					            palette_bytes = b""
 | 
				
			||||||
            newPositions = {}
 | 
					            new_positions = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            i = 0
 | 
					            i = 0
 | 
				
			||||||
            # pick only the used colors from the palette
 | 
					            # pick only the used colors from the palette
 | 
				
			||||||
            for oldPosition in usedPaletteColors:
 | 
					            for oldPosition in used_palette_colors:
 | 
				
			||||||
                paletteBytes += sourcePalette[oldPosition*3:oldPosition*3+3]
 | 
					                palette_bytes += source_palette[oldPosition*3:oldPosition*3+3]
 | 
				
			||||||
                newPositions[oldPosition] = i
 | 
					                new_positions[oldPosition] = i
 | 
				
			||||||
                i += 1
 | 
					                i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # replace the palette color id of all pixel with the new id
 | 
					            # replace the palette color id of all pixel with the new id
 | 
				
			||||||
            imageBytes = bytearray(im.tobytes())
 | 
					            image_bytes = bytearray(im.tobytes())
 | 
				
			||||||
            for i in range(len(imageBytes)):
 | 
					            for i in range(len(image_bytes)):
 | 
				
			||||||
                imageBytes[i] = newPositions[imageBytes[i]]
 | 
					                image_bytes[i] = new_positions[image_bytes[i]]
 | 
				
			||||||
            im.frombytes(bytes(imageBytes))
 | 
					            im.frombytes(bytes(image_bytes))
 | 
				
			||||||
            newPaletteBytes = paletteBytes + (768 - len(paletteBytes)) * b'\x00'
 | 
					            new_palette_bytes = (palette_bytes +
 | 
				
			||||||
            im.putpalette(newPaletteBytes) 
 | 
					                                 (768 - len(palette_bytes)) * b'\x00')
 | 
				
			||||||
            im.palette = ImagePalette.ImagePalette("RGB", palette = paletteBytes, size = len(paletteBytes))
 | 
					            im.putpalette(new_palette_bytes)
 | 
				
			||||||
 | 
					            im.palette = ImagePalette.ImagePalette("RGB",
 | 
				
			||||||
 | 
					                                                   palette=palette_bytes,
 | 
				
			||||||
 | 
					                                                   size=len(palette_bytes))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not paletteBytes:
 | 
					    if not palette_bytes:
 | 
				
			||||||
        paletteBytes = sourcePalette
 | 
					        palette_bytes = source_palette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Logical Screen Descriptor
 | 
					    # Logical Screen Descriptor
 | 
				
			||||||
    # calculate the palette size for the header
 | 
					    # calculate the palette size for the header
 | 
				
			||||||
    import math
 | 
					    import math
 | 
				
			||||||
    colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1
 | 
					    color_table_size = int(math.ceil(math.log(len(palette_bytes)//3, 2)))-1
 | 
				
			||||||
    if colorTableSize < 0: colorTableSize = 0
 | 
					    if color_table_size < 0:
 | 
				
			||||||
 | 
					        color_table_size = 0
 | 
				
			||||||
    # size of global color table + global color table flag
 | 
					    # size of global color table + global color table flag
 | 
				
			||||||
    header.append(o8(colorTableSize + 128))
 | 
					    header.append(o8(color_table_size + 128))
 | 
				
			||||||
    # background + reserved/aspect
 | 
					    # background + reserved/aspect
 | 
				
			||||||
    header.append(o8(0) + o8(0))
 | 
					    header.append(o8(0) + o8(0))
 | 
				
			||||||
    # end of Logical Screen Descriptor
 | 
					    # end of Logical Screen Descriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # add the missing amount of bytes
 | 
					    # add the missing amount of bytes
 | 
				
			||||||
    # the palette has to be 2<<n in size
 | 
					    # the palette has to be 2<<n in size
 | 
				
			||||||
    actualTargetSizeDiff = (2<<colorTableSize) - len(paletteBytes)//3
 | 
					    actual_target_size_diff = (2 << color_table_size) - len(palette_bytes)//3
 | 
				
			||||||
    if actualTargetSizeDiff > 0:
 | 
					    if actual_target_size_diff > 0:
 | 
				
			||||||
        paletteBytes += o8(0) * 3 * actualTargetSizeDiff
 | 
					        palette_bytes += o8(0) * 3 * actual_target_size_diff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Header + Logical Screen Descriptor + Global Color Table
 | 
					    # Header + Logical Screen Descriptor + Global Color Table
 | 
				
			||||||
    header.append(paletteBytes)
 | 
					    header.append(palette_bytes)
 | 
				
			||||||
    return header, usedPaletteColors
 | 
					    return header, used_palette_colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getdata(im, offset = (0, 0), **params):
 | 
					def getdata(im, offset=(0, 0), **params):
 | 
				
			||||||
    """Return a list of strings representing this image.
 | 
					    """Return a list of strings representing this image.
 | 
				
			||||||
       The first string is a local image header, the rest contains
 | 
					       The first string is a local image header, the rest contains
 | 
				
			||||||
       encoded image data."""
 | 
					       encoded image data."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class collector:
 | 
					    class Collector(object):
 | 
				
			||||||
        data = []
 | 
					        data = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def write(self, data):
 | 
					        def write(self, data):
 | 
				
			||||||
            self.data.append(data)
 | 
					            self.data.append(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im.load()  # make sure raster data is available
 | 
					    im.load()  # make sure raster data is available
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fp = collector()
 | 
					    fp = Collector()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        im.encoderinfo = params
 | 
					        im.encoderinfo = params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # local image header
 | 
					        # local image header
 | 
				
			||||||
        fp.write(b"," +
 | 
					        get_local_header(fp, im, offset, 0)
 | 
				
			||||||
                 o16(offset[0]) +       # offset
 | 
					 | 
				
			||||||
                 o16(offset[1]) +
 | 
					 | 
				
			||||||
                 o16(im.size[0]) +      # size
 | 
					 | 
				
			||||||
                 o16(im.size[1]) +
 | 
					 | 
				
			||||||
                 o8(0) +                # flags
 | 
					 | 
				
			||||||
                 o8(8))                 # bits
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])
 | 
					        ImageFile._save(im, fp, [("gif", (0, 0)+im.size, 0, RAWMODE[im.mode])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fp.write(b"\0")  # end of image data
 | 
					        fp.write(b"\0")  # end of image data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ from PIL._binary import o8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EPSILON = 1e-10
 | 
					EPSILON = 1e-10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def linear(middle, pos):
 | 
					def linear(middle, pos):
 | 
				
			||||||
    if pos <= middle:
 | 
					    if pos <= middle:
 | 
				
			||||||
        if middle < EPSILON:
 | 
					        if middle < EPSILON:
 | 
				
			||||||
| 
						 | 
					@ -38,25 +39,30 @@ def linear(middle, pos):
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return 0.5 + 0.5 * pos / middle
 | 
					            return 0.5 + 0.5 * pos / middle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def curved(middle, pos):
 | 
					def curved(middle, pos):
 | 
				
			||||||
    return pos ** (log(0.5) / log(max(middle, EPSILON)))
 | 
					    return pos ** (log(0.5) / log(max(middle, EPSILON)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sine(middle, pos):
 | 
					def sine(middle, pos):
 | 
				
			||||||
    return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0
 | 
					    return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sphere_increasing(middle, pos):
 | 
					def sphere_increasing(middle, pos):
 | 
				
			||||||
    return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2)
 | 
					    return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sphere_decreasing(middle, pos):
 | 
					def sphere_decreasing(middle, pos):
 | 
				
			||||||
    return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2)
 | 
					    return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SEGMENTS = [ linear, curved, sine, sphere_increasing, sphere_decreasing ]
 | 
					SEGMENTS = [linear, curved, sine, sphere_increasing, sphere_decreasing]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GradientFile:
 | 
					
 | 
				
			||||||
 | 
					class GradientFile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gradient = None
 | 
					    gradient = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getpalette(self, entries = 256):
 | 
					    def getpalette(self, entries=256):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        palette = []
 | 
					        palette = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,6 +95,7 @@ class GradientFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return b"".join(palette), "RGBA"
 | 
					        return b"".join(palette), "RGBA"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# File handler for GIMP's gradient format.
 | 
					# File handler for GIMP's gradient format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +106,13 @@ class GimpGradientFile(GradientFile):
 | 
				
			||||||
        if fp.readline()[:13] != b"GIMP Gradient":
 | 
					        if fp.readline()[:13] != b"GIMP Gradient":
 | 
				
			||||||
            raise SyntaxError("not a GIMP gradient file")
 | 
					            raise SyntaxError("not a GIMP gradient file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        count = int(fp.readline())
 | 
					        line = fp.readline()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # GIMP 1.2 gradient files don't contain a name, but GIMP 1.3 files do
 | 
				
			||||||
 | 
					        if line.startswith(b"Name: "):
 | 
				
			||||||
 | 
					            line = fp.readline().strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count = int(line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gradient = []
 | 
					        gradient = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,10 +17,11 @@
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from PIL._binary import o8
 | 
					from PIL._binary import o8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# File handler for GIMP's palette format.
 | 
					# File handler for GIMP's palette format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GimpPaletteFile:
 | 
					class GimpPaletteFile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rawmode = "RGB"
 | 
					    rawmode = "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +57,6 @@ class GimpPaletteFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.palette = b"".join(self.palette)
 | 
					        self.palette = b"".join(self.palette)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getpalette(self):
 | 
					    def getpalette(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.palette, self.rawmode
 | 
					        return self.palette, self.rawmode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_handler = None
 | 
					_handler = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Install application-specific GRIB image handler.
 | 
					# Install application-specific GRIB image handler.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -22,12 +23,14 @@ def register_handler(handler):
 | 
				
			||||||
    global _handler
 | 
					    global _handler
 | 
				
			||||||
    _handler = handler
 | 
					    _handler = handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Image adapter
 | 
					# Image adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01'
 | 
					    return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GribStubImageFile(ImageFile.StubImageFile):
 | 
					class GribStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "GRIB"
 | 
					    format = "GRIB"
 | 
				
			||||||
| 
						 | 
					@ -53,6 +56,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
    def _load(self):
 | 
					    def _load(self):
 | 
				
			||||||
        return _handler
 | 
					        return _handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename):
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
    if _handler is None or not hasattr("_handler", "save"):
 | 
					    if _handler is None or not hasattr("_handler", "save"):
 | 
				
			||||||
        raise IOError("GRIB save handler not installed")
 | 
					        raise IOError("GRIB save handler not installed")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ from PIL import Image, ImageFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_handler = None
 | 
					_handler = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Install application-specific HDF5 image handler.
 | 
					# Install application-specific HDF5 image handler.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -22,12 +23,14 @@ def register_handler(handler):
 | 
				
			||||||
    global _handler
 | 
					    global _handler
 | 
				
			||||||
    _handler = handler
 | 
					    _handler = handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Image adapter
 | 
					# Image adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:8] == b"\x89HDF\r\n\x1a\n"
 | 
					    return prefix[:8] == b"\x89HDF\r\n\x1a\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HDF5StubImageFile(ImageFile.StubImageFile):
 | 
					class HDF5StubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    format = "HDF5"
 | 
					    format = "HDF5"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,12 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, PngImagePlugin, _binary
 | 
					from PIL import Image, ImageFile, PngImagePlugin, _binary
 | 
				
			||||||
import struct, io
 | 
					import io
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import tempfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
 | 
					enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
 | 
				
			||||||
if enable_jpeg2k:
 | 
					if enable_jpeg2k:
 | 
				
			||||||
| 
						 | 
					@ -26,9 +31,11 @@ i8 = _binary.i8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HEADERSIZE = 8
 | 
					HEADERSIZE = 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def nextheader(fobj):
 | 
					def nextheader(fobj):
 | 
				
			||||||
    return struct.unpack('>4sI', fobj.read(HEADERSIZE))
 | 
					    return struct.unpack('>4sI', fobj.read(HEADERSIZE))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_32t(fobj, start_length, size):
 | 
					def read_32t(fobj, start_length, size):
 | 
				
			||||||
    # The 128x128 icon seems to have an extra header for some reason.
 | 
					    # The 128x128 icon seems to have an extra header for some reason.
 | 
				
			||||||
    (start, length) = start_length
 | 
					    (start, length) = start_length
 | 
				
			||||||
| 
						 | 
					@ -38,6 +45,7 @@ def read_32t(fobj, start_length, size):
 | 
				
			||||||
        raise SyntaxError('Unknown signature, expecting 0x00000000')
 | 
					        raise SyntaxError('Unknown signature, expecting 0x00000000')
 | 
				
			||||||
    return read_32(fobj, (start + 4, length - 4), size)
 | 
					    return read_32(fobj, (start + 4, length - 4), size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_32(fobj, start_length, size):
 | 
					def read_32(fobj, start_length, size):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Read a 32bit RGB icon resource.  Seems to be either uncompressed or
 | 
					    Read a 32bit RGB icon resource.  Seems to be either uncompressed or
 | 
				
			||||||
| 
						 | 
					@ -83,9 +91,10 @@ def read_32(fobj, start_length, size):
 | 
				
			||||||
            im.im.putband(band.im, band_ix)
 | 
					            im.im.putband(band.im, band_ix)
 | 
				
			||||||
    return {"RGB": im}
 | 
					    return {"RGB": im}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_mk(fobj, start_length, size):
 | 
					def read_mk(fobj, start_length, size):
 | 
				
			||||||
    # Alpha masks seem to be uncompressed
 | 
					    # Alpha masks seem to be uncompressed
 | 
				
			||||||
    (start, length) = start_length
 | 
					    start = start_length[0]
 | 
				
			||||||
    fobj.seek(start)
 | 
					    fobj.seek(start)
 | 
				
			||||||
    pixel_size = (size[0] * size[2], size[1] * size[2])
 | 
					    pixel_size = (size[0] * size[2], size[1] * size[2])
 | 
				
			||||||
    sizesq = pixel_size[0] * pixel_size[1]
 | 
					    sizesq = pixel_size[0] * pixel_size[1]
 | 
				
			||||||
| 
						 | 
					@ -94,6 +103,7 @@ def read_mk(fobj, start_length, size):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    return {"A": band}
 | 
					    return {"A": band}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def read_png_or_jpeg2000(fobj, start_length, size):
 | 
					def read_png_or_jpeg2000(fobj, start_length, size):
 | 
				
			||||||
    (start, length) = start_length
 | 
					    (start, length) = start_length
 | 
				
			||||||
    fobj.seek(start)
 | 
					    fobj.seek(start)
 | 
				
			||||||
| 
						 | 
					@ -106,7 +116,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
 | 
				
			||||||
            or sig[:4] == b'\x0d\x0a\x87\x0a' \
 | 
					            or sig[:4] == b'\x0d\x0a\x87\x0a' \
 | 
				
			||||||
            or sig == b'\x00\x00\x00\x0cjP  \x0d\x0a\x87\x0a':
 | 
					            or sig == b'\x00\x00\x00\x0cjP  \x0d\x0a\x87\x0a':
 | 
				
			||||||
        if not enable_jpeg2k:
 | 
					        if not enable_jpeg2k:
 | 
				
			||||||
            raise ValueError('Unsupported icon subimage format (rebuild PIL with JPEG 2000 support to fix this)')
 | 
					            raise ValueError('Unsupported icon subimage format (rebuild PIL '
 | 
				
			||||||
 | 
					                             'with JPEG 2000 support to fix this)')
 | 
				
			||||||
        # j2k, jpc or j2c
 | 
					        # j2k, jpc or j2c
 | 
				
			||||||
        fobj.seek(start)
 | 
					        fobj.seek(start)
 | 
				
			||||||
        jp2kstream = fobj.read(length)
 | 
					        jp2kstream = fobj.read(length)
 | 
				
			||||||
| 
						 | 
					@ -118,7 +129,8 @@ def read_png_or_jpeg2000(fobj, start_length, size):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        raise ValueError('Unsupported icon subimage format')
 | 
					        raise ValueError('Unsupported icon subimage format')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IcnsFile:
 | 
					
 | 
				
			||||||
 | 
					class IcnsFile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SIZES = {
 | 
					    SIZES = {
 | 
				
			||||||
        (512, 512, 2): [
 | 
					        (512, 512, 2): [
 | 
				
			||||||
| 
						 | 
					@ -233,12 +245,13 @@ class IcnsFile:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
        return im
 | 
					        return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Mac OS icons.
 | 
					# Image plugin for Mac OS icons.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IcnsImageFile(ImageFile.ImageFile):
 | 
					class IcnsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    PIL read-only image support for Mac OS .icns files.
 | 
					    PIL image support for Mac OS .icns files.
 | 
				
			||||||
    Chooses the best resolution, but will possibly load
 | 
					    Chooses the best resolution, but will possibly load
 | 
				
			||||||
    a different size image if you mutate the size attribute
 | 
					    a different size image if you mutate the size attribute
 | 
				
			||||||
    before calling 'load'.
 | 
					    before calling 'load'.
 | 
				
			||||||
| 
						 | 
					@ -284,11 +297,64 @@ class IcnsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.tile = ()
 | 
					        self.tile = ()
 | 
				
			||||||
        self.load_end()
 | 
					        self.load_end()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Saves the image as a series of PNG files,
 | 
				
			||||||
 | 
					    that are then converted to a .icns file
 | 
				
			||||||
 | 
					    using the OS X command line utility 'iconutil'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    OS X only.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        fp.flush()
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # create the temporary set of pngs
 | 
				
			||||||
 | 
					    iconset = tempfile.mkdtemp('.iconset')
 | 
				
			||||||
 | 
					    last_w = None
 | 
				
			||||||
 | 
					    last_im = None
 | 
				
			||||||
 | 
					    for w in [16, 32, 128, 256, 512]:
 | 
				
			||||||
 | 
					        prefix = 'icon_{}x{}'.format(w, w)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if last_w == w:
 | 
				
			||||||
 | 
					            im_scaled = last_im
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            im_scaled = im.resize((w, w), Image.LANCZOS)
 | 
				
			||||||
 | 
					        im_scaled.save(os.path.join(iconset, prefix+'.png'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        im_scaled = im.resize((w*2, w*2), Image.LANCZOS)
 | 
				
			||||||
 | 
					        im_scaled.save(os.path.join(iconset, prefix+'@2x.png'))
 | 
				
			||||||
 | 
					        last_im = im_scaled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # iconutil -c icns -o {} {}
 | 
				
			||||||
 | 
					    from subprocess import Popen, PIPE, CalledProcessError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    convert_cmd = ["iconutil", "-c", "icns", "-o", filename, iconset]
 | 
				
			||||||
 | 
					    stderr = tempfile.TemporaryFile()
 | 
				
			||||||
 | 
					    convert_proc = Popen(convert_cmd, stdout=PIPE, stderr=stderr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    convert_proc.stdout.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    retcode = convert_proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # remove the temporary files
 | 
				
			||||||
 | 
					    shutil.rmtree(iconset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if retcode:
 | 
				
			||||||
 | 
					        raise CalledProcessError(retcode, convert_cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == b'icns')
 | 
					Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == b'icns')
 | 
				
			||||||
Image.register_extension("ICNS", '.icns')
 | 
					Image.register_extension("ICNS", '.icns')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if sys.platform == 'darwin':
 | 
				
			||||||
 | 
					    Image.register_save("ICNS", _save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Image.register_mime("ICNS", "image/icns")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    import os, sys
 | 
					 | 
				
			||||||
    imf = IcnsImageFile(open(sys.argv[1], 'rb'))
 | 
					    imf = IcnsImageFile(open(sys.argv[1], 'rb'))
 | 
				
			||||||
    for size in imf.info['sizes']:
 | 
					    for size in imf.info['sizes']:
 | 
				
			||||||
        imf.size = size
 | 
					        imf.size = size
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,8 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
 | 
					# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
 | 
				
			||||||
 | 
					# <casadebender@gmail.com>.
 | 
				
			||||||
# https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
					# https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Icon format references:
 | 
					# Icon format references:
 | 
				
			||||||
| 
						 | 
					@ -23,6 +24,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = "0.1"
 | 
					__version__ = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, BmpImagePlugin, PngImagePlugin, _binary
 | 
					from PIL import Image, ImageFile, BmpImagePlugin, PngImagePlugin, _binary
 | 
				
			||||||
from math import log, ceil
 | 
					from math import log, ceil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,11 +39,47 @@ i32 = _binary.i32le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_MAGIC = b"\0\0\1\0"
 | 
					_MAGIC = b"\0\0\1\0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
 | 
					    fp.write(_MAGIC)  # (2+2)
 | 
				
			||||||
 | 
					    sizes = im.encoderinfo.get("sizes",
 | 
				
			||||||
 | 
					                               [(16, 16), (24, 24), (32, 32), (48, 48),
 | 
				
			||||||
 | 
					                                (64, 64), (128, 128), (255, 255)])
 | 
				
			||||||
 | 
					    width, height = im.size
 | 
				
			||||||
 | 
					    filter(lambda x: False if (x[0] > width or x[1] > height or
 | 
				
			||||||
 | 
					                               x[0] > 255 or x[1] > 255) else True, sizes)
 | 
				
			||||||
 | 
					    fp.write(struct.pack("<H", len(sizes)))  # idCount(2)
 | 
				
			||||||
 | 
					    offset = fp.tell() + len(sizes)*16
 | 
				
			||||||
 | 
					    for size in sizes:
 | 
				
			||||||
 | 
					        width, height = size
 | 
				
			||||||
 | 
					        fp.write(struct.pack("B", width))  # bWidth(1)
 | 
				
			||||||
 | 
					        fp.write(struct.pack("B", height))  # bHeight(1)
 | 
				
			||||||
 | 
					        fp.write(b"\0")  # bColorCount(1)
 | 
				
			||||||
 | 
					        fp.write(b"\0")  # bReserved(1)
 | 
				
			||||||
 | 
					        fp.write(b"\0\0")  # wPlanes(2)
 | 
				
			||||||
 | 
					        fp.write(struct.pack("<H", 32))  # wBitCount(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        image_io = BytesIO()
 | 
				
			||||||
 | 
					        tmp = im.copy()
 | 
				
			||||||
 | 
					        tmp.thumbnail(size, Image.LANCZOS)
 | 
				
			||||||
 | 
					        tmp.save(image_io, "png")
 | 
				
			||||||
 | 
					        image_io.seek(0)
 | 
				
			||||||
 | 
					        image_bytes = image_io.read()
 | 
				
			||||||
 | 
					        bytes_len = len(image_bytes)
 | 
				
			||||||
 | 
					        fp.write(struct.pack("<I", bytes_len))  # dwBytesInRes(4)
 | 
				
			||||||
 | 
					        fp.write(struct.pack("<I", offset))  # dwImageOffset(4)
 | 
				
			||||||
 | 
					        current = fp.tell()
 | 
				
			||||||
 | 
					        fp.seek(offset)
 | 
				
			||||||
 | 
					        fp.write(image_bytes)
 | 
				
			||||||
 | 
					        offset = offset + bytes_len
 | 
				
			||||||
 | 
					        fp.seek(current)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:4] == _MAGIC
 | 
					    return prefix[:4] == _MAGIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IcoFile:
 | 
					class IcoFile(object):
 | 
				
			||||||
    def __init__(self, buf):
 | 
					    def __init__(self, buf):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Parse image from file-like object containing ico file data
 | 
					        Parse image from file-like object containing ico file data
 | 
				
			||||||
| 
						 | 
					@ -63,7 +103,7 @@ class IcoFile:
 | 
				
			||||||
            icon_header = {
 | 
					            icon_header = {
 | 
				
			||||||
                'width': i8(s[0]),
 | 
					                'width': i8(s[0]),
 | 
				
			||||||
                'height': i8(s[1]),
 | 
					                'height': i8(s[1]),
 | 
				
			||||||
                'nb_color': i8(s[2]), # Number of colors in image (0 if >=8bpp)
 | 
					                'nb_color': i8(s[2]),  # No. of colors in image (0 if >=8bpp)
 | 
				
			||||||
                'reserved': i8(s[3]),
 | 
					                'reserved': i8(s[3]),
 | 
				
			||||||
                'planes': i16(s[4:]),
 | 
					                'planes': i16(s[4:]),
 | 
				
			||||||
                'bpp': i16(s[6:]),
 | 
					                'bpp': i16(s[6:]),
 | 
				
			||||||
| 
						 | 
					@ -78,10 +118,14 @@ class IcoFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # See Wikipedia notes about color depth.
 | 
					            # See Wikipedia notes about color depth.
 | 
				
			||||||
            # We need this just to differ images with equal sizes
 | 
					            # We need this just to differ images with equal sizes
 | 
				
			||||||
            icon_header['color_depth'] = (icon_header['bpp'] or (icon_header['nb_color'] != 0 and ceil(log(icon_header['nb_color'],2))) or 256)
 | 
					            icon_header['color_depth'] = (icon_header['bpp'] or
 | 
				
			||||||
 | 
					                                          (icon_header['nb_color'] != 0 and
 | 
				
			||||||
 | 
					                                           ceil(log(icon_header['nb_color'],
 | 
				
			||||||
 | 
					                                                    2))) or 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            icon_header['dim'] = (icon_header['width'], icon_header['height'])
 | 
					            icon_header['dim'] = (icon_header['width'], icon_header['height'])
 | 
				
			||||||
            icon_header['square'] = icon_header['width'] * icon_header['height']
 | 
					            icon_header['square'] = (icon_header['width'] *
 | 
				
			||||||
 | 
					                                     icon_header['height'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.entry.append(icon_header)
 | 
					            self.entry.append(icon_header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +146,7 @@ class IcoFile:
 | 
				
			||||||
        Get an image from the icon
 | 
					        Get an image from the icon
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        for (i, h) in enumerate(self.entry):
 | 
					        for (i, h) in enumerate(self.entry):
 | 
				
			||||||
            if size == h['dim'] and (bpp == False or bpp == h['color_depth']):
 | 
					            if size == h['dim'] and (bpp is False or bpp == h['color_depth']):
 | 
				
			||||||
                return self.frame(i)
 | 
					                return self.frame(i)
 | 
				
			||||||
        return self.frame(0)
 | 
					        return self.frame(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,7 +171,7 @@ class IcoFile:
 | 
				
			||||||
            # change tile dimension to only encompass XOR image
 | 
					            # change tile dimension to only encompass XOR image
 | 
				
			||||||
            im.size = (im.size[0], int(im.size[1] / 2))
 | 
					            im.size = (im.size[0], int(im.size[1] / 2))
 | 
				
			||||||
            d, e, o, a = im.tile[0]
 | 
					            d, e, o, a = im.tile[0]
 | 
				
			||||||
            im.tile[0] = d, (0,0) + im.size, o, a
 | 
					            im.tile[0] = d, (0, 0) + im.size, o, a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # figure out where AND mask image starts
 | 
					            # figure out where AND mask image starts
 | 
				
			||||||
            mode = a[0]
 | 
					            mode = a[0]
 | 
				
			||||||
| 
						 | 
					@ -139,8 +183,9 @@ class IcoFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if 32 == bpp:
 | 
					            if 32 == bpp:
 | 
				
			||||||
                # 32-bit color depth icon image allows semitransparent areas
 | 
					                # 32-bit color depth icon image allows semitransparent areas
 | 
				
			||||||
                # PIL's DIB format ignores transparency bits, recover them
 | 
					                # PIL's DIB format ignores transparency bits, recover them.
 | 
				
			||||||
                # The DIB is packed in BGRX byte order where X is the alpha channel
 | 
					                # The DIB is packed in BGRX byte order where X is the alpha
 | 
				
			||||||
 | 
					                # channel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Back up to start of bmp data
 | 
					                # Back up to start of bmp data
 | 
				
			||||||
                self.buf.seek(o)
 | 
					                self.buf.seek(o)
 | 
				
			||||||
| 
						 | 
					@ -162,9 +207,11 @@ class IcoFile:
 | 
				
			||||||
                    # bitmap row data is aligned to word boundaries
 | 
					                    # bitmap row data is aligned to word boundaries
 | 
				
			||||||
                    w += 32 - (im.size[0] % 32)
 | 
					                    w += 32 - (im.size[0] % 32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # the total mask data is padded row size * height / bits per char
 | 
					                # the total mask data is
 | 
				
			||||||
 | 
					                # padded row size * height / bits per char
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                and_mask_offset = o + int(im.size[0] * im.size[1] * (bpp / 8.0))
 | 
					                and_mask_offset = o + int(im.size[0] * im.size[1] *
 | 
				
			||||||
 | 
					                                          (bpp / 8.0))
 | 
				
			||||||
                total_bytes = int((w * im.size[1]) / 8)
 | 
					                total_bytes = int((w * im.size[1]) / 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                self.buf.seek(and_mask_offset)
 | 
					                self.buf.seek(and_mask_offset)
 | 
				
			||||||
| 
						 | 
					@ -187,6 +234,7 @@ class IcoFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return im
 | 
					        return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Windows Icon files.
 | 
					# Image plugin for Windows Icon files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -194,15 +242,16 @@ class IcoImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    PIL read-only image support for Microsoft Windows .ico files.
 | 
					    PIL read-only image support for Microsoft Windows .ico files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    By default the largest resolution image in the file will be loaded. This can
 | 
					    By default the largest resolution image in the file will be loaded. This
 | 
				
			||||||
    be changed by altering the 'size' attribute before calling 'load'.
 | 
					    can be changed by altering the 'size' attribute before calling 'load'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    The info dictionary has a key 'sizes' that is a list of the sizes available
 | 
					    The info dictionary has a key 'sizes' that is a list of the sizes available
 | 
				
			||||||
    in the icon file.
 | 
					    in the icon file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Handles classic, XP and Vista icon formats.
 | 
					    Handles classic, XP and Vista icon formats.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
 | 
					    This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
 | 
				
			||||||
 | 
					    <casadebender@gmail.com>.
 | 
				
			||||||
    https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
					    https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    format = "ICO"
 | 
					    format = "ICO"
 | 
				
			||||||
| 
						 | 
					@ -222,12 +271,13 @@ class IcoImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.mode = im.mode
 | 
					        self.mode = im.mode
 | 
				
			||||||
        self.size = im.size
 | 
					        self.size = im.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def load_seek(self):
 | 
					    def load_seek(self):
 | 
				
			||||||
        # Flage the ImageFile.Parser so that it just does all the decode at the end.
 | 
					        # Flag the ImageFile.Parser so that it
 | 
				
			||||||
 | 
					        # just does all the decode at the end.
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image.register_open("ICO", IcoImageFile, _accept)
 | 
					Image.register_open("ICO", IcoImageFile, _accept)
 | 
				
			||||||
 | 
					Image.register_save("ICO", _save)
 | 
				
			||||||
Image.register_extension("ICO", ".ico")
 | 
					Image.register_extension("ICO", ".ico")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ __version__ = "0.7"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from PIL import Image, ImageFile, ImagePalette
 | 
					from PIL import Image, ImageFile, ImagePalette
 | 
				
			||||||
from PIL._binary import i8, o8
 | 
					from PIL._binary import i8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,8 @@ SCALE = "Scale (x,y)"
 | 
				
			||||||
SIZE = "Image size (x*y)"
 | 
					SIZE = "Image size (x*y)"
 | 
				
			||||||
MODE = "Image type"
 | 
					MODE = "Image type"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
 | 
					TAGS = {COMMENT: 0, DATE: 0, EQUIPMENT: 0, FRAMES: 0, LUT: 0, NAME: 0,
 | 
				
			||||||
         SCALE:0, SIZE:0, MODE:0 }
 | 
					        SCALE: 0, SIZE: 0, MODE: 0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OPEN = {
 | 
					OPEN = {
 | 
				
			||||||
    # ifunc93/p3cfunc formats
 | 
					    # ifunc93/p3cfunc formats
 | 
				
			||||||
| 
						 | 
					@ -94,12 +94,14 @@ for i in range(2, 33):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
 | 
					split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def number(s):
 | 
					def number(s):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        return int(s)
 | 
					        return int(s)
 | 
				
			||||||
    except ValueError:
 | 
					    except ValueError:
 | 
				
			||||||
        return float(s)
 | 
					        return float(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for the IFUNC IM file format.
 | 
					# Image plugin for the IFUNC IM file format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,7 +115,7 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # Quick rejection: if there's not an LF among the first
 | 
					        # Quick rejection: if there's not an LF among the first
 | 
				
			||||||
        # 100 bytes, this is (probably) not a text header.
 | 
					        # 100 bytes, this is (probably) not a text header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not b"\n" in self.fp.read(100):
 | 
					        if b"\n" not in self.fp.read(100):
 | 
				
			||||||
            raise SyntaxError("not an IM file")
 | 
					            raise SyntaxError("not an IM file")
 | 
				
			||||||
        self.fp.seek(0)
 | 
					        self.fp.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,10 +157,10 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if m:
 | 
					            if m:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                k, v = m.group(1,2)
 | 
					                k, v = m.group(1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Don't know if this is the correct encoding, but a decent guess
 | 
					                # Don't know if this is the correct encoding,
 | 
				
			||||||
                # (I guess)
 | 
					                # but a decent guess (I guess)
 | 
				
			||||||
                k = k.decode('latin-1', 'replace')
 | 
					                k = k.decode('latin-1', 'replace')
 | 
				
			||||||
                v = v.decode('latin-1', 'replace')
 | 
					                v = v.decode('latin-1', 'replace')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,7 +188,8 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                raise SyntaxError("Syntax error in IM header: " + s.decode('ascii', 'replace'))
 | 
					                raise SyntaxError("Syntax error in IM header: " +
 | 
				
			||||||
 | 
					                                  s.decode('ascii', 'replace'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not n:
 | 
					        if not n:
 | 
				
			||||||
            raise SyntaxError("Not an IM file")
 | 
					            raise SyntaxError("Not an IM file")
 | 
				
			||||||
| 
						 | 
					@ -239,7 +242,7 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                # use bit decoder (if necessary)
 | 
					                # use bit decoder (if necessary)
 | 
				
			||||||
                bits = int(self.rawmode[2:])
 | 
					                bits = int(self.rawmode[2:])
 | 
				
			||||||
                if bits not in [8, 16, 32]:
 | 
					                if bits not in [8, 16, 32]:
 | 
				
			||||||
                    self.tile = [("bit", (0,0)+self.size, offs,
 | 
					                    self.tile = [("bit", (0, 0)+self.size, offs,
 | 
				
			||||||
                                 (bits, 8, 3, 0, -1))]
 | 
					                                 (bits, 8, 3, 0, -1))]
 | 
				
			||||||
                    return
 | 
					                    return
 | 
				
			||||||
            except ValueError:
 | 
					            except ValueError:
 | 
				
			||||||
| 
						 | 
					@ -249,12 +252,17 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            # Old LabEye/3PC files.  Would be very surprised if anyone
 | 
					            # Old LabEye/3PC files.  Would be very surprised if anyone
 | 
				
			||||||
            # ever stumbled upon such a file ;-)
 | 
					            # ever stumbled upon such a file ;-)
 | 
				
			||||||
            size = self.size[0] * self.size[1]
 | 
					            size = self.size[0] * self.size[1]
 | 
				
			||||||
            self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
 | 
					            self.tile = [("raw", (0, 0)+self.size, offs, ("G", 0, -1)),
 | 
				
			||||||
                         ("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
 | 
					                         ("raw", (0, 0)+self.size, offs+size, ("R", 0, -1)),
 | 
				
			||||||
                         ("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
 | 
					                         ("raw", (0, 0)+self.size, offs+2*size, ("B", 0, -1))]
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            # LabEye/IFUNC files
 | 
					            # LabEye/IFUNC files
 | 
				
			||||||
            self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
 | 
					            self.tile = [("raw", (0, 0)+self.size, offs,
 | 
				
			||||||
 | 
					                         (self.rawmode, 0, -1))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return self.info[FRAMES]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,7 +284,7 @@ class ImImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.fp = self.__fp
 | 
					        self.fp = self.__fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
 | 
					        self.tile = [("raw", (0, 0)+self.size, offs, (self.rawmode, 0, -1))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tell(self):
 | 
					    def tell(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,10 +313,11 @@ SAVE = {
 | 
				
			||||||
    "YCbCr": ("YCC", "YCbCr;L")
 | 
					    "YCbCr": ("YCC", "YCbCr;L")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename, check=0):
 | 
					def _save(im, fp, filename, check=0):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        type, rawmode = SAVE[im.mode]
 | 
					        image_type, rawmode = SAVE[im.mode]
 | 
				
			||||||
    except KeyError:
 | 
					    except KeyError:
 | 
				
			||||||
        raise ValueError("Cannot save %s images as IM" % im.mode)
 | 
					        raise ValueError("Cannot save %s images as IM" % im.mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,7 +329,7 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    if check:
 | 
					    if check:
 | 
				
			||||||
        return check
 | 
					        return check
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fp.write(("Image type: %s image\r\n" % type).encode('ascii'))
 | 
					    fp.write(("Image type: %s image\r\n" % image_type).encode('ascii'))
 | 
				
			||||||
    if filename:
 | 
					    if filename:
 | 
				
			||||||
        fp.write(("Name: %s\r\n" % filename).encode('ascii'))
 | 
					        fp.write(("Name: %s\r\n" % filename).encode('ascii'))
 | 
				
			||||||
    fp.write(("Image size (x*y): %d*%d\r\n" % im.size).encode('ascii'))
 | 
					    fp.write(("Image size (x*y): %d*%d\r\n" % im.size).encode('ascii'))
 | 
				
			||||||
| 
						 | 
					@ -330,7 +339,7 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    fp.write(b"\000" * (511-fp.tell()) + b"\032")
 | 
					    fp.write(b"\000" * (511-fp.tell()) + b"\032")
 | 
				
			||||||
    if im.mode == "P":
 | 
					    if im.mode == "P":
 | 
				
			||||||
        fp.write(im.im.getpalette("RGB", "RGB;L"))  # 768 bytes
 | 
					        fp.write(im.im.getpalette("RGB", "RGB;L"))  # 768 bytes
 | 
				
			||||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
 | 
					    ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, -1))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										228
									
								
								PIL/Image.py
									
									
									
									
									
								
							
							
						
						
									
										228
									
								
								PIL/Image.py
									
									
									
									
									
								
							| 
						 | 
					@ -34,7 +34,8 @@ import warnings
 | 
				
			||||||
class DecompressionBombWarning(RuntimeWarning):
 | 
					class DecompressionBombWarning(RuntimeWarning):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _imaging_not_installed:
 | 
					
 | 
				
			||||||
 | 
					class _imaging_not_installed(object):
 | 
				
			||||||
    # module placeholder
 | 
					    # module placeholder
 | 
				
			||||||
    def __getattr__(self, id):
 | 
					    def __getattr__(self, id):
 | 
				
			||||||
        raise ImportError("The _imaging C module is not installed")
 | 
					        raise ImportError("The _imaging C module is not installed")
 | 
				
			||||||
| 
						 | 
					@ -54,10 +55,11 @@ except ImportError:
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    # If the _imaging C module is not present, you can still use
 | 
					    # If the _imaging C module is not present, Pillow will not load.
 | 
				
			||||||
    # the "open" function to identify files, but you cannot load
 | 
					    # Note that other modules should not refer to _imaging directly;
 | 
				
			||||||
    # them.  Note that other modules should not refer to _imaging
 | 
					    # import Image and use the Image.core variable instead.
 | 
				
			||||||
    # directly; import Image and use the Image.core variable instead.
 | 
					    # Also note that Image.core is not a publicly documented interface,
 | 
				
			||||||
 | 
					    # and should be considered private and subject to change.
 | 
				
			||||||
    from PIL import _imaging as core
 | 
					    from PIL import _imaging as core
 | 
				
			||||||
    if PILLOW_VERSION != getattr(core, 'PILLOW_VERSION', None):
 | 
					    if PILLOW_VERSION != getattr(core, 'PILLOW_VERSION', None):
 | 
				
			||||||
        raise ImportError("The _imaging extension was built for another "
 | 
					        raise ImportError("The _imaging extension was built for another "
 | 
				
			||||||
| 
						 | 
					@ -90,6 +92,7 @@ except ImportError as v:
 | 
				
			||||||
            RuntimeWarning
 | 
					            RuntimeWarning
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
    # Fail here anyway. Don't let people run with a mostly broken Pillow.
 | 
					    # Fail here anyway. Don't let people run with a mostly broken Pillow.
 | 
				
			||||||
 | 
					    # see docs/porting-pil-to-pillow.rst
 | 
				
			||||||
    raise
 | 
					    raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
| 
						 | 
					@ -106,6 +109,8 @@ from PIL._util import deferred_error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# type stuff
 | 
					# type stuff
 | 
				
			||||||
import collections
 | 
					import collections
 | 
				
			||||||
| 
						 | 
					@ -149,6 +154,7 @@ FLIP_TOP_BOTTOM = 1
 | 
				
			||||||
ROTATE_90 = 2
 | 
					ROTATE_90 = 2
 | 
				
			||||||
ROTATE_180 = 3
 | 
					ROTATE_180 = 3
 | 
				
			||||||
ROTATE_270 = 4
 | 
					ROTATE_270 = 4
 | 
				
			||||||
 | 
					TRANSPOSE = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# transforms
 | 
					# transforms
 | 
				
			||||||
AFFINE = 0
 | 
					AFFINE = 0
 | 
				
			||||||
| 
						 | 
					@ -158,11 +164,10 @@ QUAD = 3
 | 
				
			||||||
MESH = 4
 | 
					MESH = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# resampling filters
 | 
					# resampling filters
 | 
				
			||||||
NONE = 0
 | 
					NEAREST = NONE = 0
 | 
				
			||||||
NEAREST = 0
 | 
					LANCZOS = ANTIALIAS = 1
 | 
				
			||||||
ANTIALIAS = 1  # 3-lobed lanczos
 | 
					BILINEAR = LINEAR = 2
 | 
				
			||||||
LINEAR = BILINEAR = 2
 | 
					BICUBIC = CUBIC = 3
 | 
				
			||||||
CUBIC = BICUBIC = 3
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# dithers
 | 
					# dithers
 | 
				
			||||||
NONE = 0
 | 
					NONE = 0
 | 
				
			||||||
| 
						 | 
					@ -382,7 +387,7 @@ def init():
 | 
				
			||||||
    for plugin in _plugins:
 | 
					    for plugin in _plugins:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            if DEBUG:
 | 
					            if DEBUG:
 | 
				
			||||||
                print ("Importing %s" % plugin)
 | 
					                print("Importing %s" % plugin)
 | 
				
			||||||
            __import__("PIL.%s" % plugin, globals(), locals(), [])
 | 
					            __import__("PIL.%s" % plugin, globals(), locals(), [])
 | 
				
			||||||
        except ImportError:
 | 
					        except ImportError:
 | 
				
			||||||
            if DEBUG:
 | 
					            if DEBUG:
 | 
				
			||||||
| 
						 | 
					@ -438,7 +443,7 @@ def coerce_e(value):
 | 
				
			||||||
    return value if isinstance(value, _E) else _E(value)
 | 
					    return value if isinstance(value, _E) else _E(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _E:
 | 
					class _E(object):
 | 
				
			||||||
    def __init__(self, data):
 | 
					    def __init__(self, data):
 | 
				
			||||||
        self.data = data
 | 
					        self.data = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,7 +478,7 @@ def _getscaleoffset(expr):
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Implementation wrapper
 | 
					# Implementation wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Image:
 | 
					class Image(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This class represents an image object.  To create
 | 
					    This class represents an image object.  To create
 | 
				
			||||||
    :py:class:`~PIL.Image.Image` objects, use the appropriate factory
 | 
					    :py:class:`~PIL.Image.Image` objects, use the appropriate factory
 | 
				
			||||||
| 
						 | 
					@ -530,7 +535,7 @@ class Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Closes the file pointer, if possible.
 | 
					        Closes the file pointer, if possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        This operation will destroy the image core and release it's memory.
 | 
					        This operation will destroy the image core and release its memory.
 | 
				
			||||||
        The image data will be unusable afterward.
 | 
					        The image data will be unusable afterward.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        This function is only required to close images that have not
 | 
					        This function is only required to close images that have not
 | 
				
			||||||
| 
						 | 
					@ -541,7 +546,7 @@ class Image:
 | 
				
			||||||
            self.fp.close()
 | 
					            self.fp.close()
 | 
				
			||||||
        except Exception as msg:
 | 
					        except Exception as msg:
 | 
				
			||||||
            if DEBUG:
 | 
					            if DEBUG:
 | 
				
			||||||
                print ("Error closing: %s" % msg)
 | 
					                print("Error closing: %s" % msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Instead of simply setting to None, we're setting up a
 | 
					        # Instead of simply setting to None, we're setting up a
 | 
				
			||||||
        # deferred error that will better explain that the core image
 | 
					        # deferred error that will better explain that the core image
 | 
				
			||||||
| 
						 | 
					@ -595,6 +600,16 @@ class Image:
 | 
				
			||||||
            id(self)
 | 
					            id(self)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _repr_png_(self):
 | 
				
			||||||
 | 
					        """ iPython display hook support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :returns: png version of the image as bytes
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        from io import BytesIO
 | 
				
			||||||
 | 
					        b = BytesIO()
 | 
				
			||||||
 | 
					        self.save(b, 'PNG')
 | 
				
			||||||
 | 
					        return b.getvalue()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __getattr__(self, name):
 | 
					    def __getattr__(self, name):
 | 
				
			||||||
        if name == "__array_interface__":
 | 
					        if name == "__array_interface__":
 | 
				
			||||||
            # numpy array interface support
 | 
					            # numpy array interface support
 | 
				
			||||||
| 
						 | 
					@ -622,7 +637,7 @@ class Image:
 | 
				
			||||||
        self.mode = mode
 | 
					        self.mode = mode
 | 
				
			||||||
        self.size = size
 | 
					        self.size = size
 | 
				
			||||||
        self.im = core.new(mode, size)
 | 
					        self.im = core.new(mode, size)
 | 
				
			||||||
        if mode in ("L", "P"):
 | 
					        if mode in ("L", "P") and palette:
 | 
				
			||||||
            self.putpalette(palette)
 | 
					            self.putpalette(palette)
 | 
				
			||||||
        self.frombytes(data)
 | 
					        self.frombytes(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,6 +679,10 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Declare tostring as alias to tobytes
 | 
					    # Declare tostring as alias to tobytes
 | 
				
			||||||
    def tostring(self, *args, **kw):
 | 
					    def tostring(self, *args, **kw):
 | 
				
			||||||
 | 
					        """Deprecated alias to tobytes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. deprecated:: 2.0
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        warnings.warn(
 | 
					        warnings.warn(
 | 
				
			||||||
            'tostring() is deprecated. Please call tobytes() instead.',
 | 
					            'tostring() is deprecated. Please call tobytes() instead.',
 | 
				
			||||||
            DeprecationWarning,
 | 
					            DeprecationWarning,
 | 
				
			||||||
| 
						 | 
					@ -737,6 +756,7 @@ class Image:
 | 
				
			||||||
        associated with the image.
 | 
					        associated with the image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :returns: An image access object.
 | 
					        :returns: An image access object.
 | 
				
			||||||
 | 
					        :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if self.im and self.palette and self.palette.dirty:
 | 
					        if self.im and self.palette and self.palette.dirty:
 | 
				
			||||||
            # realize palette
 | 
					            # realize palette
 | 
				
			||||||
| 
						 | 
					@ -796,7 +816,7 @@ class Image:
 | 
				
			||||||
        use other thresholds, use the :py:meth:`~PIL.Image.Image.point`
 | 
					        use other thresholds, use the :py:meth:`~PIL.Image.Image.point`
 | 
				
			||||||
        method.
 | 
					        method.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param mode: The requested mode.
 | 
					        :param mode: The requested mode. See: :ref:`concept-modes`.
 | 
				
			||||||
        :param matrix: An optional conversion matrix.  If given, this
 | 
					        :param matrix: An optional conversion matrix.  If given, this
 | 
				
			||||||
           should be 4- or 16-tuple containing floating point values.
 | 
					           should be 4- or 16-tuple containing floating point values.
 | 
				
			||||||
        :param dither: Dithering method, used when converting from
 | 
					        :param dither: Dithering method, used when converting from
 | 
				
			||||||
| 
						 | 
					@ -847,8 +867,9 @@ class Image:
 | 
				
			||||||
                t = self.info['transparency']
 | 
					                t = self.info['transparency']
 | 
				
			||||||
                if isinstance(t, bytes):
 | 
					                if isinstance(t, bytes):
 | 
				
			||||||
                    # Dragons. This can't be represented by a single color
 | 
					                    # Dragons. This can't be represented by a single color
 | 
				
			||||||
                    warnings.warn('Palette images with Transparency expressed ' +
 | 
					                    warnings.warn('Palette images with Transparency  ' +
 | 
				
			||||||
                                  ' in bytes should be converted to RGBA images')
 | 
					                                  ' expressed in bytes should be converted ' +
 | 
				
			||||||
 | 
					                                  'to RGBA images')
 | 
				
			||||||
                    delete_trns = True
 | 
					                    delete_trns = True
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    # get the new transparency color.
 | 
					                    # get the new transparency color.
 | 
				
			||||||
| 
						 | 
					@ -864,11 +885,20 @@ class Image:
 | 
				
			||||||
                        # can't just retrieve the palette number, got to do it
 | 
					                        # can't just retrieve the palette number, got to do it
 | 
				
			||||||
                        # after quantization.
 | 
					                        # after quantization.
 | 
				
			||||||
                        trns_im = trns_im.convert('RGB')
 | 
					                        trns_im = trns_im.convert('RGB')
 | 
				
			||||||
                    trns = trns_im.getpixel((0,0))
 | 
					                    trns = trns_im.getpixel((0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elif self.mode == 'P' and mode == 'RGBA':
 | 
					            elif self.mode == 'P' and mode == 'RGBA':
 | 
				
			||||||
 | 
					                t = self.info['transparency']
 | 
				
			||||||
                delete_trns = True
 | 
					                delete_trns = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if isinstance(t, bytes):
 | 
				
			||||||
 | 
					                    self.im.putpalettealphas(t)
 | 
				
			||||||
 | 
					                elif isinstance(t, int):
 | 
				
			||||||
 | 
					                    self.im.putpalettealpha(t, 0)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    raise ValueError("Transparency for P mode should" +
 | 
				
			||||||
 | 
					                                     " be bytes or int")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if mode == "P" and palette == ADAPTIVE:
 | 
					        if mode == "P" and palette == ADAPTIVE:
 | 
				
			||||||
            im = self.im.quantize(colors)
 | 
					            im = self.im.quantize(colors)
 | 
				
			||||||
            new = self._new(im)
 | 
					            new = self._new(im)
 | 
				
			||||||
| 
						 | 
					@ -920,14 +950,19 @@ class Image:
 | 
				
			||||||
        return new_im
 | 
					        return new_im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def quantize(self, colors=256, method=None, kmeans=0, palette=None):
 | 
					    def quantize(self, colors=256, method=None, kmeans=0, palette=None):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Convert the image to 'P' mode with the specified number
 | 
				
			||||||
 | 
					        of colors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # methods:
 | 
					        :param colors: The desired number of colors, <= 256
 | 
				
			||||||
        #    0 = median cut
 | 
					        :param method: 0 = median cut
 | 
				
			||||||
        #    1 = maximum coverage
 | 
					                       1 = maximum coverage
 | 
				
			||||||
        #    2 = fast octree
 | 
					                       2 = fast octree
 | 
				
			||||||
 | 
					        :param kmeans: Integer
 | 
				
			||||||
 | 
					        :param palette: Quantize to the :py:class:`PIL.ImagingPalette` palette.
 | 
				
			||||||
 | 
					        :returns: A new image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # NOTE: this functionality will be moved to the extended
 | 
					        """
 | 
				
			||||||
        # quantizer interface in a later version of PIL.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.load()
 | 
					        self.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -994,8 +1029,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
 | 
				
			||||||
| 
						 | 
					@ -1255,11 +1288,11 @@ class Image:
 | 
				
			||||||
        images (in the latter case, the alpha band is used as mask).
 | 
					        images (in the latter case, the alpha band is used as mask).
 | 
				
			||||||
        Where the mask is 255, the given image is copied as is.  Where
 | 
					        Where the mask is 255, the given image is copied as is.  Where
 | 
				
			||||||
        the mask is 0, the current value is preserved.  Intermediate
 | 
					        the mask is 0, the current value is preserved.  Intermediate
 | 
				
			||||||
        values can be used for transparency effects.
 | 
					        values will mix the two images together, including their alpha
 | 
				
			||||||
 | 
					        channels if they have them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Note that if you paste an "RGBA" image, the alpha band is
 | 
					        See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
 | 
				
			||||||
        ignored.  You can work around this by using the same image as
 | 
					        combine images with respect to their alpha channels.
 | 
				
			||||||
        both source image and mask.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param im: Source image or pixel value (integer or tuple).
 | 
					        :param im: Source image or pixel value (integer or tuple).
 | 
				
			||||||
        :param box: An optional 4-tuple giving the region to paste into.
 | 
					        :param box: An optional 4-tuple giving the region to paste into.
 | 
				
			||||||
| 
						 | 
					@ -1500,36 +1533,30 @@ class Image:
 | 
				
			||||||
           (width, height).
 | 
					           (width, height).
 | 
				
			||||||
        :param resample: An optional resampling filter.  This can be
 | 
					        :param resample: An optional resampling filter.  This can be
 | 
				
			||||||
           one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),
 | 
					           one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),
 | 
				
			||||||
           :py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2
 | 
					           :py:attr:`PIL.Image.BILINEAR` (linear interpolation),
 | 
				
			||||||
           environment), :py:attr:`PIL.Image.BICUBIC` (cubic spline
 | 
					           :py:attr:`PIL.Image.BICUBIC` (cubic spline interpolation), or
 | 
				
			||||||
           interpolation in a 4x4 environment), or
 | 
					           :py:attr:`PIL.Image.LANCZOS` (a high-quality downsampling filter).
 | 
				
			||||||
           :py:attr:`PIL.Image.ANTIALIAS` (a high-quality downsampling filter).
 | 
					 | 
				
			||||||
           If omitted, or if the image has mode "1" or "P", it is
 | 
					           If omitted, or if the image has mode "1" or "P", it is
 | 
				
			||||||
           set :py:attr:`PIL.Image.NEAREST`.
 | 
					           set :py:attr:`PIL.Image.NEAREST`.
 | 
				
			||||||
        :returns: An :py:class:`~PIL.Image.Image` object.
 | 
					        :returns: An :py:class:`~PIL.Image.Image` object.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if resample not in (NEAREST, BILINEAR, BICUBIC, ANTIALIAS):
 | 
					        if resample not in (NEAREST, BILINEAR, BICUBIC, LANCZOS):
 | 
				
			||||||
            raise ValueError("unknown resampling filter")
 | 
					            raise ValueError("unknown resampling filter")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.load()
 | 
					        self.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        size = tuple(size)
 | 
				
			||||||
 | 
					        if self.size == size:
 | 
				
			||||||
 | 
					            return self._new(self.im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.mode in ("1", "P"):
 | 
					        if self.mode in ("1", "P"):
 | 
				
			||||||
            resample = NEAREST
 | 
					            resample = NEAREST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.mode == 'RGBA':
 | 
					        if self.mode == 'RGBA':
 | 
				
			||||||
            return self.convert('RGBa').resize(size, resample).convert('RGBA')
 | 
					            return self.convert('RGBa').resize(size, resample).convert('RGBA')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if resample == ANTIALIAS:
 | 
					        return self._new(self.im.resize(size, resample))
 | 
				
			||||||
            # requires stretch support (imToolkit & PIL 1.1.3)
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                im = self.im.stretch(size, resample)
 | 
					 | 
				
			||||||
            except AttributeError:
 | 
					 | 
				
			||||||
                raise ValueError("unsupported resampling filter")
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            im = self.im.resize(size, resample)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return self._new(im)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def rotate(self, angle, resample=NEAREST, expand=0):
 | 
					    def rotate(self, angle, resample=NEAREST, expand=0):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -1600,15 +1627,16 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Keyword options can be used to provide additional instructions
 | 
					        Keyword options can be used to provide additional instructions
 | 
				
			||||||
        to the writer. If a writer doesn't recognise an option, it is
 | 
					        to the writer. If a writer doesn't recognise an option, it is
 | 
				
			||||||
        silently ignored. The available options are described later in
 | 
					        silently ignored. The available options are described in the
 | 
				
			||||||
        this handbook.
 | 
					        :doc:`image format documentation
 | 
				
			||||||
 | 
					        <../handbook/image-file-formats>` for each writer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        You can use a file object instead of a filename. In this case,
 | 
					        You can use a file object instead of a filename. In this case,
 | 
				
			||||||
        you must always specify the format. The file object must
 | 
					        you must always specify the format. The file object must
 | 
				
			||||||
        implement the **seek**, **tell**, and **write**
 | 
					        implement the ``seek``, ``tell``, and ``write``
 | 
				
			||||||
        methods, and be opened in binary mode.
 | 
					        methods, and be opened in binary mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param file: File name or file object.
 | 
					        :param fp: File name or file object.
 | 
				
			||||||
        :param format: Optional format override.  If omitted, the
 | 
					        :param format: Optional format override.  If omitted, the
 | 
				
			||||||
           format to use is determined from the filename extension.
 | 
					           format to use is determined from the filename extension.
 | 
				
			||||||
           If a file object was used instead of a filename, this
 | 
					           If a file object was used instead of a filename, this
 | 
				
			||||||
| 
						 | 
					@ -1735,7 +1763,7 @@ class Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def thumbnail(self, size, resample=ANTIALIAS):
 | 
					    def thumbnail(self, size, resample=BICUBIC):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Make this image into a thumbnail.  This method modifies the
 | 
					        Make this image into a thumbnail.  This method modifies the
 | 
				
			||||||
        image to contain a thumbnail version of itself, no larger than
 | 
					        image to contain a thumbnail version of itself, no larger than
 | 
				
			||||||
| 
						 | 
					@ -1744,12 +1772,7 @@ class Image:
 | 
				
			||||||
        :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
 | 
					        :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
 | 
				
			||||||
        (where applicable), and finally resizes the image.
 | 
					        (where applicable), and finally resizes the image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Note that the bilinear and bicubic filters in the current
 | 
					        Note that this function modifies the :py:class:`~PIL.Image.Image`
 | 
				
			||||||
        version of PIL are not well-suited for thumbnail generation.
 | 
					 | 
				
			||||||
        You should use :py:attr:`PIL.Image.ANTIALIAS` unless speed is much more
 | 
					 | 
				
			||||||
        important than quality.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Also note that this function modifies the :py:class:`~PIL.Image.Image`
 | 
					 | 
				
			||||||
        object in place.  If you need to use the full resolution image as well,
 | 
					        object in place.  If you need to use the full resolution image as well,
 | 
				
			||||||
        apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
 | 
					        apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
 | 
				
			||||||
        image.
 | 
					        image.
 | 
				
			||||||
| 
						 | 
					@ -1757,10 +1780,9 @@ class Image:
 | 
				
			||||||
        :param size: Requested size.
 | 
					        :param size: Requested size.
 | 
				
			||||||
        :param resample: Optional resampling filter.  This can be one
 | 
					        :param resample: Optional resampling filter.  This can be one
 | 
				
			||||||
           of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`,
 | 
					           of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`,
 | 
				
			||||||
           :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS`
 | 
					           :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.LANCZOS`.
 | 
				
			||||||
           (best quality).  If omitted, it defaults to
 | 
					           If omitted, it defaults to :py:attr:`PIL.Image.BICUBIC`.
 | 
				
			||||||
           :py:attr:`PIL.Image.ANTIALIAS`. (was :py:attr:`PIL.Image.NEAREST`
 | 
					           (was :py:attr:`PIL.Image.NEAREST` prior to version 2.5.0)
 | 
				
			||||||
           prior to version 2.5.0)
 | 
					 | 
				
			||||||
        :returns: None
 | 
					        :returns: None
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1779,14 +1801,7 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.draft(None, size)
 | 
					        self.draft(None, size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.load()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
        im = self.resize(size, resample)
 | 
					        im = self.resize(size, resample)
 | 
				
			||||||
        except ValueError:
 | 
					 | 
				
			||||||
            if resample != ANTIALIAS:
 | 
					 | 
				
			||||||
                raise
 | 
					 | 
				
			||||||
            im = self.resize(size, NEAREST)  # fallback
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.im = im.im
 | 
					        self.im = im.im
 | 
				
			||||||
        self.mode = im.mode
 | 
					        self.mode = im.mode
 | 
				
			||||||
| 
						 | 
					@ -1795,7 +1810,7 @@ class Image:
 | 
				
			||||||
        self.readonly = 0
 | 
					        self.readonly = 0
 | 
				
			||||||
        self.pyaccess = None
 | 
					        self.pyaccess = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # FIXME: the different tranform methods need further explanation
 | 
					    # FIXME: the different transform methods need further explanation
 | 
				
			||||||
    # instead of bloating the method docs, add a separate chapter.
 | 
					    # instead of bloating the method docs, add a separate chapter.
 | 
				
			||||||
    def transform(self, size, method, data=None, resample=NEAREST, fill=1):
 | 
					    def transform(self, size, method, data=None, resample=NEAREST, fill=1):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -1902,12 +1917,22 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param method: One of :py:attr:`PIL.Image.FLIP_LEFT_RIGHT`,
 | 
					        :param method: One of :py:attr:`PIL.Image.FLIP_LEFT_RIGHT`,
 | 
				
			||||||
          :py:attr:`PIL.Image.FLIP_TOP_BOTTOM`, :py:attr:`PIL.Image.ROTATE_90`,
 | 
					          :py:attr:`PIL.Image.FLIP_TOP_BOTTOM`, :py:attr:`PIL.Image.ROTATE_90`,
 | 
				
			||||||
          :py:attr:`PIL.Image.ROTATE_180`, or :py:attr:`PIL.Image.ROTATE_270`.
 | 
					          :py:attr:`PIL.Image.ROTATE_180`, :py:attr:`PIL.Image.ROTATE_270` or
 | 
				
			||||||
 | 
					          :py:attr:`PIL.Image.TRANSPOSE`.
 | 
				
			||||||
        :returns: Returns a flipped or rotated copy of this image.
 | 
					        :returns: Returns a flipped or rotated copy of this image.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.load()
 | 
					        self.load()
 | 
				
			||||||
        im = self.im.transpose(method)
 | 
					        return self._new(self.im.transpose(method))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def effect_spread(self, distance):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Randomly spread pixels in an image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param distance: Distance to spread pixels.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.load()
 | 
				
			||||||
 | 
					        im = self.im.effect_spread(distance)
 | 
				
			||||||
        return self._new(im)
 | 
					        return self._new(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1950,12 +1975,12 @@ class _ImageCrop(Image):
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Abstract handlers.
 | 
					# Abstract handlers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImagePointHandler:
 | 
					class ImagePointHandler(object):
 | 
				
			||||||
    # used as a mixin by point transforms (for use with im.point)
 | 
					    # used as a mixin by point transforms (for use with im.point)
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImageTransformHandler:
 | 
					class ImageTransformHandler(object):
 | 
				
			||||||
    # used as a mixin by geometry transforms (for use with im.transform)
 | 
					    # used as a mixin by geometry transforms (for use with im.transform)
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1976,7 +2001,8 @@ def new(mode, size, color=0):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Creates a new image with the given mode and size.
 | 
					    Creates a new image with the given mode and size.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param mode: The mode to use for the new image.
 | 
					    :param mode: The mode to use for the new image. See:
 | 
				
			||||||
 | 
					       :ref:`concept-modes`.
 | 
				
			||||||
    :param size: A 2-tuple, containing (width, height) in pixels.
 | 
					    :param size: A 2-tuple, containing (width, height) in pixels.
 | 
				
			||||||
    :param color: What color to use for the image.  Default is black.
 | 
					    :param color: What color to use for the image.  Default is black.
 | 
				
			||||||
       If given, this should be a single integer or floating point value
 | 
					       If given, this should be a single integer or floating point value
 | 
				
			||||||
| 
						 | 
					@ -2009,14 +2035,14 @@ def frombytes(mode, size, data, decoder_name="raw", *args):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    You can also use any pixel decoder supported by PIL.  For more
 | 
					    You can also use any pixel decoder supported by PIL.  For more
 | 
				
			||||||
    information on available decoders, see the section
 | 
					    information on available decoders, see the section
 | 
				
			||||||
    **Writing Your Own File Decoder**.
 | 
					    :ref:`Writing Your Own File Decoder <file-decoders>`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Note that this function decodes pixel data only, not entire images.
 | 
					    Note that this function decodes pixel data only, not entire images.
 | 
				
			||||||
    If you have an entire image in a string, wrap it in a
 | 
					    If you have an entire image in a string, wrap it in a
 | 
				
			||||||
    :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
 | 
					    :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
 | 
				
			||||||
    it.
 | 
					    it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param mode: The image mode.
 | 
					    :param mode: The image mode. See: :ref:`concept-modes`.
 | 
				
			||||||
    :param size: The image size.
 | 
					    :param size: The image size.
 | 
				
			||||||
    :param data: A byte buffer containing raw data for the given mode.
 | 
					    :param data: A byte buffer containing raw data for the given mode.
 | 
				
			||||||
    :param decoder_name: What decoder to use.
 | 
					    :param decoder_name: What decoder to use.
 | 
				
			||||||
| 
						 | 
					@ -2068,7 +2094,7 @@ def frombuffer(mode, size, data, decoder_name="raw", *args):
 | 
				
			||||||
    issues a warning if you do this; to disable the warning, you should provide
 | 
					    issues a warning if you do this; to disable the warning, you should provide
 | 
				
			||||||
    the full set of parameters.  See below for details.
 | 
					    the full set of parameters.  See below for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param mode: The image mode.
 | 
					    :param mode: The image mode. See: :ref:`concept-modes`.
 | 
				
			||||||
    :param size: The image size.
 | 
					    :param size: The image size.
 | 
				
			||||||
    :param data: A bytes or other buffer object containing raw
 | 
					    :param data: A bytes or other buffer object containing raw
 | 
				
			||||||
        data for the given mode.
 | 
					        data for the given mode.
 | 
				
			||||||
| 
						 | 
					@ -2119,7 +2145,8 @@ def fromarray(obj, mode=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param obj: Object with array interface
 | 
					    :param obj: Object with array interface
 | 
				
			||||||
    :param mode: Mode to use (will be determined from type if None)
 | 
					    :param mode: Mode to use (will be determined from type if None)
 | 
				
			||||||
    :returns: An image memory.
 | 
					      See: :ref:`concept-modes`.
 | 
				
			||||||
 | 
					    :returns: An image object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .. versionadded:: 1.1.6
 | 
					    .. versionadded:: 1.1.6
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -2222,6 +2249,11 @@ def open(fp, mode="r"):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        filename = ""
 | 
					        filename = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        fp.seek(0)
 | 
				
			||||||
 | 
					    except (AttributeError, io.UnsupportedOperation):
 | 
				
			||||||
 | 
					        fp = io.BytesIO(fp.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prefix = fp.read(16)
 | 
					    prefix = fp.read(16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    preinit()
 | 
					    preinit()
 | 
				
			||||||
| 
						 | 
					@ -2234,7 +2266,7 @@ def open(fp, mode="r"):
 | 
				
			||||||
                im = factory(fp, filename)
 | 
					                im = factory(fp, filename)
 | 
				
			||||||
                _decompression_bomb_check(im.size)
 | 
					                _decompression_bomb_check(im.size)
 | 
				
			||||||
                return im
 | 
					                return im
 | 
				
			||||||
        except (SyntaxError, IndexError, TypeError):
 | 
					        except (SyntaxError, IndexError, TypeError, struct.error):
 | 
				
			||||||
            # import traceback
 | 
					            # import traceback
 | 
				
			||||||
            # traceback.print_exc()
 | 
					            # traceback.print_exc()
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					@ -2249,7 +2281,7 @@ def open(fp, mode="r"):
 | 
				
			||||||
                    im = factory(fp, filename)
 | 
					                    im = factory(fp, filename)
 | 
				
			||||||
                    _decompression_bomb_check(im.size)
 | 
					                    _decompression_bomb_check(im.size)
 | 
				
			||||||
                    return im
 | 
					                    return im
 | 
				
			||||||
            except (SyntaxError, IndexError, TypeError):
 | 
					            except (SyntaxError, IndexError, TypeError, struct.error):
 | 
				
			||||||
                # import traceback
 | 
					                # import traceback
 | 
				
			||||||
                # traceback.print_exc()
 | 
					                # traceback.print_exc()
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
| 
						 | 
					@ -2306,7 +2338,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.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -2336,7 +2368,8 @@ def merge(mode, bands):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Merge a set of single band images into a new multiband image.
 | 
					    Merge a set of single band images into a new multiband image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param mode: The mode to use for the output image.
 | 
					    :param mode: The mode to use for the output image. See:
 | 
				
			||||||
 | 
					        :ref:`concept-modes`.
 | 
				
			||||||
    :param bands: A sequence containing one single-band image for
 | 
					    :param bands: A sequence containing one single-band image for
 | 
				
			||||||
        each band in the output image.  All bands must have the
 | 
					        each band in the output image.  All bands must have the
 | 
				
			||||||
        same size.
 | 
					        same size.
 | 
				
			||||||
| 
						 | 
					@ -2419,3 +2452,32 @@ def _show(image, **options):
 | 
				
			||||||
def _showxv(image, title=None, **options):
 | 
					def _showxv(image, title=None, **options):
 | 
				
			||||||
    from PIL import ImageShow
 | 
					    from PIL import ImageShow
 | 
				
			||||||
    ImageShow.show(image, title, **options)
 | 
					    ImageShow.show(image, title, **options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Effects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def effect_mandelbrot(size, extent, quality):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Generate a Mandelbrot set covering the given extent.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param size: The requested size in pixels, as a 2-tuple:
 | 
				
			||||||
 | 
					       (width, height).
 | 
				
			||||||
 | 
					    :param extent: The extent to cover, as a 4-tuple:
 | 
				
			||||||
 | 
					       (x0, y0, x1, y2).
 | 
				
			||||||
 | 
					    :param quality: Quality.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return Image()._new(core.effect_mandelbrot(size, extent, quality))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def effect_noise(size, sigma):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Generate Gaussian noise centered around 128.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param size: The requested size in pixels, as a 2-tuple:
 | 
				
			||||||
 | 
					       (width, height).
 | 
				
			||||||
 | 
					    :param sigma: Standard deviation of noise.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return Image()._new(core.effect_noise(size, sigma))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,19 @@
 | 
				
			||||||
## The Python Imaging Library.
 | 
					# The Python Imaging Library.
 | 
				
			||||||
## $Id$
 | 
					# $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Optional color managment support, based on Kevin Cazabon's PyCMS
 | 
					# Optional color managment support, based on Kevin Cazabon's PyCMS
 | 
				
			||||||
## library.
 | 
					# library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## History:
 | 
					# History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 2009-03-08 fl   Added to PIL.
 | 
					# 2009-03-08 fl   Added to PIL.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Copyright (C) 2002-2003 Kevin Cazabon
 | 
					# Copyright (C) 2002-2003 Kevin Cazabon
 | 
				
			||||||
## Copyright (c) 2009 by Fredrik Lundh
 | 
					# Copyright (c) 2009 by Fredrik Lundh
 | 
				
			||||||
## Copyright (c) 2013 by Eric Soroos
 | 
					# Copyright (c) 2013 by Eric Soroos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## See the README file for information on usage and redistribution.  See
 | 
					# See the README file for information on usage and redistribution.  See
 | 
				
			||||||
## below for the original description.
 | 
					# below for the original description.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ pyCMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        0.0.2 alpha     Jan 6, 2002
 | 
					        0.0.2 alpha     Jan 6, 2002
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        Added try/except statements arount type() checks of
 | 
					                        Added try/except statements around type() checks of
 | 
				
			||||||
                        potential CObjects... Python won't let you use type()
 | 
					                        potential CObjects... Python won't let you use type()
 | 
				
			||||||
                        on them, and raises a TypeError (stupid, if you ask
 | 
					                        on them, and raises a TypeError (stupid, if you ask
 | 
				
			||||||
                        me!)
 | 
					                        me!)
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -123,8 +123,8 @@ FLAGS = {
 | 
				
			||||||
    "NOTCACHE": 64,  # Inhibit 1-pixel cache
 | 
					    "NOTCACHE": 64,  # Inhibit 1-pixel cache
 | 
				
			||||||
    "NOTPRECALC": 256,
 | 
					    "NOTPRECALC": 256,
 | 
				
			||||||
    "NULLTRANSFORM": 512,  # Don't transform anyway
 | 
					    "NULLTRANSFORM": 512,  # Don't transform anyway
 | 
				
			||||||
    "HIGHRESPRECALC": 1024,  # Use more memory to give better accurancy
 | 
					    "HIGHRESPRECALC": 1024,  # Use more memory to give better accuracy
 | 
				
			||||||
    "LOWRESPRECALC": 2048,  # Use less memory to minimize resouces
 | 
					    "LOWRESPRECALC": 2048,  # Use less memory to minimize resources
 | 
				
			||||||
    "WHITEBLACKCOMPENSATION": 8192,
 | 
					    "WHITEBLACKCOMPENSATION": 8192,
 | 
				
			||||||
    "BLACKPOINTCOMPENSATION": 8192,
 | 
					    "BLACKPOINTCOMPENSATION": 8192,
 | 
				
			||||||
    "GAMUTCHECK": 4096,  # Out of Gamut alarm
 | 
					    "GAMUTCHECK": 4096,  # Out of Gamut alarm
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ for flag in FLAGS.values():
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Profile.
 | 
					# Profile.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImageCmsProfile:
 | 
					class ImageCmsProfile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, profile):
 | 
					    def __init__(self, profile):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,7 @@ class ImageCmsProfile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return core.profile_tobytes(self.profile)
 | 
					        return core.profile_tobytes(self.profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImageCmsTransform(Image.ImagePointHandler):
 | 
					class ImageCmsTransform(Image.ImagePointHandler):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Transform.  This can be used with the procedural API, or with the
 | 
					    # Transform.  This can be used with the procedural API, or with the
 | 
				
			||||||
| 
						 | 
					@ -191,7 +192,6 @@ class ImageCmsTransform(Image.ImagePointHandler):
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # Will return the output profile in the output.info['icc_profile'].
 | 
					    # Will return the output profile in the output.info['icc_profile'].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, input, output, input_mode, output_mode,
 | 
					    def __init__(self, input, output, input_mode, output_mode,
 | 
				
			||||||
                 intent=INTENT_PERCEPTUAL, proof=None,
 | 
					                 intent=INTENT_PERCEPTUAL, proof=None,
 | 
				
			||||||
                 proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
 | 
					                 proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
 | 
				
			||||||
| 
						 | 
					@ -573,7 +573,7 @@ def applyTransform(im, transform, inPlace=0):
 | 
				
			||||||
    This function applies a pre-calculated transform (from
 | 
					    This function applies a pre-calculated transform (from
 | 
				
			||||||
    ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles())
 | 
					    ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles())
 | 
				
			||||||
    to an image.  The transform can be used for multiple images, saving
 | 
					    to an image.  The transform can be used for multiple images, saving
 | 
				
			||||||
    considerable calcuation time if doing the same conversion multiple times.
 | 
					    considerable calculation time if doing the same conversion multiple times.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    If you want to modify im in-place instead of receiving a new image as
 | 
					    If you want to modify im in-place instead of receiving a new image as
 | 
				
			||||||
    the return value, set inPlace to TRUE.  This can only be done if
 | 
					    the return value, set inPlace to TRUE.  This can only be done if
 | 
				
			||||||
| 
						 | 
					@ -858,7 +858,7 @@ def getDefaultIntent(profile):
 | 
				
			||||||
    If an error occurs while trying to obtain the default intent, a
 | 
					    If an error occurs while trying to obtain the default intent, a
 | 
				
			||||||
    PyCMSError is raised.
 | 
					    PyCMSError is raised.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Use this function to determine the default (and usually best optomized)
 | 
					    Use this function to determine the default (and usually best optimized)
 | 
				
			||||||
    rendering intent for this profile.  Most profiles support multiple
 | 
					    rendering intent for this profile.  Most profiles support multiple
 | 
				
			||||||
    rendering intents, but are intended mostly for one type of conversion.
 | 
					    rendering intents, but are intended mostly for one type of conversion.
 | 
				
			||||||
    If you wish to use a different intent than returned, use
 | 
					    If you wish to use a different intent than returned, use
 | 
				
			||||||
| 
						 | 
					@ -914,7 +914,7 @@ def isIntentSupported(profile, intent, direction):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        see the pyCMS documentation for details on rendering intents and what
 | 
					        see the pyCMS documentation for details on rendering intents and what
 | 
				
			||||||
            they do.
 | 
					            they do.
 | 
				
			||||||
    :param direction: Integer specifing if the profile is to be used for input,
 | 
					    :param direction: Integer specifying if the profile is to be used for input,
 | 
				
			||||||
        output, or proof
 | 
					        output, or proof
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            INPUT  = 0 (or use ImageCms.DIRECTION_INPUT)
 | 
					            INPUT  = 0 (or use ImageCms.DIRECTION_INPUT)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getrgb(color):
 | 
					def getrgb(color):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
     Convert a color string to an RGB tuple. If the string cannot be parsed,
 | 
					     Convert a color string to an RGB tuple. If the string cannot be parsed,
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,8 @@ def getrgb(color):
 | 
				
			||||||
            int(rgb[1] * 255 + 0.5),
 | 
					            int(rgb[1] * 255 + 0.5),
 | 
				
			||||||
            int(rgb[2] * 255 + 0.5)
 | 
					            int(rgb[2] * 255 + 0.5)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
    m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
 | 
					    m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$",
 | 
				
			||||||
 | 
					                 color)
 | 
				
			||||||
    if m:
 | 
					    if m:
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            int(m.group(1)),
 | 
					            int(m.group(1)),
 | 
				
			||||||
| 
						 | 
					@ -96,6 +98,7 @@ def getrgb(color):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
    raise ValueError("unknown color specifier: %r" % color)
 | 
					    raise ValueError("unknown color specifier: %r" % color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getcolor(color, mode):
 | 
					def getcolor(color, mode):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
 | 
					    Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,13 +40,14 @@ try:
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    warnings = None
 | 
					    warnings = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# A simple 2D drawing interface for PIL images.
 | 
					# A simple 2D drawing interface for PIL images.
 | 
				
			||||||
# <p>
 | 
					# <p>
 | 
				
			||||||
# Application code should use the <b>Draw</b> factory, instead of
 | 
					# Application code should use the <b>Draw</b> factory, instead of
 | 
				
			||||||
# directly.
 | 
					# directly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImageDraw:
 | 
					class ImageDraw(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ##
 | 
					    ##
 | 
				
			||||||
    # Create a drawing instance.
 | 
					    # Create a drawing instance.
 | 
				
			||||||
| 
						 | 
					@ -61,7 +62,7 @@ class ImageDraw:
 | 
				
			||||||
    def __init__(self, im, mode=None):
 | 
					    def __init__(self, im, mode=None):
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        if im.readonly:
 | 
					        if im.readonly:
 | 
				
			||||||
            im._copy() # make it writable
 | 
					            im._copy()  # make it writeable
 | 
				
			||||||
        blend = 0
 | 
					        blend = 0
 | 
				
			||||||
        if mode is None:
 | 
					        if mode is None:
 | 
				
			||||||
            mode = im.mode
 | 
					            mode = im.mode
 | 
				
			||||||
| 
						 | 
					@ -280,6 +281,7 @@ class ImageDraw:
 | 
				
			||||||
            font = self.getfont()
 | 
					            font = self.getfont()
 | 
				
			||||||
        return font.getsize(text)
 | 
					        return font.getsize(text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# A simple 2D drawing interface for PIL images.
 | 
					# A simple 2D drawing interface for PIL images.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -302,6 +304,7 @@ try:
 | 
				
			||||||
except:
 | 
					except:
 | 
				
			||||||
    Outline = None
 | 
					    Outline = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# (Experimental) A more advanced 2D drawing interface for PIL images,
 | 
					# (Experimental) A more advanced 2D drawing interface for PIL images,
 | 
				
			||||||
# based on the WCK interface.
 | 
					# based on the WCK interface.
 | 
				
			||||||
| 
						 | 
					@ -325,6 +328,7 @@ def getdraw(im=None, hints=None):
 | 
				
			||||||
        im = handler.Draw(im)
 | 
					        im = handler.Draw(im)
 | 
				
			||||||
    return im, handler
 | 
					    return im, handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# (experimental) Fills a bounded region with a given color.
 | 
					# (experimental) Fills a bounded region with a given color.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,22 +18,26 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath
 | 
					from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Pen:
 | 
					
 | 
				
			||||||
 | 
					class Pen(object):
 | 
				
			||||||
    def __init__(self, color, width=1, opacity=255):
 | 
					    def __init__(self, color, width=1, opacity=255):
 | 
				
			||||||
        self.color = ImageColor.getrgb(color)
 | 
					        self.color = ImageColor.getrgb(color)
 | 
				
			||||||
        self.width = width
 | 
					        self.width = width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Brush:
 | 
					
 | 
				
			||||||
 | 
					class Brush(object):
 | 
				
			||||||
    def __init__(self, color, opacity=255):
 | 
					    def __init__(self, color, opacity=255):
 | 
				
			||||||
        self.color = ImageColor.getrgb(color)
 | 
					        self.color = ImageColor.getrgb(color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Font:
 | 
					
 | 
				
			||||||
 | 
					class Font(object):
 | 
				
			||||||
    def __init__(self, color, file, size=12):
 | 
					    def __init__(self, color, file, size=12):
 | 
				
			||||||
        # FIXME: add support for bitmap fonts
 | 
					        # FIXME: add support for bitmap fonts
 | 
				
			||||||
        self.color = ImageColor.getrgb(color)
 | 
					        self.color = ImageColor.getrgb(color)
 | 
				
			||||||
        self.font = ImageFont.truetype(file, size)
 | 
					        self.font = ImageFont.truetype(file, size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Draw:
 | 
					
 | 
				
			||||||
 | 
					class Draw(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, image, size=None, color=None):
 | 
					    def __init__(self, image, size=None, color=None):
 | 
				
			||||||
        if not hasattr(image, "im"):
 | 
					        if not hasattr(image, "im"):
 | 
				
			||||||
| 
						 | 
					@ -47,7 +51,8 @@ class Draw:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def render(self, op, xy, pen, brush=None):
 | 
					    def render(self, op, xy, pen, brush=None):
 | 
				
			||||||
        # handle color arguments
 | 
					        # handle color arguments
 | 
				
			||||||
        outline = fill = None; width = 1
 | 
					        outline = fill = None
 | 
				
			||||||
 | 
					        width = 1
 | 
				
			||||||
        if isinstance(pen, Pen):
 | 
					        if isinstance(pen, Pen):
 | 
				
			||||||
            outline = pen.color
 | 
					            outline = pen.color
 | 
				
			||||||
            width = pen.width
 | 
					            width = pen.width
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
from PIL import Image, ImageFilter, ImageStat
 | 
					from PIL import Image, ImageFilter, ImageStat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _Enhance:
 | 
					class _Enhance(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def enhance(self, factor):
 | 
					    def enhance(self, factor):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,11 @@ class Color(_Enhance):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def __init__(self, image):
 | 
					    def __init__(self, image):
 | 
				
			||||||
        self.image = image
 | 
					        self.image = image
 | 
				
			||||||
        self.degenerate = image.convert("L").convert(image.mode)
 | 
					        self.intermediate_mode = 'L'
 | 
				
			||||||
 | 
					        if 'A' in image.getbands():
 | 
				
			||||||
 | 
					            self.intermediate_mode = 'LA'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.degenerate = image.convert(self.intermediate_mode).convert(image.mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Contrast(_Enhance):
 | 
					class Contrast(_Enhance):
 | 
				
			||||||
| 
						 | 
					@ -62,11 +66,14 @@ class Contrast(_Enhance):
 | 
				
			||||||
        mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
 | 
					        mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
 | 
				
			||||||
        self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
 | 
					        self.degenerate = Image.new("L", image.size, mean).convert(image.mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'A' in image.getbands():
 | 
				
			||||||
 | 
					            self.degenerate.putalpha(image.split()[-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Brightness(_Enhance):
 | 
					class Brightness(_Enhance):
 | 
				
			||||||
    """Adjust image brightness.
 | 
					    """Adjust image brightness.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This class can be used to control the brighntess of an image.  An
 | 
					    This class can be used to control the brightness of an image.  An
 | 
				
			||||||
    enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the
 | 
					    enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the
 | 
				
			||||||
    original image.
 | 
					    original image.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -74,6 +81,9 @@ class Brightness(_Enhance):
 | 
				
			||||||
        self.image = image
 | 
					        self.image = image
 | 
				
			||||||
        self.degenerate = Image.new(image.mode, image.size, 0)
 | 
					        self.degenerate = Image.new(image.mode, image.size, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'A' in image.getbands():
 | 
				
			||||||
 | 
					            self.degenerate.putalpha(image.split()[-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Sharpness(_Enhance):
 | 
					class Sharpness(_Enhance):
 | 
				
			||||||
    """Adjust image sharpness.
 | 
					    """Adjust image sharpness.
 | 
				
			||||||
| 
						 | 
					@ -85,3 +95,6 @@ class Sharpness(_Enhance):
 | 
				
			||||||
    def __init__(self, image):
 | 
					    def __init__(self, image):
 | 
				
			||||||
        self.image = image
 | 
					        self.image = image
 | 
				
			||||||
        self.degenerate = image.filter(ImageFilter.SMOOTH)
 | 
					        self.degenerate = image.filter(ImageFilter.SMOOTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'A' in image.getbands():
 | 
				
			||||||
 | 
					            self.degenerate.putalpha(image.split()[-1])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,8 +29,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
from PIL._util import isPath
 | 
					from PIL._util import isPath
 | 
				
			||||||
import traceback, os, sys
 | 
					 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import traceback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MAXBLOCK = 65536
 | 
					MAXBLOCK = 65536
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +48,7 @@ ERRORS = {
 | 
				
			||||||
    -9: "out of memory error"
 | 
					    -9: "out of memory error"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def raise_ioerror(error):
 | 
					def raise_ioerror(error):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        message = Image.core.getcodecstatus(error)
 | 
					        message = Image.core.getcodecstatus(error)
 | 
				
			||||||
| 
						 | 
					@ -55,6 +58,7 @@ def raise_ioerror(error):
 | 
				
			||||||
        message = "decoder error %d" % error
 | 
					        message = "decoder error %d" % error
 | 
				
			||||||
    raise IOError(message + " when reading image file")
 | 
					    raise IOError(message + " when reading image file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Helpers
 | 
					# Helpers
 | 
				
			||||||
| 
						 | 
					@ -63,6 +67,7 @@ def _tilesort(t):
 | 
				
			||||||
    # sort on offset
 | 
					    # sort on offset
 | 
				
			||||||
    return t[2]
 | 
					    return t[2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# ImageFile base class
 | 
					# ImageFile base class
 | 
				
			||||||
| 
						 | 
					@ -191,6 +196,9 @@ class ImageFile(Image.Image):
 | 
				
			||||||
            except AttributeError:
 | 
					            except AttributeError:
 | 
				
			||||||
                prefix = b""
 | 
					                prefix = b""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Buffer length read; assign a default value
 | 
				
			||||||
 | 
					            t = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for d, e, o, a in self.tile:
 | 
					            for d, e, o, a in self.tile:
 | 
				
			||||||
                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
 | 
					                d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
 | 
				
			||||||
                seek(o)
 | 
					                seek(o)
 | 
				
			||||||
| 
						 | 
					@ -213,13 +221,15 @@ class ImageFile(Image.Image):
 | 
				
			||||||
                        self.tile = []
 | 
					                        self.tile = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        # JpegDecode needs to clean things up here either way
 | 
					                        # JpegDecode needs to clean things up here either way
 | 
				
			||||||
                        # If we don't destroy the decompressor, we have a memory leak.
 | 
					                        # If we don't destroy the decompressor,
 | 
				
			||||||
 | 
					                        # we have a memory leak.
 | 
				
			||||||
                        d.cleanup()
 | 
					                        d.cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if LOAD_TRUNCATED_IMAGES:
 | 
					                        if LOAD_TRUNCATED_IMAGES:
 | 
				
			||||||
                            break
 | 
					                            break
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            raise IOError("image file is truncated (%d bytes not processed)" % len(b))
 | 
					                            raise IOError("image file is truncated "
 | 
				
			||||||
 | 
					                                          "(%d bytes not processed)" % len(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    b = b + s
 | 
					                    b = b + s
 | 
				
			||||||
                    n, e = d.decode(b)
 | 
					                    n, e = d.decode(b)
 | 
				
			||||||
| 
						 | 
					@ -227,6 +237,8 @@ class ImageFile(Image.Image):
 | 
				
			||||||
                        break
 | 
					                        break
 | 
				
			||||||
                    b = b[n:]
 | 
					                    b = b[n:]
 | 
				
			||||||
                    t = t + n
 | 
					                    t = t + n
 | 
				
			||||||
 | 
					                # Need to cleanup here to prevent leaks in PyPy
 | 
				
			||||||
 | 
					                d.cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.tile = []
 | 
					        self.tile = []
 | 
				
			||||||
        self.readonly = readonly
 | 
					        self.readonly = readonly
 | 
				
			||||||
| 
						 | 
					@ -299,7 +311,7 @@ class StubImageFile(ImageFile):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Parser:
 | 
					class Parser(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Incremental image parser.  This class implements the standard
 | 
					    Incremental image parser.  This class implements the standard
 | 
				
			||||||
    feed/close consumer interface.
 | 
					    feed/close consumer interface.
 | 
				
			||||||
| 
						 | 
					@ -310,6 +322,7 @@ class Parser:
 | 
				
			||||||
    image = None
 | 
					    image = None
 | 
				
			||||||
    data = None
 | 
					    data = None
 | 
				
			||||||
    decoder = None
 | 
					    decoder = None
 | 
				
			||||||
 | 
					    offset = 0
 | 
				
			||||||
    finished = 0
 | 
					    finished = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reset(self):
 | 
					    def reset(self):
 | 
				
			||||||
| 
						 | 
					@ -434,6 +447,7 @@ class Parser:
 | 
				
			||||||
                fp.close()  # explicitly close the virtual file
 | 
					                fp.close()  # explicitly close the virtual file
 | 
				
			||||||
        return self.image
 | 
					        return self.image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, tile, bufsize=0):
 | 
					def _save(im, fp, tile, bufsize=0):
 | 
				
			||||||
| 
						 | 
					@ -450,7 +464,7 @@ def _save(im, fp, tile, bufsize=0):
 | 
				
			||||||
        im.encoderconfig = ()
 | 
					        im.encoderconfig = ()
 | 
				
			||||||
    tile.sort(key=_tilesort)
 | 
					    tile.sort(key=_tilesort)
 | 
				
			||||||
    # FIXME: make MAXBLOCK a configuration parameter
 | 
					    # FIXME: make MAXBLOCK a configuration parameter
 | 
				
			||||||
    # It would be great if we could have the encoder specifiy what it needs
 | 
					    # It would be great if we could have the encoder specify what it needs
 | 
				
			||||||
    # But, it would need at least the image size in most cases. RawEncode is
 | 
					    # But, it would need at least the image size in most cases. RawEncode is
 | 
				
			||||||
    # a tricky case.
 | 
					    # a tricky case.
 | 
				
			||||||
    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c
 | 
					    bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4)  # see RawEncode.c
 | 
				
			||||||
| 
						 | 
					@ -471,6 +485,7 @@ def _save(im, fp, tile, bufsize=0):
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
            if s < 0:
 | 
					            if s < 0:
 | 
				
			||||||
                raise IOError("encoder error %d when writing image file" % s)
 | 
					                raise IOError("encoder error %d when writing image file" % s)
 | 
				
			||||||
 | 
					            e.cleanup()
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # slight speedup: compress to real file object
 | 
					        # slight speedup: compress to real file object
 | 
				
			||||||
        for e, b, o, a in tile:
 | 
					        for e, b, o, a in tile:
 | 
				
			||||||
| 
						 | 
					@ -481,9 +496,11 @@ def _save(im, fp, tile, bufsize=0):
 | 
				
			||||||
            s = e.encode_to_file(fh, bufsize)
 | 
					            s = e.encode_to_file(fh, bufsize)
 | 
				
			||||||
            if s < 0:
 | 
					            if s < 0:
 | 
				
			||||||
                raise IOError("encoder error %d when writing image file" % s)
 | 
					                raise IOError("encoder error %d when writing image file" % s)
 | 
				
			||||||
 | 
					            e.cleanup()
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        fp.flush()
 | 
					        fp.flush()
 | 
				
			||||||
    except: pass
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _safe_read(fp, size):
 | 
					def _safe_read(fp, size):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from functools import reduce
 | 
					import functools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Filter(object):
 | 
					class Filter(object):
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ class Kernel(Filter):
 | 
				
			||||||
    def __init__(self, size, kernel, scale=None, offset=0):
 | 
					    def __init__(self, size, kernel, scale=None, offset=0):
 | 
				
			||||||
        if scale is None:
 | 
					        if scale is None:
 | 
				
			||||||
            # default scale is sum of kernel
 | 
					            # default scale is sum of kernel
 | 
				
			||||||
            scale = reduce(lambda a,b: a+b, kernel)
 | 
					            scale = functools.reduce(lambda a, b: a+b, kernel)
 | 
				
			||||||
        if size[0] * size[1] != len(kernel):
 | 
					        if size[0] * size[1] != len(kernel):
 | 
				
			||||||
            raise ValueError("not enough coefficients in kernel")
 | 
					            raise ValueError("not enough coefficients in kernel")
 | 
				
			||||||
        self.filterargs = size, scale, offset, kernel
 | 
					        self.filterargs = size, scale, offset, kernel
 | 
				
			||||||
| 
						 | 
					@ -162,7 +162,13 @@ class UnsharpMask(Filter):
 | 
				
			||||||
    See Wikipedia's entry on `digital unsharp masking`_ for an explanation of
 | 
					    See Wikipedia's entry on `digital unsharp masking`_ for an explanation of
 | 
				
			||||||
    the parameters.
 | 
					    the parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param radius: Blur Radius
 | 
				
			||||||
 | 
					    :param percent: Unsharp strength, in percent
 | 
				
			||||||
 | 
					    :param threshold: Threshold controls the minimum brightness change that
 | 
				
			||||||
 | 
					      will be sharpened
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .. _digital unsharp masking: https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking
 | 
					    .. _digital unsharp masking: https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    name = "UnsharpMask"
 | 
					    name = "UnsharpMask"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,8 +25,6 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
from PIL._util import isDirectory, isPath
 | 
					from PIL._util import isDirectory, isPath
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
| 
						 | 
					@ -38,7 +36,7 @@ except ImportError:
 | 
				
			||||||
    warnings = None
 | 
					    warnings = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _imagingft_not_installed:
 | 
					class _imagingft_not_installed(object):
 | 
				
			||||||
    # module placeholder
 | 
					    # module placeholder
 | 
				
			||||||
    def __getattr__(self, id):
 | 
					    def __getattr__(self, id):
 | 
				
			||||||
        raise ImportError("The _imagingft C module is not installed")
 | 
					        raise ImportError("The _imagingft C module is not installed")
 | 
				
			||||||
| 
						 | 
					@ -64,7 +62,7 @@ except ImportError:
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImageFont:
 | 
					class ImageFont(object):
 | 
				
			||||||
    "PIL font wrapper"
 | 
					    "PIL font wrapper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _load_pilfont(self, filename):
 | 
					    def _load_pilfont(self, filename):
 | 
				
			||||||
| 
						 | 
					@ -120,7 +118,7 @@ class ImageFont:
 | 
				
			||||||
# Wrapper for FreeType fonts.  Application code should use the
 | 
					# Wrapper for FreeType fonts.  Application code should use the
 | 
				
			||||||
# <b>truetype</b> factory function to create font objects.
 | 
					# <b>truetype</b> factory function to create font objects.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FreeTypeFont:
 | 
					class FreeTypeFont(object):
 | 
				
			||||||
    "FreeType font wrapper (requires _imagingft service)"
 | 
					    "FreeType font wrapper (requires _imagingft service)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, font=None, size=10, index=0, encoding="", file=None):
 | 
					    def __init__(self, font=None, size=10, index=0, encoding="", file=None):
 | 
				
			||||||
| 
						 | 
					@ -133,6 +131,11 @@ class FreeTypeFont:
 | 
				
			||||||
                    DeprecationWarning)
 | 
					                    DeprecationWarning)
 | 
				
			||||||
            font = file
 | 
					            font = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.path = font
 | 
				
			||||||
 | 
					        self.size = size
 | 
				
			||||||
 | 
					        self.index = index
 | 
				
			||||||
 | 
					        self.encoding = encoding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if isPath(font):
 | 
					        if isPath(font):
 | 
				
			||||||
            self.font = core.getfont(font, size, index, encoding)
 | 
					            self.font = core.getfont(font, size, index, encoding)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					@ -162,6 +165,22 @@ class FreeTypeFont:
 | 
				
			||||||
        self.font.render(text, im.id, mode == "1")
 | 
					        self.font.render(text, im.id, mode == "1")
 | 
				
			||||||
        return im, offset
 | 
					        return im, offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def font_variant(self, font=None, size=None, index=None, encoding=None):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Create a copy of this FreeTypeFont object,
 | 
				
			||||||
 | 
					        using any specified arguments to override the settings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Parameters are identical to the parameters used to initialize this
 | 
				
			||||||
 | 
					        object, minus the deprecated 'file' argument.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :return: A FreeTypeFont object.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return FreeTypeFont(font=self.path if font is None else font,
 | 
				
			||||||
 | 
					                            size=self.size if size is None else size,
 | 
				
			||||||
 | 
					                            index=self.index if index is None else index,
 | 
				
			||||||
 | 
					                            encoding=self.encoding if encoding is None else
 | 
				
			||||||
 | 
					                            encoding)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Wrapper that creates a transposed font from any existing font
 | 
					# Wrapper that creates a transposed font from any existing font
 | 
				
			||||||
# object.
 | 
					# object.
 | 
				
			||||||
| 
						 | 
					@ -172,7 +191,7 @@ class FreeTypeFont:
 | 
				
			||||||
#     Image.ROTATE_90, Image.ROTATE_180, or Image.ROTATE_270.
 | 
					#     Image.ROTATE_90, Image.ROTATE_180, or Image.ROTATE_270.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TransposedFont:
 | 
					class TransposedFont(object):
 | 
				
			||||||
    "Wrapper for writing rotated or mirrored text"
 | 
					    "Wrapper for writing rotated or mirrored text"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, font, orientation=None):
 | 
					    def __init__(self, font, orientation=None):
 | 
				
			||||||
| 
						 | 
					@ -214,7 +233,7 @@ def truetype(font=None, size=10, index=0, encoding="", filename=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This function requires the _imagingft service.
 | 
					    This function requires the _imagingft service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param filename: A truetype font file. Under Windows, if the file
 | 
					    :param font: A truetype font file. Under Windows, if the file
 | 
				
			||||||
                     is not found in this filename, the loader also looks in
 | 
					                     is not found in this filename, the loader also looks in
 | 
				
			||||||
                     Windows :file:`fonts/` directory.
 | 
					                     Windows :file:`fonts/` directory.
 | 
				
			||||||
    :param size: The requested size, in points.
 | 
					    :param size: The requested size, in points.
 | 
				
			||||||
| 
						 | 
					@ -224,6 +243,7 @@ def truetype(font=None, size=10, index=0, encoding="", filename=None):
 | 
				
			||||||
                     Symbol), "ADOB" (Adobe Standard), "ADBE" (Adobe Expert),
 | 
					                     Symbol), "ADOB" (Adobe Standard), "ADBE" (Adobe Expert),
 | 
				
			||||||
                     and "armn" (Apple Roman). See the FreeType documentation
 | 
					                     and "armn" (Apple Roman). See the FreeType documentation
 | 
				
			||||||
                     for more information.
 | 
					                     for more information.
 | 
				
			||||||
 | 
					    :param filename: Deprecated. Please use font instead.
 | 
				
			||||||
    :return: A font object.
 | 
					    :return: A font object.
 | 
				
			||||||
    :exception IOError: If the file could not be read.
 | 
					    :exception IOError: If the file could not be read.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -239,14 +259,44 @@ def truetype(font=None, size=10, index=0, encoding="", filename=None):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        return FreeTypeFont(font, size, index, encoding)
 | 
					        return FreeTypeFont(font, size, index, encoding)
 | 
				
			||||||
    except IOError:
 | 
					    except IOError:
 | 
				
			||||||
 | 
					        ttf_filename = os.path.basename(font)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dirs = []
 | 
				
			||||||
        if sys.platform == "win32":
 | 
					        if sys.platform == "win32":
 | 
				
			||||||
            # check the windows font repository
 | 
					            # check the windows font repository
 | 
				
			||||||
            # NOTE: must use uppercase WINDIR, to work around bugs in
 | 
					            # NOTE: must use uppercase WINDIR, to work around bugs in
 | 
				
			||||||
            # 1.5.2's os.environ.get()
 | 
					            # 1.5.2's os.environ.get()
 | 
				
			||||||
            windir = os.environ.get("WINDIR")
 | 
					            windir = os.environ.get("WINDIR")
 | 
				
			||||||
            if windir:
 | 
					            if windir:
 | 
				
			||||||
                filename = os.path.join(windir, "fonts", font)
 | 
					                dirs.append(os.path.join(windir, "fonts"))
 | 
				
			||||||
                return FreeTypeFont(filename, size, index, encoding)
 | 
					        elif sys.platform in ('linux', 'linux2'):
 | 
				
			||||||
 | 
					            lindirs = os.environ.get("XDG_DATA_DIRS", "")
 | 
				
			||||||
 | 
					            if not lindirs:
 | 
				
			||||||
 | 
					                # According to the freedesktop spec, XDG_DATA_DIRS should
 | 
				
			||||||
 | 
					                # default to /usr/share
 | 
				
			||||||
 | 
					                lindirs = '/usr/share'
 | 
				
			||||||
 | 
					            dirs += [os.path.join(lindir, "fonts") for lindir in lindirs.split(":")]
 | 
				
			||||||
 | 
					        elif sys.platform == 'darwin':
 | 
				
			||||||
 | 
					            dirs += ['/Library/Fonts', '/System/Library/Fonts',
 | 
				
			||||||
 | 
					                     os.path.expanduser('~/Library/Fonts')]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ext = os.path.splitext(ttf_filename)[1]
 | 
				
			||||||
 | 
					        first_font_with_a_different_extension = None
 | 
				
			||||||
 | 
					        for directory in dirs:
 | 
				
			||||||
 | 
					            for walkroot, walkdir, walkfilenames in os.walk(directory):
 | 
				
			||||||
 | 
					                for walkfilename in walkfilenames:
 | 
				
			||||||
 | 
					                    if ext and walkfilename == ttf_filename:
 | 
				
			||||||
 | 
					                        fontpath = os.path.join(walkroot, walkfilename)
 | 
				
			||||||
 | 
					                        return FreeTypeFont(fontpath, size, index, encoding)
 | 
				
			||||||
 | 
					                    elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename:
 | 
				
			||||||
 | 
					                        fontpath = os.path.join(walkroot, walkfilename)
 | 
				
			||||||
 | 
					                        if os.path.splitext(fontpath)[1] == '.ttf':
 | 
				
			||||||
 | 
					                            return FreeTypeFont(fontpath, size, index, encoding)
 | 
				
			||||||
 | 
					                        if not ext and first_font_with_a_different_extension is None:
 | 
				
			||||||
 | 
					                            first_font_with_a_different_extension = fontpath
 | 
				
			||||||
 | 
					        if first_font_with_a_different_extension:
 | 
				
			||||||
 | 
					            return FreeTypeFont(first_font_with_a_different_extension, size,
 | 
				
			||||||
 | 
					                                index, encoding)
 | 
				
			||||||
        raise
 | 
					        raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,15 +309,15 @@ def load_path(filename):
 | 
				
			||||||
    :return: A font object.
 | 
					    :return: A font object.
 | 
				
			||||||
    :exception IOError: If the file could not be read.
 | 
					    :exception IOError: If the file could not be read.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    for dir in sys.path:
 | 
					    for directory in sys.path:
 | 
				
			||||||
        if isDirectory(dir):
 | 
					        if isDirectory(directory):
 | 
				
			||||||
            if not isinstance(filename, str):
 | 
					            if not isinstance(filename, str):
 | 
				
			||||||
                if bytes is str:
 | 
					                if bytes is str:
 | 
				
			||||||
                    filename = filename.encode("utf-8")
 | 
					                    filename = filename.encode("utf-8")
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    filename = filename.decode("utf-8")
 | 
					                    filename = filename.decode("utf-8")
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                return load(os.path.join(dir, filename))
 | 
					                return load(os.path.join(directory, filename))
 | 
				
			||||||
            except IOError:
 | 
					            except IOError:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
    raise IOError("cannot find font file")
 | 
					    raise IOError("cannot find font file")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					if sys.platform != "win32":
 | 
				
			||||||
 | 
					    raise ImportError("ImageGrab is Windows only")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    # built-in driver (1.1.3 and later)
 | 
					    # built-in driver (1.1.3 and later)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ def _isconstant(v):
 | 
				
			||||||
    return isinstance(v, int) or isinstance(v, float)
 | 
					    return isinstance(v, int) or isinstance(v, float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _Operand:
 | 
					class _Operand(object):
 | 
				
			||||||
    # wraps an image operand, providing standard operators
 | 
					    # wraps an image operand, providing standard operators
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, im):
 | 
					    def __init__(self, im):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,10 +16,11 @@
 | 
				
			||||||
# mode descriptor cache
 | 
					# mode descriptor cache
 | 
				
			||||||
_modes = {}
 | 
					_modes = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Wrapper for mode strings.
 | 
					# Wrapper for mode strings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ModeDescriptor:
 | 
					class ModeDescriptor(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, mode, bands, basemode, basetype):
 | 
					    def __init__(self, mode, bands, basemode, basetype):
 | 
				
			||||||
        self.mode = mode
 | 
					        self.mode = mode
 | 
				
			||||||
| 
						 | 
					@ -30,6 +31,7 @@ class ModeDescriptor:
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.mode
 | 
					        return self.mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Gets a mode descriptor for the given mode.
 | 
					# Gets a mode descriptor for the given mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ import re
 | 
				
			||||||
LUT_SIZE = 1 << 9
 | 
					LUT_SIZE = 1 << 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LutBuilder:
 | 
					class LutBuilder(object):
 | 
				
			||||||
    """A class for building a MorphLut from a descriptive language
 | 
					    """A class for building a MorphLut from a descriptive language
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      The input patterns is a list of a strings sequences like these::
 | 
					      The input patterns is a list of a strings sequences like these::
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ class LutBuilder:
 | 
				
			||||||
        return self.lut
 | 
					        return self.lut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MorphOp:
 | 
					class MorphOp(object):
 | 
				
			||||||
    """A class for binary morphological operators"""
 | 
					    """A class for binary morphological operators"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self,
 | 
					    def __init__(self,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,8 @@
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
from PIL._util import isStringType
 | 
					from PIL._util import isStringType
 | 
				
			||||||
import operator
 | 
					import operator
 | 
				
			||||||
from functools import reduce
 | 
					import functools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# helpers
 | 
					# helpers
 | 
				
			||||||
| 
						 | 
					@ -35,12 +36,14 @@ def _border(border):
 | 
				
			||||||
        left = top = right = bottom = border
 | 
					        left = top = right = bottom = border
 | 
				
			||||||
    return left, top, right, bottom
 | 
					    return left, top, right, bottom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _color(color, mode):
 | 
					def _color(color, mode):
 | 
				
			||||||
    if isStringType(color):
 | 
					    if isStringType(color):
 | 
				
			||||||
        from PIL import ImageColor
 | 
					        from PIL import ImageColor
 | 
				
			||||||
        color = ImageColor.getcolor(color, mode)
 | 
					        color = ImageColor.getcolor(color, mode)
 | 
				
			||||||
    return color
 | 
					    return color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _lut(image, lut):
 | 
					def _lut(image, lut):
 | 
				
			||||||
    if image.mode == "P":
 | 
					    if image.mode == "P":
 | 
				
			||||||
        # FIXME: apply to lookup table, not image data
 | 
					        # FIXME: apply to lookup table, not image data
 | 
				
			||||||
| 
						 | 
					@ -147,7 +150,9 @@ def colorize(image, black, white):
 | 
				
			||||||
    assert image.mode == "L"
 | 
					    assert image.mode == "L"
 | 
				
			||||||
    black = _color(black, "RGB")
 | 
					    black = _color(black, "RGB")
 | 
				
			||||||
    white = _color(white, "RGB")
 | 
					    white = _color(white, "RGB")
 | 
				
			||||||
    red = []; green = []; blue = []
 | 
					    red = []
 | 
				
			||||||
 | 
					    green = []
 | 
				
			||||||
 | 
					    blue = []
 | 
				
			||||||
    for i in range(256):
 | 
					    for i in range(256):
 | 
				
			||||||
        red.append(black[0]+i*(white[0]-black[0])//255)
 | 
					        red.append(black[0]+i*(white[0]-black[0])//255)
 | 
				
			||||||
        green.append(black[1]+i*(white[1]-black[1])//255)
 | 
					        green.append(black[1]+i*(white[1]-black[1])//255)
 | 
				
			||||||
| 
						 | 
					@ -208,7 +213,7 @@ def equalize(image, mask=None):
 | 
				
			||||||
        if len(histo) <= 1:
 | 
					        if len(histo) <= 1:
 | 
				
			||||||
            lut.extend(list(range(256)))
 | 
					            lut.extend(list(range(256)))
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            step = (reduce(operator.add, histo) - histo[-1]) // 255
 | 
					            step = (functools.reduce(operator.add, histo) - histo[-1]) // 255
 | 
				
			||||||
            if not step:
 | 
					            if not step:
 | 
				
			||||||
                lut.extend(list(range(256)))
 | 
					                lut.extend(list(range(256)))
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
| 
						 | 
					@ -228,7 +233,6 @@ def expand(image, border=0, fill=0):
 | 
				
			||||||
    :param fill: Pixel fill value (a color value).  Default is 0 (black).
 | 
					    :param fill: Pixel fill value (a color value).  Default is 0 (black).
 | 
				
			||||||
    :return: An image.
 | 
					    :return: An image.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    "Add border to image"
 | 
					 | 
				
			||||||
    left, top, right, bottom = _border(border)
 | 
					    left, top, right, bottom = _border(border)
 | 
				
			||||||
    width = left + image.size[0] + right
 | 
					    width = left + image.size[0] + right
 | 
				
			||||||
    height = top + image.size[1] + bottom
 | 
					    height = top + image.size[1] + bottom
 | 
				
			||||||
| 
						 | 
					@ -273,7 +277,7 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)):
 | 
				
			||||||
        centering = [centering[0], centering[1]]
 | 
					        centering = [centering[0], centering[1]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if centering[0] > 1.0 or centering[0] < 0.0:
 | 
					    if centering[0] > 1.0 or centering[0] < 0.0:
 | 
				
			||||||
        centering [0] = 0.50
 | 
					        centering[0] = 0.50
 | 
				
			||||||
    if centering[1] > 1.0 or centering[1] < 0.0:
 | 
					    if centering[1] > 1.0 or centering[1] < 0.0:
 | 
				
			||||||
        centering[1] = 0.50
 | 
					        centering[1] = 0.50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -404,6 +408,7 @@ def solarize(image, threshold=128):
 | 
				
			||||||
            lut.append(255-i)
 | 
					            lut.append(255-i)
 | 
				
			||||||
    return _lut(image, lut)
 | 
					    return _lut(image, lut)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# PIL USM components, from Kevin Cazabon.
 | 
					# PIL USM components, from Kevin Cazabon.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,6 +424,7 @@ def gaussian_blur(im, radius=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gblur = gaussian_blur
 | 
					gblur = gaussian_blur
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def unsharp_mask(im, radius=None, percent=None, threshold=None):
 | 
					def unsharp_mask(im, radius=None, percent=None, threshold=None):
 | 
				
			||||||
    """ PIL_usm.usm(im, [radius, percent, threshold])"""
 | 
					    """ PIL_usm.usm(im, [radius, percent, threshold])"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -434,3 +440,22 @@ def unsharp_mask(im, radius=None, percent=None, threshold=None):
 | 
				
			||||||
    return im.im.unsharp_mask(radius, percent, threshold)
 | 
					    return im.im.unsharp_mask(radius, percent, threshold)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
usm = unsharp_mask
 | 
					usm = unsharp_mask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def box_blur(image, radius):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Blur the image by setting each pixel to the average value of the pixels
 | 
				
			||||||
 | 
					    in a square box extending radius pixels in each direction.
 | 
				
			||||||
 | 
					    Supports float radius of arbitrary size. Uses an optimized implementation
 | 
				
			||||||
 | 
					    which runs in linear time relative to the size of the image
 | 
				
			||||||
 | 
					    for any radius value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param image: The image to blur.
 | 
				
			||||||
 | 
					    :param radius: Size of the box in one direction. Radius 0 does not blur,
 | 
				
			||||||
 | 
					                   returns an identical image. Radius 1 takes 1 pixel
 | 
				
			||||||
 | 
					                   in each direction, i.e. 9 pixels in total.
 | 
				
			||||||
 | 
					    :return: An image.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    image.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return image._new(image.im.box_blur(radius))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ import warnings
 | 
				
			||||||
from PIL import ImageColor
 | 
					from PIL import ImageColor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImagePalette:
 | 
					class ImagePalette(object):
 | 
				
			||||||
    "Color palette for palette mapped images"
 | 
					    "Color palette for palette mapped images"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, mode="RGB", palette=None, size=0):
 | 
					    def __init__(self, mode="RGB", palette=None, size=0):
 | 
				
			||||||
| 
						 | 
					@ -225,8 +225,8 @@ def load(filename):
 | 
				
			||||||
            p = PaletteFile.PaletteFile(fp)
 | 
					            p = PaletteFile.PaletteFile(fp)
 | 
				
			||||||
            lut = p.getpalette()
 | 
					            lut = p.getpalette()
 | 
				
			||||||
        except (SyntaxError, ValueError):
 | 
					        except (SyntaxError, ValueError):
 | 
				
			||||||
            import traceback
 | 
					            #import traceback
 | 
				
			||||||
            traceback.print_exc()
 | 
					            #traceback.print_exc()
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not lut:
 | 
					    if not lut:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ from PIL import Image
 | 
				
			||||||
# the Python class below is overridden by the C implementation.
 | 
					# the Python class below is overridden by the C implementation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Path:
 | 
					class Path(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, xy):
 | 
					    def __init__(self, xy):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,20 +18,30 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
from PIL._util import isPath
 | 
					from PIL._util import isPath
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					if 'PyQt4.QtGui' not in sys.modules:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
        from PyQt5.QtGui import QImage, qRgba
 | 
					        from PyQt5.QtGui import QImage, qRgba
 | 
				
			||||||
except:
 | 
					    except:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            from PyQt4.QtGui import QImage, qRgba
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            from PySide.QtGui import QImage, qRgba
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					else:  #PyQt4 is used
 | 
				
			||||||
    from PyQt4.QtGui import QImage, qRgba
 | 
					    from PyQt4.QtGui import QImage, qRgba
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# (Internal) Turns an RGB color into a Qt compatible color integer.
 | 
					# (Internal) Turns an RGB color into a Qt compatible color integer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def rgb(r, g, b, a=255):
 | 
					def rgb(r, g, b, a=255):
 | 
				
			||||||
    # use qRgb to pack the colors, and then turn the resulting long
 | 
					    # use qRgb to pack the colors, and then turn the resulting long
 | 
				
			||||||
    # into a negative integer with the same bitpattern.
 | 
					    # into a negative integer with the same bitpattern.
 | 
				
			||||||
    return (qRgba(r, g, b, a) & 0xffffffff)
 | 
					    return (qRgba(r, g, b, a) & 0xffffffff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# An PIL image wrapper for Qt.  This is a subclass of PyQt4's QImage
 | 
					# An PIL image wrapper for Qt.  This is a subclass of PyQt4's QImage
 | 
				
			||||||
# class.
 | 
					# class.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Iterator:
 | 
					
 | 
				
			||||||
 | 
					class Iterator(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This class implements an iterator object that can be used to loop
 | 
					    This class implements an iterator object that can be used to loop
 | 
				
			||||||
    over an image sequence.
 | 
					    over an image sequence.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,8 @@
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
import os, sys
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.version_info >= (3, 3):
 | 
					if sys.version_info >= (3, 3):
 | 
				
			||||||
    from shlex import quote
 | 
					    from shlex import quote
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,7 @@ else:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_viewers = []
 | 
					_viewers = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def register(viewer, order=1):
 | 
					def register(viewer, order=1):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        if issubclass(viewer, Viewer):
 | 
					        if issubclass(viewer, Viewer):
 | 
				
			||||||
| 
						 | 
					@ -35,6 +37,7 @@ def register(viewer, order=1):
 | 
				
			||||||
    elif order < 0:
 | 
					    elif order < 0:
 | 
				
			||||||
        _viewers.insert(0, viewer)
 | 
					        _viewers.insert(0, viewer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Displays a given image.
 | 
					# Displays a given image.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -49,10 +52,11 @@ def show(image, title=None, **options):
 | 
				
			||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
    return 0
 | 
					    return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Base class for viewers.
 | 
					# Base class for viewers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Viewer:
 | 
					class Viewer(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # main api
 | 
					    # main api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,6 +106,7 @@ if sys.platform == "win32":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class WindowsViewer(Viewer):
 | 
					    class WindowsViewer(Viewer):
 | 
				
			||||||
        format = "BMP"
 | 
					        format = "BMP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def get_command(self, file, **options):
 | 
					        def get_command(self, file, **options):
 | 
				
			||||||
            return ('start "Pillow" /WAIT "%s" '
 | 
					            return ('start "Pillow" /WAIT "%s" '
 | 
				
			||||||
                    '&& ping -n 2 127.0.0.1 >NUL '
 | 
					                    '&& ping -n 2 127.0.0.1 >NUL '
 | 
				
			||||||
| 
						 | 
					@ -113,11 +118,13 @@ elif sys.platform == "darwin":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class MacViewer(Viewer):
 | 
					    class MacViewer(Viewer):
 | 
				
			||||||
        format = "BMP"
 | 
					        format = "BMP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def get_command(self, file, **options):
 | 
					        def get_command(self, file, **options):
 | 
				
			||||||
            # on darwin open returns immediately resulting in the temp
 | 
					            # on darwin open returns immediately resulting in the temp
 | 
				
			||||||
            # file removal while app is opening
 | 
					            # file removal while app is opening
 | 
				
			||||||
            command = "open -a /Applications/Preview.app"
 | 
					            command = "open -a /Applications/Preview.app"
 | 
				
			||||||
            command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file), quote(file))
 | 
					            command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file),
 | 
				
			||||||
 | 
					                                                        quote(file))
 | 
				
			||||||
            return command
 | 
					            return command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    register(MacViewer)
 | 
					    register(MacViewer)
 | 
				
			||||||
| 
						 | 
					@ -140,7 +147,8 @@ else:
 | 
				
			||||||
    class UnixViewer(Viewer):
 | 
					    class UnixViewer(Viewer):
 | 
				
			||||||
        def show_file(self, file, **options):
 | 
					        def show_file(self, file, **options):
 | 
				
			||||||
            command, executable = self.get_command_ex(file, **options)
 | 
					            command, executable = self.get_command_ex(file, **options)
 | 
				
			||||||
            command = "(%s %s; rm -f %s)&" % (command, quote(file), quote(file))
 | 
					            command = "(%s %s; rm -f %s)&" % (command, quote(file),
 | 
				
			||||||
 | 
					                                              quote(file))
 | 
				
			||||||
            os.system(command)
 | 
					            os.system(command)
 | 
				
			||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,13 +21,14 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import operator, math
 | 
					import math
 | 
				
			||||||
from functools import reduce
 | 
					import operator
 | 
				
			||||||
 | 
					import functools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Stat:
 | 
					class Stat(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, image_or_list, mask = None):
 | 
					    def __init__(self, image_or_list, mask=None):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            if mask:
 | 
					            if mask:
 | 
				
			||||||
                self.h = image_or_list.histogram(mask)
 | 
					                self.h = image_or_list.histogram(mask)
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ class Stat:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        v = []
 | 
					        v = []
 | 
				
			||||||
        for i in range(0, len(self.h), 256):
 | 
					        for i in range(0, len(self.h), 256):
 | 
				
			||||||
            v.append(reduce(operator.add, self.h[i:i+256]))
 | 
					            v.append(functools.reduce(operator.add, self.h[i:i+256]))
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getsum(self):
 | 
					    def _getsum(self):
 | 
				
			||||||
| 
						 | 
					@ -78,10 +79,10 @@ class Stat:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        v = []
 | 
					        v = []
 | 
				
			||||||
        for i in range(0, len(self.h), 256):
 | 
					        for i in range(0, len(self.h), 256):
 | 
				
			||||||
            sum = 0.0
 | 
					            layerSum = 0.0
 | 
				
			||||||
            for j in range(256):
 | 
					            for j in range(256):
 | 
				
			||||||
                sum += j * self.h[i + j]
 | 
					                layerSum += j * self.h[i + j]
 | 
				
			||||||
            v.append(sum)
 | 
					            v.append(layerSum)
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getsum2(self):
 | 
					    def _getsum2(self):
 | 
				
			||||||
| 
						 | 
					@ -126,7 +127,6 @@ class Stat:
 | 
				
			||||||
            v.append(math.sqrt(self.sum2[i] / self.count[i]))
 | 
					            v.append(math.sqrt(self.sum2[i] / self.count[i]))
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _getvar(self):
 | 
					    def _getvar(self):
 | 
				
			||||||
        "Get variance for each layer"
 | 
					        "Get variance for each layer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,21 +40,23 @@ from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_pilbitmap_ok = None
 | 
					_pilbitmap_ok = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _pilbitmap_check():
 | 
					def _pilbitmap_check():
 | 
				
			||||||
    global _pilbitmap_ok
 | 
					    global _pilbitmap_ok
 | 
				
			||||||
    if _pilbitmap_ok is None:
 | 
					    if _pilbitmap_ok is None:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            im = Image.new("1", (1,1))
 | 
					            im = Image.new("1", (1, 1))
 | 
				
			||||||
            tkinter.BitmapImage(data="PIL:%d" % im.im.id)
 | 
					            tkinter.BitmapImage(data="PIL:%d" % im.im.id)
 | 
				
			||||||
            _pilbitmap_ok = 1
 | 
					            _pilbitmap_ok = 1
 | 
				
			||||||
        except tkinter.TclError:
 | 
					        except tkinter.TclError:
 | 
				
			||||||
            _pilbitmap_ok = 0
 | 
					            _pilbitmap_ok = 0
 | 
				
			||||||
    return _pilbitmap_ok
 | 
					    return _pilbitmap_ok
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# PhotoImage
 | 
					# PhotoImage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PhotoImage:
 | 
					class PhotoImage(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    A Tkinter-compatible photo image.  This can be used
 | 
					    A Tkinter-compatible photo image.  This can be used
 | 
				
			||||||
    everywhere Tkinter expects an image object.  If the image is an RGBA
 | 
					    everywhere Tkinter expects an image object.  If the image is an RGBA
 | 
				
			||||||
| 
						 | 
					@ -120,7 +122,6 @@ class PhotoImage:
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            pass  # ignore internal errors
 | 
					            pass  # ignore internal errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the Tkinter photo image identifier.  This method is automatically
 | 
					        Get the Tkinter photo image identifier.  This method is automatically
 | 
				
			||||||
| 
						 | 
					@ -131,7 +132,6 @@ class PhotoImage:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return str(self.__photo)
 | 
					        return str(self.__photo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def width(self):
 | 
					    def width(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the width of the image.
 | 
					        Get the width of the image.
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,6 @@ class PhotoImage:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.__size[0]
 | 
					        return self.__size[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def height(self):
 | 
					    def height(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the height of the image.
 | 
					        Get the height of the image.
 | 
				
			||||||
| 
						 | 
					@ -149,7 +148,6 @@ class PhotoImage:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.__size[1]
 | 
					        return self.__size[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def paste(self, im, box=None):
 | 
					    def paste(self, im, box=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Paste a PIL image into the photo image.  Note that this can
 | 
					        Paste a PIL image into the photo image.  Note that this can
 | 
				
			||||||
| 
						 | 
					@ -176,7 +174,7 @@ class PhotoImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            tk.call("PyImagingPhoto", self.__photo, block.id)
 | 
					            tk.call("PyImagingPhoto", self.__photo, block.id)
 | 
				
			||||||
        except tkinter.TclError as v:
 | 
					        except tkinter.TclError:
 | 
				
			||||||
            # activate Tkinter hook
 | 
					            # activate Tkinter hook
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                from PIL import _imagingtk
 | 
					                from PIL import _imagingtk
 | 
				
			||||||
| 
						 | 
					@ -192,7 +190,7 @@ class PhotoImage:
 | 
				
			||||||
# BitmapImage
 | 
					# BitmapImage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BitmapImage:
 | 
					class BitmapImage(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    A Tkinter-compatible bitmap image.  This can be used everywhere Tkinter
 | 
					    A Tkinter-compatible bitmap image.  This can be used everywhere Tkinter
 | 
				
			||||||
| 
						 | 
					@ -240,7 +238,6 @@ class BitmapImage:
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            pass  # ignore internal errors
 | 
					            pass  # ignore internal errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def width(self):
 | 
					    def width(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the width of the image.
 | 
					        Get the width of the image.
 | 
				
			||||||
| 
						 | 
					@ -249,7 +246,6 @@ class BitmapImage:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.__size[0]
 | 
					        return self.__size[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def height(self):
 | 
					    def height(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the height of the image.
 | 
					        Get the height of the image.
 | 
				
			||||||
| 
						 | 
					@ -258,7 +254,6 @@ class BitmapImage:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.__size[1]
 | 
					        return self.__size[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the Tkinter bitmap image identifier.  This method is automatically
 | 
					        Get the Tkinter bitmap image identifier.  This method is automatically
 | 
				
			||||||
| 
						 | 
					@ -274,6 +269,7 @@ def getimage(photo):
 | 
				
			||||||
    """Copies the contents of a PhotoImage to a PIL image memory."""
 | 
					    """Copies the contents of a PhotoImage to a PIL image memory."""
 | 
				
			||||||
    photo.tk.call("PyImagingPhotoGet", photo)
 | 
					    photo.tk.call("PyImagingPhotoGet", photo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Helper for the Image.show method.
 | 
					# Helper for the Image.show method.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,16 +15,20 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Transform(Image.ImageTransformHandler):
 | 
					class Transform(Image.ImageTransformHandler):
 | 
				
			||||||
    def __init__(self, data):
 | 
					    def __init__(self, data):
 | 
				
			||||||
        self.data = data
 | 
					        self.data = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getdata(self):
 | 
					    def getdata(self):
 | 
				
			||||||
        return self.method, self.data
 | 
					        return self.method, self.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def transform(self, size, image, **options):
 | 
					    def transform(self, size, image, **options):
 | 
				
			||||||
        # can be overridden
 | 
					        # can be overridden
 | 
				
			||||||
        method, data = self.getdata()
 | 
					        method, data = self.getdata()
 | 
				
			||||||
        return image.transform(size, method, data, **options)
 | 
					        return image.transform(size, method, data, **options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Define an affine image transform.
 | 
					# Define an affine image transform.
 | 
				
			||||||
# <p>
 | 
					# <p>
 | 
				
			||||||
| 
						 | 
					@ -43,9 +47,11 @@ class Transform(Image.ImageTransformHandler):
 | 
				
			||||||
#    the first two rows from an affine transform matrix.
 | 
					#    the first two rows from an affine transform matrix.
 | 
				
			||||||
# @see Image#Image.transform
 | 
					# @see Image#Image.transform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AffineTransform(Transform):
 | 
					class AffineTransform(Transform):
 | 
				
			||||||
    method = Image.AFFINE
 | 
					    method = Image.AFFINE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Define a transform to extract a subregion from an image.
 | 
					# Define a transform to extract a subregion from an image.
 | 
				
			||||||
# <p>
 | 
					# <p>
 | 
				
			||||||
| 
						 | 
					@ -68,6 +74,7 @@ class AffineTransform(Transform):
 | 
				
			||||||
class ExtentTransform(Transform):
 | 
					class ExtentTransform(Transform):
 | 
				
			||||||
    method = Image.EXTENT
 | 
					    method = Image.EXTENT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Define an quad image transform.
 | 
					# Define an quad image transform.
 | 
				
			||||||
# <p>
 | 
					# <p>
 | 
				
			||||||
| 
						 | 
					@ -83,6 +90,7 @@ class ExtentTransform(Transform):
 | 
				
			||||||
class QuadTransform(Transform):
 | 
					class QuadTransform(Transform):
 | 
				
			||||||
    method = Image.QUAD
 | 
					    method = Image.QUAD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Define an mesh image transform.  A mesh transform consists of one
 | 
					# Define an mesh image transform.  A mesh transform consists of one
 | 
				
			||||||
# or more individual quad transforms.
 | 
					# or more individual quad transforms.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,30 +21,33 @@ import warnings
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HDC:
 | 
					class HDC(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Wraps a HDC integer. The resulting object can be passed to the
 | 
					    Wraps an HDC integer. The resulting object can be passed to the
 | 
				
			||||||
    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
					    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
				
			||||||
    methods.
 | 
					    methods.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def __init__(self, dc):
 | 
					    def __init__(self, dc):
 | 
				
			||||||
        self.dc = dc
 | 
					        self.dc = dc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __int__(self):
 | 
					    def __int__(self):
 | 
				
			||||||
        return self.dc
 | 
					        return self.dc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HWND:
 | 
					
 | 
				
			||||||
 | 
					class HWND(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Wraps a HWND integer. The resulting object can be passed to the
 | 
					    Wraps an HWND integer. The resulting object can be passed to the
 | 
				
			||||||
    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
					    :py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
 | 
				
			||||||
    methods, instead of a DC.
 | 
					    methods, instead of a DC.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def __init__(self, wnd):
 | 
					    def __init__(self, wnd):
 | 
				
			||||||
        self.wnd = wnd
 | 
					        self.wnd = wnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __int__(self):
 | 
					    def __int__(self):
 | 
				
			||||||
        return self.wnd
 | 
					        return self.wnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Dib:
 | 
					class Dib(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    A Windows bitmap with the given mode and size.  The mode can be one of "1",
 | 
					    A Windows bitmap with the given mode and size.  The mode can be one of "1",
 | 
				
			||||||
    "L", "P", or "RGB".
 | 
					    "L", "P", or "RGB".
 | 
				
			||||||
| 
						 | 
					@ -79,13 +82,12 @@ class Dib:
 | 
				
			||||||
        if image:
 | 
					        if image:
 | 
				
			||||||
            self.paste(image)
 | 
					            self.paste(image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def expose(self, handle):
 | 
					    def expose(self, handle):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Copy the bitmap contents to a device context.
 | 
					        Copy the bitmap contents to a device context.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param handle: Device context (HDC), cast to a Python integer, or a HDC
 | 
					        :param handle: Device context (HDC), cast to a Python integer, or an
 | 
				
			||||||
                       or HWND instance.  In PythonWin, you can use the
 | 
					                       HDC or HWND instance.  In PythonWin, you can use the
 | 
				
			||||||
                       :py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
 | 
					                       :py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if isinstance(handle, HWND):
 | 
					        if isinstance(handle, HWND):
 | 
				
			||||||
| 
						 | 
					@ -109,7 +111,7 @@ class Dib:
 | 
				
			||||||
        necessary.
 | 
					        necessary.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not src:
 | 
					        if not src:
 | 
				
			||||||
            src = (0,0) + self.size
 | 
					            src = (0, 0) + self.size
 | 
				
			||||||
        if isinstance(handle, HWND):
 | 
					        if isinstance(handle, HWND):
 | 
				
			||||||
            dc = self.image.getdc(handle)
 | 
					            dc = self.image.getdc(handle)
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					@ -120,7 +122,6 @@ class Dib:
 | 
				
			||||||
            result = self.image.draw(handle, dst, src)
 | 
					            result = self.image.draw(handle, dst, src)
 | 
				
			||||||
        return result
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def query_palette(self, handle):
 | 
					    def query_palette(self, handle):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Installs the palette associated with the image in the given device
 | 
					        Installs the palette associated with the image in the given device
 | 
				
			||||||
| 
						 | 
					@ -146,7 +147,6 @@ class Dib:
 | 
				
			||||||
            result = self.image.query_palette(handle)
 | 
					            result = self.image.query_palette(handle)
 | 
				
			||||||
        return result
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def paste(self, im, box=None):
 | 
					    def paste(self, im, box=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Paste a PIL image into the bitmap image.
 | 
					        Paste a PIL image into the bitmap image.
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,6 @@ class Dib:
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.image.paste(im.im)
 | 
					            self.image.paste(im.im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def frombytes(self, buffer):
 | 
					    def frombytes(self, buffer):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Load display memory contents from byte data.
 | 
					        Load display memory contents from byte data.
 | 
				
			||||||
| 
						 | 
					@ -176,7 +175,6 @@ class Dib:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.image.frombytes(buffer)
 | 
					        return self.image.frombytes(buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def tobytes(self):
 | 
					    def tobytes(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Copy display memory contents to bytes object.
 | 
					        Copy display memory contents to bytes object.
 | 
				
			||||||
| 
						 | 
					@ -204,10 +202,11 @@ class Dib:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return self.tobytes()
 | 
					        return self.tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Create a Window with the given title size.
 | 
					# Create a Window with the given title size.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Window:
 | 
					class Window(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, title="PIL", width=None, height=None):
 | 
					    def __init__(self, title="PIL", width=None, height=None):
 | 
				
			||||||
        self.hwnd = Image.core.createwindow(
 | 
					        self.hwnd = Image.core.createwindow(
 | 
				
			||||||
| 
						 | 
					@ -235,6 +234,7 @@ class Window:
 | 
				
			||||||
    def mainloop(self):
 | 
					    def mainloop(self):
 | 
				
			||||||
        Image.core.eventloop()
 | 
					        Image.core.eventloop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Create an image window which displays the given image.
 | 
					# Create an image window which displays the given image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ from PIL import Image, ImageFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
field = re.compile(br"([a-z]*) ([^ \r\n]*)")
 | 
					field = re.compile(br"([a-z]*) ([^ \r\n]*)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for IM Tools images.
 | 
					# Image plugin for IM Tools images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +40,7 @@ class ImtImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # Quick rejection: if there's not a LF among the first
 | 
					        # Quick rejection: if there's not a LF among the first
 | 
				
			||||||
        # 100 bytes, this is (probably) not a text header.
 | 
					        # 100 bytes, this is (probably) not a text header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not b"\n" in self.fp.read(100):
 | 
					        if b"\n" not in self.fp.read(100):
 | 
				
			||||||
            raise SyntaxError("not an IM file")
 | 
					            raise SyntaxError("not an IM file")
 | 
				
			||||||
        self.fp.seek(0)
 | 
					        self.fp.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +55,7 @@ class ImtImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            if s == b'\x0C':
 | 
					            if s == b'\x0C':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # image data begins
 | 
					                # image data begins
 | 
				
			||||||
                self.tile = [("raw", (0,0)+self.size,
 | 
					                self.tile = [("raw", (0, 0)+self.size,
 | 
				
			||||||
                             self.fp.tell(),
 | 
					                             self.fp.tell(),
 | 
				
			||||||
                             (self.mode, 0, 1))]
 | 
					                             (self.mode, 0, 1))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +74,7 @@ class ImtImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                m = field.match(s)
 | 
					                m = field.match(s)
 | 
				
			||||||
                if not m:
 | 
					                if not m:
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
                k, v = m.group(1,2)
 | 
					                k, v = m.group(1, 2)
 | 
				
			||||||
                if k == "width":
 | 
					                if k == "width":
 | 
				
			||||||
                    xsize = int(v)
 | 
					                    xsize = int(v)
 | 
				
			||||||
                    self.size = xsize, ysize
 | 
					                    self.size = xsize, ysize
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,7 +222,7 @@ def getiptcinfo(im):
 | 
				
			||||||
                    offset += 2
 | 
					                    offset += 2
 | 
				
			||||||
                    # resource name (usually empty)
 | 
					                    # resource name (usually empty)
 | 
				
			||||||
                    name_len = i8(app[offset])
 | 
					                    name_len = i8(app[offset])
 | 
				
			||||||
                    name = app[offset+1:offset+1+name_len]
 | 
					                    # name = app[offset+1:offset+1+name_len]
 | 
				
			||||||
                    offset = 1 + offset + name_len
 | 
					                    offset = 1 + offset + name_len
 | 
				
			||||||
                    if offset & 1:
 | 
					                    if offset & 1:
 | 
				
			||||||
                        offset += 1
 | 
					                        offset += 1
 | 
				
			||||||
| 
						 | 
					@ -251,7 +251,7 @@ def getiptcinfo(im):
 | 
				
			||||||
        return None  # no properties
 | 
					        return None  # no properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # create an IptcImagePlugin object without initializing it
 | 
					    # create an IptcImagePlugin object without initializing it
 | 
				
			||||||
    class FakeImage:
 | 
					    class FakeImage(object):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    im = FakeImage()
 | 
					    im = FakeImage()
 | 
				
			||||||
    im.__class__ = IptcImageFile
 | 
					    im.__class__ = IptcImageFile
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,14 +12,13 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					 | 
				
			||||||
__version__ = "0.1"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from PIL import Image, ImageFile
 | 
					from PIL import Image, ImageFile
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__ = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _parse_codestream(fp):
 | 
					def _parse_codestream(fp):
 | 
				
			||||||
    """Parse the JPEG 2000 codestream to extract the size and component
 | 
					    """Parse the JPEG 2000 codestream to extract the size and component
 | 
				
			||||||
| 
						 | 
					@ -208,8 +207,8 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return (prefix[:4] == b'\xff\x4f\xff\x51'
 | 
					    return (prefix[:4] == b'\xff\x4f\xff\x51' or
 | 
				
			||||||
            or prefix[:12] == b'\x00\x00\x00\x0cjP  \x0d\x0a\x87\x0a')
 | 
					            prefix[:12] == b'\x00\x00\x00\x0cjP  \x0d\x0a\x87\x0a')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ------------------------------------------------------------
 | 
					# ------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# JPEG (JFIF) file handling
 | 
					# JPEG (JFIF) file handling
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# See "Digital Compression and Coding of Continous-Tone Still Images,
 | 
					# See "Digital Compression and Coding of Continuous-Tone Still Images,
 | 
				
			||||||
# Part 1, Requirements and Guidelines" (CCITT T.81 / ISO 10918-1)
 | 
					# Part 1, Requirements and Guidelines" (CCITT T.81 / ISO 10918-1)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# History:
 | 
					# History:
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,8 @@ def APP(self, marker):
 | 
				
			||||||
    elif marker == 0xFFE2 and s[:4] == b"MPF\0":
 | 
					    elif marker == 0xFFE2 and s[:4] == b"MPF\0":
 | 
				
			||||||
        # extract MPO information
 | 
					        # extract MPO information
 | 
				
			||||||
        self.info["mp"] = s[4:]
 | 
					        self.info["mp"] = s[4:]
 | 
				
			||||||
        # offset is current location minus buffer size plus constant header size
 | 
					        # offset is current location minus buffer size
 | 
				
			||||||
 | 
					        # plus constant header size
 | 
				
			||||||
        self.info["mpoffset"] = self.fp.tell() - n + 4
 | 
					        self.info["mpoffset"] = self.fp.tell() - n + 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -321,7 +322,8 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                    rawmode = self.mode
 | 
					                    rawmode = self.mode
 | 
				
			||||||
                    if self.mode == "CMYK":
 | 
					                    if self.mode == "CMYK":
 | 
				
			||||||
                        rawmode = "CMYK;I"  # assume adobe conventions
 | 
					                        rawmode = "CMYK;I"  # assume adobe conventions
 | 
				
			||||||
                    self.tile = [("jpeg", (0, 0) + self.size, 0, (rawmode, ""))]
 | 
					                    self.tile = [("jpeg", (0, 0) + self.size, 0,
 | 
				
			||||||
 | 
					                                 (rawmode, ""))]
 | 
				
			||||||
                    # self.__offset = self.fp.tell()
 | 
					                    # self.__offset = self.fp.tell()
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
                s = self.fp.read(1)
 | 
					                s = self.fp.read(1)
 | 
				
			||||||
| 
						 | 
					@ -353,7 +355,7 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            scale = s
 | 
					            scale = s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.tile = [(d, e, o, a)]
 | 
					        self.tile = [(d, e, o, a)]
 | 
				
			||||||
        self.decoderconfig = (scale, 1)
 | 
					        self.decoderconfig = (scale, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -452,13 +454,13 @@ def _getmp(self):
 | 
				
			||||||
        data = self.info["mp"]
 | 
					        data = self.info["mp"]
 | 
				
			||||||
    except KeyError:
 | 
					    except KeyError:
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
    file = io.BytesIO(data)
 | 
					    file_contents = io.BytesIO(data)
 | 
				
			||||||
    head = file.read(8)
 | 
					    head = file_contents.read(8)
 | 
				
			||||||
    endianness = '>' if head[:4] == b'\x4d\x4d\x00\x2a' else '<'
 | 
					    endianness = '>' if head[:4] == b'\x4d\x4d\x00\x2a' else '<'
 | 
				
			||||||
    mp = {}
 | 
					    mp = {}
 | 
				
			||||||
    # process dictionary
 | 
					    # process dictionary
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory(head)
 | 
					    info = TiffImagePlugin.ImageFileDirectory(head)
 | 
				
			||||||
    info.load(file)
 | 
					    info.load(file_contents)
 | 
				
			||||||
    for key, value in info.items():
 | 
					    for key, value in info.items():
 | 
				
			||||||
        mp[key] = _fixup(value)
 | 
					        mp[key] = _fixup(value)
 | 
				
			||||||
    # it's an error not to have a number of images
 | 
					    # it's an error not to have a number of images
 | 
				
			||||||
| 
						 | 
					@ -472,14 +474,18 @@ def _getmp(self):
 | 
				
			||||||
        for entrynum in range(0, quant):
 | 
					        for entrynum in range(0, quant):
 | 
				
			||||||
            rawmpentry = mp[0xB002][entrynum * 16:(entrynum + 1) * 16]
 | 
					            rawmpentry = mp[0xB002][entrynum * 16:(entrynum + 1) * 16]
 | 
				
			||||||
            unpackedentry = unpack('{0}LLLHH'.format(endianness), rawmpentry)
 | 
					            unpackedentry = unpack('{0}LLLHH'.format(endianness), rawmpentry)
 | 
				
			||||||
            labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1', 'EntryNo2')
 | 
					            labels = ('Attribute', 'Size', 'DataOffset', 'EntryNo1',
 | 
				
			||||||
 | 
					                      'EntryNo2')
 | 
				
			||||||
            mpentry = dict(zip(labels, unpackedentry))
 | 
					            mpentry = dict(zip(labels, unpackedentry))
 | 
				
			||||||
            mpentryattr = {
 | 
					            mpentryattr = {
 | 
				
			||||||
                'DependentParentImageFlag': bool(mpentry['Attribute'] & (1<<31)),
 | 
					                'DependentParentImageFlag': bool(mpentry['Attribute'] &
 | 
				
			||||||
                'DependentChildImageFlag': bool(mpentry['Attribute'] & (1<<30)),
 | 
					                                                 (1 << 31)),
 | 
				
			||||||
                'RepresentativeImageFlag': bool(mpentry['Attribute'] & (1<<29)),
 | 
					                'DependentChildImageFlag': bool(mpentry['Attribute'] &
 | 
				
			||||||
                'Reserved': (mpentry['Attribute'] & (3<<27)) >> 27,
 | 
					                                                (1 << 30)),
 | 
				
			||||||
                'ImageDataFormat': (mpentry['Attribute'] & (7<<24)) >> 24,
 | 
					                'RepresentativeImageFlag': bool(mpentry['Attribute'] &
 | 
				
			||||||
 | 
					                                                (1 << 29)),
 | 
				
			||||||
 | 
					                'Reserved': (mpentry['Attribute'] & (3 << 27)) >> 27,
 | 
				
			||||||
 | 
					                'ImageDataFormat': (mpentry['Attribute'] & (7 << 24)) >> 24,
 | 
				
			||||||
                'MPType': mpentry['Attribute'] & 0x00FFFFFF
 | 
					                'MPType': mpentry['Attribute'] & 0x00FFFFFF
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if mpentryattr['ImageDataFormat'] == 0:
 | 
					            if mpentryattr['ImageDataFormat'] == 0:
 | 
				
			||||||
| 
						 | 
					@ -530,8 +536,7 @@ zigzag_index = ( 0,  1,  5,  6, 14, 15, 27, 28,
 | 
				
			||||||
                21, 34, 37, 47, 50, 56, 59, 61,
 | 
					                21, 34, 37, 47, 50, 56, 59, 61,
 | 
				
			||||||
                35, 36, 48, 49, 57, 58, 62, 63)
 | 
					                35, 36, 48, 49, 57, 58, 62, 63)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
samplings = {
 | 
					samplings = {(1, 1, 1, 1, 1, 1): 0,
 | 
				
			||||||
             (1, 1, 1, 1, 1, 1): 0,
 | 
					 | 
				
			||||||
             (2, 1, 1, 1, 1, 1): 1,
 | 
					             (2, 1, 1, 1, 1, 1): 1,
 | 
				
			||||||
             (2, 2, 1, 1, 1, 1): 2,
 | 
					             (2, 2, 1, 1, 1, 1): 2,
 | 
				
			||||||
             }
 | 
					             }
 | 
				
			||||||
| 
						 | 
					@ -545,6 +550,15 @@ def convert_dict_qtables(qtables):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_sampling(im):
 | 
					def get_sampling(im):
 | 
				
			||||||
 | 
					    # There's no subsampling when image have only 1 layer
 | 
				
			||||||
 | 
					    # (grayscale images) or when they are CMYK (4 layers),
 | 
				
			||||||
 | 
					    # so set subsampling to default value.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # NOTE: currently Pillow can't encode JPEG to YCCK format.
 | 
				
			||||||
 | 
					    # If YCCK support is added in the future, subsampling code will have
 | 
				
			||||||
 | 
					    # to be updated (here and in JpegEncode.c) to deal with 4 layers.
 | 
				
			||||||
 | 
					    if not hasattr(im, 'layers') or im.layers in (1, 4):
 | 
				
			||||||
 | 
					        return -1
 | 
				
			||||||
    sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3]
 | 
					    sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3]
 | 
				
			||||||
    return samplings.get(sampling, -1)
 | 
					    return samplings.get(sampling, -1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -589,7 +603,8 @@ def _save(im, fp, filename):
 | 
				
			||||||
        subsampling = 2
 | 
					        subsampling = 2
 | 
				
			||||||
    elif subsampling == "keep":
 | 
					    elif subsampling == "keep":
 | 
				
			||||||
        if im.format != "JPEG":
 | 
					        if im.format != "JPEG":
 | 
				
			||||||
            raise ValueError("Cannot use 'keep' when original image is not a JPEG")
 | 
					            raise ValueError(
 | 
				
			||||||
 | 
					                "Cannot use 'keep' when original image is not a JPEG")
 | 
				
			||||||
        subsampling = get_sampling(im)
 | 
					        subsampling = get_sampling(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def validate_qtables(qtables):
 | 
					    def validate_qtables(qtables):
 | 
				
			||||||
| 
						 | 
					@ -623,7 +638,8 @@ def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if qtables == "keep":
 | 
					    if qtables == "keep":
 | 
				
			||||||
        if im.format != "JPEG":
 | 
					        if im.format != "JPEG":
 | 
				
			||||||
            raise ValueError("Cannot use 'keep' when original image is not a JPEG")
 | 
					            raise ValueError(
 | 
				
			||||||
 | 
					                "Cannot use 'keep' when original image is not a JPEG")
 | 
				
			||||||
        qtables = getattr(im, "quantization", None)
 | 
					        qtables = getattr(im, "quantization", None)
 | 
				
			||||||
    qtables = validate_qtables(qtables)
 | 
					    qtables = validate_qtables(qtables)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -641,7 +657,8 @@ def _save(im, fp, filename):
 | 
				
			||||||
        i = 1
 | 
					        i = 1
 | 
				
			||||||
        for marker in markers:
 | 
					        for marker in markers:
 | 
				
			||||||
            size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
 | 
					            size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
 | 
				
			||||||
            extra += b"\xFF\xE2" + size + b"ICC_PROFILE\0" + o8(i) + o8(len(markers)) + marker
 | 
					            extra += (b"\xFF\xE2" + size + b"ICC_PROFILE\0" + o8(i) +
 | 
				
			||||||
 | 
					                      o8(len(markers)) + marker)
 | 
				
			||||||
            i += 1
 | 
					            i += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # get keyword arguments
 | 
					    # get keyword arguments
 | 
				
			||||||
| 
						 | 
					@ -667,7 +684,8 @@ def _save(im, fp, filename):
 | 
				
			||||||
    # https://github.com/jdriscoll/django-imagekit/issues/50
 | 
					    # https://github.com/jdriscoll/django-imagekit/issues/50
 | 
				
			||||||
    bufsize = 0
 | 
					    bufsize = 0
 | 
				
			||||||
    if "optimize" in info or "progressive" in info or "progression" in info:
 | 
					    if "optimize" in info or "progressive" in info or "progression" in info:
 | 
				
			||||||
        if quality >= 95:
 | 
					        # keep sets quality to 0, but the actual value may be high.
 | 
				
			||||||
 | 
					        if quality >= 95 or quality == 0:
 | 
				
			||||||
            bufsize = 2 * im.size[0] * im.size[1]
 | 
					            bufsize = 2 * im.size[0] * im.size[1]
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            bufsize = im.size[0] * im.size[1]
 | 
					            bufsize = im.size[0] * im.size[1]
 | 
				
			||||||
| 
						 | 
					@ -686,7 +704,7 @@ def _save_cjpeg(im, fp, filename):
 | 
				
			||||||
    tempfile = im._dump()
 | 
					    tempfile = im._dump()
 | 
				
			||||||
    subprocess.check_call(["cjpeg", "-outfile", filename, tempfile])
 | 
					    subprocess.check_call(["cjpeg", "-outfile", filename, tempfile])
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        os.unlink(file)
 | 
					        os.unlink(tempfile)
 | 
				
			||||||
    except:
 | 
					    except:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,8 +48,8 @@ You can get the quantization tables of a JPEG with::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  im.quantization
 | 
					  im.quantization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This will return a dict with a number of arrays. You can pass this dict directly
 | 
					This will return a dict with a number of arrays. You can pass this dict
 | 
				
			||||||
as the qtables argument when saving a JPEG.
 | 
					directly as the qtables argument when saving a JPEG.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The tables format between im.quantization and quantization in presets differ in
 | 
					The tables format between im.quantization and quantization in presets differ in
 | 
				
			||||||
3 ways:
 | 
					3 ways:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,9 +21,11 @@ __version__ = "0.2"
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
from PIL import Image, ImageFile
 | 
					from PIL import Image, ImageFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(s):
 | 
					def _accept(s):
 | 
				
			||||||
    return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"
 | 
					    return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for McIdas area images.
 | 
					# Image plugin for McIdas area images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,10 +49,12 @@ class McIdasImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            mode = rawmode = "L"
 | 
					            mode = rawmode = "L"
 | 
				
			||||||
        elif w[11] == 2:
 | 
					        elif w[11] == 2:
 | 
				
			||||||
            # FIXME: add memory map support
 | 
					            # FIXME: add memory map support
 | 
				
			||||||
            mode = "I"; rawmode = "I;16B"
 | 
					            mode = "I"
 | 
				
			||||||
 | 
					            rawmode = "I;16B"
 | 
				
			||||||
        elif w[11] == 4:
 | 
					        elif w[11] == 4:
 | 
				
			||||||
            # FIXME: add memory map support
 | 
					            # FIXME: add memory map support
 | 
				
			||||||
            mode = "I"; rawmode = "I;32B"
 | 
					            mode = "I"
 | 
				
			||||||
 | 
					            rawmode = "I;32B"
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise SyntaxError("unsupported McIdas format")
 | 
					            raise SyntaxError("unsupported McIdas format")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ __version__ = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, TiffImagePlugin
 | 
					from PIL import Image, TiffImagePlugin
 | 
				
			||||||
from PIL.OleFileIO import *
 | 
					from PIL.OleFileIO import MAGIC, OleFileIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ from PIL.OleFileIO import *
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:8] == MAGIC
 | 
					    return prefix[:8] == MAGIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Microsoft's Image Composer file format.
 | 
					# Image plugin for Microsoft's Image Composer file format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,9 +54,9 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
 | 
				
			||||||
        # best way to identify MIC files, but what the... ;-)
 | 
					        # best way to identify MIC files, but what the... ;-)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.images = []
 | 
					        self.images = []
 | 
				
			||||||
        for file in self.ole.listdir():
 | 
					        for path in self.ole.listdir():
 | 
				
			||||||
            if file[1:] and file[0][-4:] == ".ACI" and file[1] == "Image":
 | 
					            if path[1:] and path[0][-4:] == ".ACI" and path[1] == "Image":
 | 
				
			||||||
                self.images.append(file)
 | 
					                self.images.append(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # if we didn't find any images, this is probably not
 | 
					        # if we didn't find any images, this is probably not
 | 
				
			||||||
        # an MIC file.
 | 
					        # an MIC file.
 | 
				
			||||||
| 
						 | 
					@ -70,6 +71,10 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.seek(0)
 | 
					        self.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return len(self.images)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,11 @@ __version__ = "0.1"
 | 
				
			||||||
from PIL import Image, ImageFile
 | 
					from PIL import Image, ImageFile
 | 
				
			||||||
from PIL._binary import i8
 | 
					from PIL._binary import i8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Bitstream parser
 | 
					# Bitstream parser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BitStream:
 | 
					class BitStream(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, fp):
 | 
					    def __init__(self, fp):
 | 
				
			||||||
        self.fp = fp
 | 
					        self.fp = fp
 | 
				
			||||||
| 
						 | 
					@ -52,6 +53,7 @@ class BitStream:
 | 
				
			||||||
        self.bits = self.bits - bits
 | 
					        self.bits = self.bits - bits
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for MPEG streams.  This plugin can identify a stream,
 | 
					# Image plugin for MPEG streams.  This plugin can identify a stream,
 | 
				
			||||||
# but it cannot read it.
 | 
					# but it cannot read it.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,13 +22,16 @@ __version__ = "0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, JpegImagePlugin
 | 
					from PIL import Image, JpegImagePlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return JpegImagePlugin._accept(prefix)
 | 
					    return JpegImagePlugin._accept(prefix)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename):
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
    # Note that we can only save the current frame at present
 | 
					    # Note that we can only save the current frame at present
 | 
				
			||||||
    return JpegImagePlugin._save(im, fp, filename)
 | 
					    return JpegImagePlugin._save(im, fp, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for MPO images.
 | 
					# Image plugin for MPO images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +45,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
 | 
				
			||||||
        JpegImagePlugin.JpegImageFile._open(self)
 | 
					        JpegImagePlugin.JpegImageFile._open(self)
 | 
				
			||||||
        self.mpinfo = self._getmp()
 | 
					        self.mpinfo = self._getmp()
 | 
				
			||||||
        self.__framecount = self.mpinfo[0xB001]
 | 
					        self.__framecount = self.mpinfo[0xB001]
 | 
				
			||||||
        self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] \
 | 
					        self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset']
 | 
				
			||||||
                            for mpent in self.mpinfo[0xB002]]
 | 
					                            for mpent in self.mpinfo[0xB002]]
 | 
				
			||||||
        self.__mpoffsets[0] = 0
 | 
					        self.__mpoffsets[0] = 0
 | 
				
			||||||
        # Note that the following assertion will only be invalid if something
 | 
					        # Note that the following assertion will only be invalid if something
 | 
				
			||||||
| 
						 | 
					@ -59,6 +62,10 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
 | 
				
			||||||
    def load_seek(self, pos):
 | 
					    def load_seek(self, pos):
 | 
				
			||||||
        self.__fp.seek(pos)
 | 
					        self.__fp.seek(pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return self.__framecount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
        if frame < 0 or frame >= self.__framecount:
 | 
					        if frame < 0 or frame >= self.__framecount:
 | 
				
			||||||
            raise EOFError("no more images in MPO file")
 | 
					            raise EOFError("no more images in MPO file")
 | 
				
			||||||
| 
						 | 
					@ -79,7 +86,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Note that since MPO shares a factory with JPEG, we do not need to do a
 | 
					# Note that since MPO shares a factory with JPEG, we do not need to do a
 | 
				
			||||||
# separate registration for it here.
 | 
					# separate registration for it here.
 | 
				
			||||||
#Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept)
 | 
					# Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept)
 | 
				
			||||||
Image.register_save("MPO", _save)
 | 
					Image.register_save("MPO", _save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image.register_extension("MPO", ".mpo")
 | 
					Image.register_extension("MPO", ".mpo")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,9 +27,11 @@ from PIL import Image, ImageFile, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i16 = _binary.i16le
 | 
					i16 = _binary.i16le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:4] in [b"DanM", b"LinS"]
 | 
					    return prefix[:4] in [b"DanM", b"LinS"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Windows MSP images.  This plugin supports both
 | 
					# Image plugin for Windows MSP images.  This plugin supports both
 | 
				
			||||||
# uncompressed (Windows 1.0).
 | 
					# uncompressed (Windows 1.0).
 | 
				
			||||||
| 
						 | 
					@ -47,25 +49,26 @@ class MspImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            raise SyntaxError("not an MSP file")
 | 
					            raise SyntaxError("not an MSP file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Header checksum
 | 
					        # Header checksum
 | 
				
			||||||
        sum = 0
 | 
					        checksum = 0
 | 
				
			||||||
        for i in range(0, 32, 2):
 | 
					        for i in range(0, 32, 2):
 | 
				
			||||||
            sum = sum ^ i16(s[i:i+2])
 | 
					            checksum = checksum ^ i16(s[i:i+2])
 | 
				
			||||||
        if sum != 0:
 | 
					        if checksum != 0:
 | 
				
			||||||
            raise SyntaxError("bad MSP checksum")
 | 
					            raise SyntaxError("bad MSP checksum")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.mode = "1"
 | 
					        self.mode = "1"
 | 
				
			||||||
        self.size = i16(s[4:]), i16(s[6:])
 | 
					        self.size = i16(s[4:]), i16(s[6:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if s[:4] == b"DanM":
 | 
					        if s[:4] == b"DanM":
 | 
				
			||||||
            self.tile = [("raw", (0,0)+self.size, 32, ("1", 0, 1))]
 | 
					            self.tile = [("raw", (0, 0)+self.size, 32, ("1", 0, 1))]
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.tile = [("msp", (0,0)+self.size, 32+2*self.size[1], None)]
 | 
					            self.tile = [("msp", (0, 0)+self.size, 32+2*self.size[1], None)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# write MSP files (uncompressed only)
 | 
					# write MSP files (uncompressed only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
o16 = _binary.o16le
 | 
					o16 = _binary.o16le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename):
 | 
					def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if im.mode != "1":
 | 
					    if im.mode != "1":
 | 
				
			||||||
| 
						 | 
					@ -80,17 +83,17 @@ def _save(im, fp, filename):
 | 
				
			||||||
    header[6], header[7] = 1, 1
 | 
					    header[6], header[7] = 1, 1
 | 
				
			||||||
    header[8], header[9] = im.size
 | 
					    header[8], header[9] = im.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sum = 0
 | 
					    checksum = 0
 | 
				
			||||||
    for h in header:
 | 
					    for h in header:
 | 
				
			||||||
        sum = sum ^ h
 | 
					        checksum = checksum ^ h
 | 
				
			||||||
    header[12] = sum # FIXME: is this the right field?
 | 
					    header[12] = checksum  # FIXME: is this the right field?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # header
 | 
					    # header
 | 
				
			||||||
    for h in header:
 | 
					    for h in header:
 | 
				
			||||||
        fp.write(o16(h))
 | 
					        fp.write(o16(h))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # image body
 | 
					    # image body
 | 
				
			||||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 32, ("1", 0, 1))])
 | 
					    ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 32, ("1", 0, 1))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# registry
 | 
					# registry
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										927
									
								
								PIL/OleFileIO.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										927
									
								
								PIL/OleFileIO.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -15,14 +15,13 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from PIL import EpsImagePlugin
 | 
					from PIL import EpsImagePlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Simple Postscript graphics interface.
 | 
					# Simple Postscript graphics interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PSDraw:
 | 
					class PSDraw(object):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Sets up printing to the given file. If **file** is omitted,
 | 
					    Sets up printing to the given file. If **file** is omitted,
 | 
				
			||||||
    :py:attr:`sys.stdout` is assumed.
 | 
					    :py:attr:`sys.stdout` is assumed.
 | 
				
			||||||
| 
						 | 
					@ -34,23 +33,29 @@ class PSDraw:
 | 
				
			||||||
            fp = sys.stdout
 | 
					            fp = sys.stdout
 | 
				
			||||||
        self.fp = fp
 | 
					        self.fp = fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def begin_document(self, id = None):
 | 
					    def _fp_write(self, to_write):
 | 
				
			||||||
 | 
					        if bytes is str:
 | 
				
			||||||
 | 
					            self.fp.write(to_write)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.fp.write(bytes(to_write, 'UTF-8'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def begin_document(self, id=None):
 | 
				
			||||||
        """Set up printing of a document. (Write Postscript DSC header.)"""
 | 
					        """Set up printing of a document. (Write Postscript DSC header.)"""
 | 
				
			||||||
        # FIXME: incomplete
 | 
					        # FIXME: incomplete
 | 
				
			||||||
        self.fp.write("%!PS-Adobe-3.0\n"
 | 
					        self._fp_write("%!PS-Adobe-3.0\n"
 | 
				
			||||||
                       "save\n"
 | 
					                       "save\n"
 | 
				
			||||||
                       "/showpage { } def\n"
 | 
					                       "/showpage { } def\n"
 | 
				
			||||||
                       "%%EndComments\n"
 | 
					                       "%%EndComments\n"
 | 
				
			||||||
                       "%%BeginDocument\n")
 | 
					                       "%%BeginDocument\n")
 | 
				
			||||||
        #self.fp.write(ERROR_PS) # debugging!
 | 
					        # self.fp_write(ERROR_PS)  # debugging!
 | 
				
			||||||
        self.fp.write(EDROFF_PS)
 | 
					        self._fp_write(EDROFF_PS)
 | 
				
			||||||
        self.fp.write(VDI_PS)
 | 
					        self._fp_write(VDI_PS)
 | 
				
			||||||
        self.fp.write("%%EndProlog\n")
 | 
					        self._fp_write("%%EndProlog\n")
 | 
				
			||||||
        self.isofont = {}
 | 
					        self.isofont = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def end_document(self):
 | 
					    def end_document(self):
 | 
				
			||||||
        """Ends printing. (Write Postscript DSC footer.)"""
 | 
					        """Ends printing. (Write Postscript DSC footer.)"""
 | 
				
			||||||
        self.fp.write("%%EndDocument\n"
 | 
					        self._fp_write("%%EndDocument\n"
 | 
				
			||||||
                       "restore showpage\n"
 | 
					                       "restore showpage\n"
 | 
				
			||||||
                       "%%End\n")
 | 
					                       "%%End\n")
 | 
				
			||||||
        if hasattr(self.fp, "flush"):
 | 
					        if hasattr(self.fp, "flush"):
 | 
				
			||||||
| 
						 | 
					@ -65,18 +70,11 @@ class PSDraw:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if font not in self.isofont:
 | 
					        if font not in self.isofont:
 | 
				
			||||||
            # reencode font
 | 
					            # reencode font
 | 
				
			||||||
            self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\
 | 
					            self._fp_write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %
 | 
				
			||||||
                           (font, font))
 | 
					                           (font, font))
 | 
				
			||||||
            self.isofont[font] = 1
 | 
					            self.isofont[font] = 1
 | 
				
			||||||
        # rough
 | 
					        # rough
 | 
				
			||||||
        self.fp.write("/F0 %d /PSDraw-%s F\n" % (size, font))
 | 
					        self._fp_write("/F0 %d /PSDraw-%s F\n" % (size, font))
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setink(self, ink):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        .. warning:: This has been in the PIL API for ages but was never implemented.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        print("*** NOT YET IMPLEMENTED ***")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def line(self, xy0, xy1):
 | 
					    def line(self, xy0, xy1):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -85,7 +83,7 @@ class PSDraw:
 | 
				
			||||||
        left corner of the page).
 | 
					        left corner of the page).
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        xy = xy0 + xy1
 | 
					        xy = xy0 + xy1
 | 
				
			||||||
        self.fp.write("%d %d %d %d Vl\n" % xy)
 | 
					        self._fp_write("%d %d %d %d Vl\n" % xy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def rectangle(self, box):
 | 
					    def rectangle(self, box):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -100,7 +98,7 @@ class PSDraw:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        %d %d M %d %d 0 Vr\n
 | 
					                        %d %d M %d %d 0 Vr\n
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self.fp.write("%d %d M %d %d 0 Vr\n" % box)
 | 
					        self._fp_write("%d %d M %d %d 0 Vr\n" % box)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def text(self, xy, text):
 | 
					    def text(self, xy, text):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -110,9 +108,9 @@ class PSDraw:
 | 
				
			||||||
        text = "\\(".join(text.split("("))
 | 
					        text = "\\(".join(text.split("("))
 | 
				
			||||||
        text = "\\)".join(text.split(")"))
 | 
					        text = "\\)".join(text.split(")"))
 | 
				
			||||||
        xy = xy + (text,)
 | 
					        xy = xy + (text,)
 | 
				
			||||||
        self.fp.write("%d %d M (%s) S\n" % xy)
 | 
					        self._fp_write("%d %d M (%s) S\n" % xy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def image(self, box, im, dpi = None):
 | 
					    def image(self, box, im, dpi=None):
 | 
				
			||||||
        """Draw a PIL image, centered in the given box."""
 | 
					        """Draw a PIL image, centered in the given box."""
 | 
				
			||||||
        # default resolution depends on mode
 | 
					        # default resolution depends on mode
 | 
				
			||||||
        if not dpi:
 | 
					        if not dpi:
 | 
				
			||||||
| 
						 | 
					@ -127,19 +125,21 @@ class PSDraw:
 | 
				
			||||||
        xmax = float(box[2] - box[0])
 | 
					        xmax = float(box[2] - box[0])
 | 
				
			||||||
        ymax = float(box[3] - box[1])
 | 
					        ymax = float(box[3] - box[1])
 | 
				
			||||||
        if x > xmax:
 | 
					        if x > xmax:
 | 
				
			||||||
            y = y * xmax / x; x = xmax
 | 
					            y = y * xmax / x
 | 
				
			||||||
 | 
					            x = xmax
 | 
				
			||||||
        if y > ymax:
 | 
					        if y > ymax:
 | 
				
			||||||
            x = x * ymax / y; y = ymax
 | 
					            x = x * ymax / y
 | 
				
			||||||
 | 
					            y = ymax
 | 
				
			||||||
        dx = (xmax - x) / 2 + box[0]
 | 
					        dx = (xmax - x) / 2 + box[0]
 | 
				
			||||||
        dy = (ymax - y) / 2 + box[1]
 | 
					        dy = (ymax - y) / 2 + box[1]
 | 
				
			||||||
        self.fp.write("gsave\n%f %f translate\n" % (dx, dy))
 | 
					        self._fp_write("gsave\n%f %f translate\n" % (dx, dy))
 | 
				
			||||||
        if (x, y) != im.size:
 | 
					        if (x, y) != im.size:
 | 
				
			||||||
            # EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
 | 
					            # EpsImagePlugin._save prints the image at (0,0,xsize,ysize)
 | 
				
			||||||
            sx = x / im.size[0]
 | 
					            sx = x / im.size[0]
 | 
				
			||||||
            sy = y / im.size[1]
 | 
					            sy = y / im.size[1]
 | 
				
			||||||
            self.fp.write("%f %f scale\n" % (sx, sy))
 | 
					            self._fp_write("%f %f scale\n" % (sx, sy))
 | 
				
			||||||
        EpsImagePlugin._save(im, self.fp, None, 0)
 | 
					        EpsImagePlugin._save(im, self.fp, None, 0)
 | 
				
			||||||
        self.fp.write("\ngrestore\n")
 | 
					        self._fp_write("\ngrestore\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Postscript driver
 | 
					# Postscript driver
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,10 +15,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL._binary import o8
 | 
					from PIL._binary import o8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# File handler for Teragon-style palette files.
 | 
					# File handler for Teragon-style palette files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PaletteFile:
 | 
					class PaletteFile(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rawmode = "RGB"
 | 
					    rawmode = "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +50,6 @@ class PaletteFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.palette = b"".join(self.palette)
 | 
					        self.palette = b"".join(self.palette)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getpalette(self):
 | 
					    def getpalette(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.palette, self.rawmode
 | 
					        return self.palette, self.rawmode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ from PIL import Image, ImageFile, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i8 = _binary.i8
 | 
					i8 = _binary.i8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for PhotoCD images.  This plugin only reads the 768x512
 | 
					# Image plugin for PhotoCD images.  This plugin only reads the 768x512
 | 
				
			||||||
# image from the file; higher resolutions are encoded in a proprietary
 | 
					# image from the file; higher resolutions are encoded in a proprietary
 | 
				
			||||||
| 
						 | 
					@ -49,26 +50,7 @@ class PcdImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.mode = "RGB"
 | 
					        self.mode = "RGB"
 | 
				
			||||||
        self.size = 768, 512  # FIXME: not correct for rotated images!
 | 
					        self.size = 768, 512  # FIXME: not correct for rotated images!
 | 
				
			||||||
        self.tile = [("pcd", (0,0)+self.size, 96*2048, None)]
 | 
					        self.tile = [("pcd", (0, 0)+self.size, 96*2048, None)]
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def draft(self, mode, size):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if len(self.tile) != 1:
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        d, e, o, a = self.tile[0]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if size:
 | 
					 | 
				
			||||||
            scale = max(self.size[0] / size[0], self.size[1] / size[1])
 | 
					 | 
				
			||||||
            for s, o in [(4,0*2048), (2,0*2048), (1,96*2048)]:
 | 
					 | 
				
			||||||
                if scale >= s:
 | 
					 | 
				
			||||||
                    break
 | 
					 | 
				
			||||||
            # e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
 | 
					 | 
				
			||||||
            # self.size = ((self.size[0]+s-1)/s, (self.size[1]+s-1)/s)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.tile = [(d, e, o, a)]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return self
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# registry
 | 
					# registry
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,15 +25,15 @@ from PIL import _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PCF_MAGIC = 0x70636601  # "\x01fcp"
 | 
					PCF_MAGIC = 0x70636601  # "\x01fcp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PCF_PROPERTIES = (1<<0)
 | 
					PCF_PROPERTIES = (1 << 0)
 | 
				
			||||||
PCF_ACCELERATORS = (1<<1)
 | 
					PCF_ACCELERATORS = (1 << 1)
 | 
				
			||||||
PCF_METRICS = (1<<2)
 | 
					PCF_METRICS = (1 << 2)
 | 
				
			||||||
PCF_BITMAPS = (1<<3)
 | 
					PCF_BITMAPS = (1 << 3)
 | 
				
			||||||
PCF_INK_METRICS = (1<<4)
 | 
					PCF_INK_METRICS = (1 << 4)
 | 
				
			||||||
PCF_BDF_ENCODINGS = (1<<5)
 | 
					PCF_BDF_ENCODINGS = (1 << 5)
 | 
				
			||||||
PCF_SWIDTHS = (1<<6)
 | 
					PCF_SWIDTHS = (1 << 6)
 | 
				
			||||||
PCF_GLYPH_NAMES = (1<<7)
 | 
					PCF_GLYPH_NAMES = (1 << 7)
 | 
				
			||||||
PCF_BDF_ACCELERATORS = (1<<8)
 | 
					PCF_BDF_ACCELERATORS = (1 << 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BYTES_PER_ROW = [
 | 
					BYTES_PER_ROW = [
 | 
				
			||||||
    lambda bits: ((bits+7) >> 3),
 | 
					    lambda bits: ((bits+7) >> 3),
 | 
				
			||||||
| 
						 | 
					@ -48,9 +48,11 @@ l32 = _binary.i32le
 | 
				
			||||||
b16 = _binary.i16be
 | 
					b16 = _binary.i16be
 | 
				
			||||||
b32 = _binary.i32be
 | 
					b32 = _binary.i32be
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sz(s, o):
 | 
					def sz(s, o):
 | 
				
			||||||
    return s[o:s.index(b"\0", o)]
 | 
					    return s[o:s.index(b"\0", o)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Font file plugin for the X11 PCF format.
 | 
					# Font file plugin for the X11 PCF format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +204,7 @@ class PcfFontFile(FontFile.FontFile):
 | 
				
			||||||
        for i in range(4):
 | 
					        for i in range(4):
 | 
				
			||||||
            bitmapSizes.append(i32(fp.read(4)))
 | 
					            bitmapSizes.append(i32(fp.read(4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        byteorder = format & 4 # non-zero => MSB
 | 
					        # byteorder = format & 4  # non-zero => MSB
 | 
				
			||||||
        bitorder = format & 8   # non-zero => MSB
 | 
					        bitorder = format & 8   # non-zero => MSB
 | 
				
			||||||
        padindex = format & 3
 | 
					        padindex = format & 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__version__ = "0.6"
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, ImagePalette, _binary
 | 
					from PIL import Image, ImageFile, ImagePalette, _binary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,9 +33,13 @@ i8 = _binary.i8
 | 
				
			||||||
i16 = _binary.i16le
 | 
					i16 = _binary.i16le
 | 
				
			||||||
o8 = _binary.o8
 | 
					o8 = _binary.o8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__ = "0.6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5]
 | 
					    return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Paintbrush images.
 | 
					# Image plugin for Paintbrush images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,23 +56,22 @@ class PcxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            raise SyntaxError("not a PCX file")
 | 
					            raise SyntaxError("not a PCX file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # image
 | 
					        # image
 | 
				
			||||||
        bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
 | 
					        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]:
 | 
					        if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
 | 
				
			||||||
            raise SyntaxError("bad PCX image size")
 | 
					            raise SyntaxError("bad PCX image size")
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print ("BBox: %s %s %s %s" % bbox)
 | 
					            print("BBox: %s %s %s %s" % bbox)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # format
 | 
					        # format
 | 
				
			||||||
        version = i8(s[1])
 | 
					        version = i8(s[1])
 | 
				
			||||||
        bits = i8(s[3])
 | 
					        bits = i8(s[3])
 | 
				
			||||||
        planes = i8(s[65])
 | 
					        planes = i8(s[65])
 | 
				
			||||||
        stride = i16(s,66)
 | 
					        stride = i16(s, 66)
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print ("PCX version %s, bits %s, planes %s, stride %s" %
 | 
					            print("PCX version %s, bits %s, planes %s, stride %s" %
 | 
				
			||||||
                  (version, bits, planes, stride))
 | 
					                  (version, bits, planes, stride))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.info["dpi"] = i16(s,12), i16(s,14)
 | 
					        self.info["dpi"] = i16(s, 12), i16(s, 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if bits == 1 and planes == 1:
 | 
					        if bits == 1 and planes == 1:
 | 
				
			||||||
            mode = rawmode = "1"
 | 
					            mode = rawmode = "1"
 | 
				
			||||||
| 
						 | 
					@ -105,7 +108,7 @@ class PcxImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bbox = (0, 0) + self.size
 | 
					        bbox = (0, 0) + self.size
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print ("size: %sx%s" % self.size)
 | 
					            print("size: %sx%s" % self.size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
 | 
					        self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,6 +125,7 @@ SAVE = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
o16 = _binary.o16le
 | 
					o16 = _binary.o16le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename, check=0):
 | 
					def _save(im, fp, filename, check=0):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -140,9 +144,8 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    # Ideally it should be passed in in the state, but the bytes value
 | 
					    # Ideally it should be passed in in the state, but the bytes value
 | 
				
			||||||
    # gets overwritten.
 | 
					    # gets overwritten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if Image.DEBUG:
 | 
					    if Image.DEBUG:
 | 
				
			||||||
        print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
 | 
					        print("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
 | 
				
			||||||
            im.size[0], bits, stride))
 | 
					            im.size[0], bits, stride))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # under windows, we could determine the current screen size with
 | 
					    # under windows, we could determine the current screen size with
 | 
				
			||||||
| 
						 | 
					@ -163,7 +166,7 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert fp.tell() == 128
 | 
					    assert fp.tell() == 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
 | 
					    ImageFile._save(im, fp, [("pcx", (0, 0)+im.size, 0,
 | 
				
			||||||
                              (rawmode, bits*planes))])
 | 
					                              (rawmode, bits*planes))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if im.mode == "P":
 | 
					    if im.mode == "P":
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xref = [0]*(5+1)  # placeholders
 | 
					    xref = [0]*(5+1)  # placeholders
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class TextWriter:
 | 
					    class TextWriter(object):
 | 
				
			||||||
        def __init__(self, fp):
 | 
					        def __init__(self, fp):
 | 
				
			||||||
            self.fp = fp
 | 
					            self.fp = fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ from PIL import Image, ImageFile, _binary
 | 
				
			||||||
i16 = _binary.i16le
 | 
					i16 = _binary.i16le
 | 
				
			||||||
i32 = _binary.i32le
 | 
					i32 = _binary.i32le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for PIXAR raster images.
 | 
					# Image plugin for PIXAR raster images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +58,7 @@ class PixarImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # FIXME: to be continued...
 | 
					        # FIXME: to be continued...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # create tile descriptor (assuming "dumped")
 | 
					        # create tile descriptor (assuming "dumped")
 | 
				
			||||||
        self.tile = [("raw", (0,0)+self.size, 1024, (self.mode, 0, 1))]
 | 
					        self.tile = [("raw", (0, 0)+self.size, 1024, (self.mode, 0, 1))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,26 +56,42 @@ _MODES = {
 | 
				
			||||||
    (2, 0):  ("L", "L;2"),
 | 
					    (2, 0):  ("L", "L;2"),
 | 
				
			||||||
    (4, 0):  ("L", "L;4"),
 | 
					    (4, 0):  ("L", "L;4"),
 | 
				
			||||||
    (8, 0):  ("L", "L"),
 | 
					    (8, 0):  ("L", "L"),
 | 
				
			||||||
    (16,0): ("I", "I;16B"),
 | 
					    (16, 0): ("I", "I;16B"),
 | 
				
			||||||
    (8, 2):  ("RGB", "RGB"),
 | 
					    (8, 2):  ("RGB", "RGB"),
 | 
				
			||||||
    (16,2): ("RGB", "RGB;16B"),
 | 
					    (16, 2): ("RGB", "RGB;16B"),
 | 
				
			||||||
    (1, 3):  ("P", "P;1"),
 | 
					    (1, 3):  ("P", "P;1"),
 | 
				
			||||||
    (2, 3):  ("P", "P;2"),
 | 
					    (2, 3):  ("P", "P;2"),
 | 
				
			||||||
    (4, 3):  ("P", "P;4"),
 | 
					    (4, 3):  ("P", "P;4"),
 | 
				
			||||||
    (8, 3):  ("P", "P"),
 | 
					    (8, 3):  ("P", "P"),
 | 
				
			||||||
    (8, 4):  ("LA", "LA"),
 | 
					    (8, 4):  ("LA", "LA"),
 | 
				
			||||||
    (16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
 | 
					    (16, 4): ("RGBA", "LA;16B"),  # LA;16B->LA not yet available
 | 
				
			||||||
    (8, 6):  ("RGBA", "RGBA"),
 | 
					    (8, 6):  ("RGBA", "RGBA"),
 | 
				
			||||||
    (16,6): ("RGBA", "RGBA;16B"),
 | 
					    (16, 6): ("RGBA", "RGBA;16B"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_simple_palette = re.compile(b'^\xff+\x00\xff*$')
 | 
					_simple_palette = re.compile(b'^\xff+\x00\xff*$')
 | 
				
			||||||
 | 
					_null_palette = re.compile(b'^\x00*$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Maximum decompressed size for a iTXt or zTXt chunk.
 | 
				
			||||||
 | 
					# Eliminates decompression bombs where compressed chunks can expand 1000x
 | 
				
			||||||
 | 
					MAX_TEXT_CHUNK = ImageFile.SAFEBLOCK
 | 
				
			||||||
 | 
					# Set the maximum total text chunk size.
 | 
				
			||||||
 | 
					MAX_TEXT_MEMORY = 64 * MAX_TEXT_CHUNK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _safe_zlib_decompress(s):
 | 
				
			||||||
 | 
					    dobj = zlib.decompressobj()
 | 
				
			||||||
 | 
					    plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
 | 
				
			||||||
 | 
					    if dobj.unconsumed_tail:
 | 
				
			||||||
 | 
					        raise ValueError("Decompressed Data Too Large")
 | 
				
			||||||
 | 
					    return plaintext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Support classes.  Suitable for PNG and related formats like MNG etc.
 | 
					# Support classes.  Suitable for PNG and related formats like MNG etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChunkStream:
 | 
					class ChunkStream(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, fp):
 | 
					    def __init__(self, fp):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,7 +139,7 @@ class ChunkStream:
 | 
				
			||||||
        crc1 = Image.core.crc32(data, Image.core.crc32(cid))
 | 
					        crc1 = Image.core.crc32(data, Image.core.crc32(cid))
 | 
				
			||||||
        crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
 | 
					        crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
 | 
				
			||||||
        if crc1 != crc2:
 | 
					        if crc1 != crc2:
 | 
				
			||||||
            raise SyntaxError("broken PNG file"\
 | 
					            raise SyntaxError("broken PNG file"
 | 
				
			||||||
                              "(bad header checksum in %s)" % cid)
 | 
					                              "(bad header checksum in %s)" % cid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def crc_skip(self, cid, data):
 | 
					    def crc_skip(self, cid, data):
 | 
				
			||||||
| 
						 | 
					@ -131,7 +147,7 @@ class ChunkStream:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.fp.read(4)
 | 
					        self.fp.read(4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def verify(self, endchunk = b"IEND"):
 | 
					    def verify(self, endchunk=b"IEND"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Simple approach; just calculate checksum for all remaining
 | 
					        # Simple approach; just calculate checksum for all remaining
 | 
				
			||||||
        # blocks.  Must be called directly after open.
 | 
					        # blocks.  Must be called directly after open.
 | 
				
			||||||
| 
						 | 
					@ -147,30 +163,57 @@ class ChunkStream:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return cids
 | 
					        return cids
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					 | 
				
			||||||
# Subclass of string to allow iTXt chunks to look like strings while
 | 
					 | 
				
			||||||
# keeping their extra information
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class iTXt(str):
 | 
					class iTXt(str):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Subclass of string to allow iTXt chunks to look like strings while
 | 
				
			||||||
 | 
					    keeping their extra information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def __new__(cls, text, lang, tkey):
 | 
					    def __new__(cls, text, lang, tkey):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        :param value: value for this key
 | 
				
			||||||
 | 
					        :param lang: language code
 | 
				
			||||||
 | 
					        :param tkey: UTF-8 version of the key name
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self = str.__new__(cls, text)
 | 
					        self = str.__new__(cls, text)
 | 
				
			||||||
        self.lang = lang
 | 
					        self.lang = lang
 | 
				
			||||||
        self.tkey = tkey
 | 
					        self.tkey = tkey
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					 | 
				
			||||||
# PNG chunk container (for use with save(pnginfo=))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PngInfo:
 | 
					class PngInfo(object):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    PNG chunk container (for use with save(pnginfo=))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self.chunks = []
 | 
					        self.chunks = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, cid, data):
 | 
					    def add(self, cid, data):
 | 
				
			||||||
 | 
					        """Appends an arbitrary chunk. Use with caution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param cid: a byte string, 4 bytes long.
 | 
				
			||||||
 | 
					        :param data: a byte string of the encoded data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.chunks.append((cid, data))
 | 
					        self.chunks.append((cid, data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_itxt(self, key, value, lang="", tkey="", zip=False):
 | 
					    def add_itxt(self, key, value, lang="", tkey="", zip=False):
 | 
				
			||||||
 | 
					        """Appends an iTXt chunk.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param key: latin-1 encodable text key name
 | 
				
			||||||
 | 
					        :param value: value for this key
 | 
				
			||||||
 | 
					        :param lang: language code
 | 
				
			||||||
 | 
					        :param tkey: UTF-8 version of the key name
 | 
				
			||||||
 | 
					        :param zip: compression flag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not isinstance(key, bytes):
 | 
					        if not isinstance(key, bytes):
 | 
				
			||||||
            key = key.encode("latin-1", "strict")
 | 
					            key = key.encode("latin-1", "strict")
 | 
				
			||||||
        if not isinstance(value, bytes):
 | 
					        if not isinstance(value, bytes):
 | 
				
			||||||
| 
						 | 
					@ -181,12 +224,21 @@ class PngInfo:
 | 
				
			||||||
            tkey = tkey.encode("utf-8", "strict")
 | 
					            tkey = tkey.encode("utf-8", "strict")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if zip:
 | 
					        if zip:
 | 
				
			||||||
            import zlib
 | 
					            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" +
 | 
				
			||||||
            self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" + zlib.compress(value))
 | 
					                     zlib.compress(value))
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" + value)
 | 
					            self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" +
 | 
				
			||||||
 | 
					                     value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_text(self, key, value, zip=0):
 | 
					    def add_text(self, key, value, zip=0):
 | 
				
			||||||
 | 
					        """Appends a text chunk.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param key: latin-1 encodable text key name
 | 
				
			||||||
 | 
					        :param value: value for this key, text or an
 | 
				
			||||||
 | 
					           :py:class:`PIL.PngImagePlugin.iTXt` instance
 | 
				
			||||||
 | 
					        :param zip: compression flag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        if isinstance(value, iTXt):
 | 
					        if isinstance(value, iTXt):
 | 
				
			||||||
            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))
 | 
					            return self.add_itxt(key, value, value.lang, value.tkey, bool(zip))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,11 +253,11 @@ class PngInfo:
 | 
				
			||||||
            key = key.encode('latin-1', 'strict')
 | 
					            key = key.encode('latin-1', 'strict')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if zip:
 | 
					        if zip:
 | 
				
			||||||
            import zlib
 | 
					 | 
				
			||||||
            self.add(b"zTXt", key + b"\0\0" + zlib.compress(value))
 | 
					            self.add(b"zTXt", key + b"\0\0" + zlib.compress(value))
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.add(b"tEXt", key + b"\0" + value)
 | 
					            self.add(b"tEXt", key + b"\0" + value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# PNG image stream (IHDR/IEND)
 | 
					# PNG image stream (IHDR/IEND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,11 +270,19 @@ class PngStream(ChunkStream):
 | 
				
			||||||
        # local copies of Image attributes
 | 
					        # local copies of Image attributes
 | 
				
			||||||
        self.im_info = {}
 | 
					        self.im_info = {}
 | 
				
			||||||
        self.im_text = {}
 | 
					        self.im_text = {}
 | 
				
			||||||
        self.im_size = (0,0)
 | 
					        self.im_size = (0, 0)
 | 
				
			||||||
        self.im_mode = None
 | 
					        self.im_mode = None
 | 
				
			||||||
        self.im_tile = None
 | 
					        self.im_tile = None
 | 
				
			||||||
        self.im_palette = None
 | 
					        self.im_palette = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.text_memory = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def check_text_memory(self, chunklen):
 | 
				
			||||||
 | 
					        self.text_memory += chunklen
 | 
				
			||||||
 | 
					        if self.text_memory > MAX_TEXT_MEMORY:
 | 
				
			||||||
 | 
					            raise ValueError("Too much memory used in text chunks: %s>MAX_TEXT_MEMORY" %
 | 
				
			||||||
 | 
					                             self.text_memory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def chunk_iCCP(self, pos, length):
 | 
					    def chunk_iCCP(self, pos, length):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # ICC profile
 | 
					        # ICC profile
 | 
				
			||||||
| 
						 | 
					@ -238,9 +298,10 @@ class PngStream(ChunkStream):
 | 
				
			||||||
            print("Compression method", i8(s[i]))
 | 
					            print("Compression method", i8(s[i]))
 | 
				
			||||||
        comp_method = i8(s[i])
 | 
					        comp_method = i8(s[i])
 | 
				
			||||||
        if comp_method != 0:
 | 
					        if comp_method != 0:
 | 
				
			||||||
            raise SyntaxError("Unknown compression method %s in iCCP chunk" % comp_method)
 | 
					            raise SyntaxError("Unknown compression method %s in iCCP chunk" %
 | 
				
			||||||
 | 
					                              comp_method)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            icc_profile = zlib.decompress(s[i+2:])
 | 
					            icc_profile = _safe_zlib_decompress(s[i+2:])
 | 
				
			||||||
        except zlib.error:
 | 
					        except zlib.error:
 | 
				
			||||||
            icc_profile = None  # FIXME
 | 
					            icc_profile = None  # FIXME
 | 
				
			||||||
        self.im_info["icc_profile"] = icc_profile
 | 
					        self.im_info["icc_profile"] = icc_profile
 | 
				
			||||||
| 
						 | 
					@ -264,7 +325,7 @@ class PngStream(ChunkStream):
 | 
				
			||||||
    def chunk_IDAT(self, pos, length):
 | 
					    def chunk_IDAT(self, pos, length):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # image data
 | 
					        # image data
 | 
				
			||||||
        self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)]
 | 
					        self.im_tile = [("zip", (0, 0)+self.im_size, pos, self.im_rawmode)]
 | 
				
			||||||
        self.im_idat = length
 | 
					        self.im_idat = length
 | 
				
			||||||
        raise EOFError
 | 
					        raise EOFError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,6 +351,8 @@ class PngStream(ChunkStream):
 | 
				
			||||||
                i = s.find(b"\0")
 | 
					                i = s.find(b"\0")
 | 
				
			||||||
                if i >= 0:
 | 
					                if i >= 0:
 | 
				
			||||||
                    self.im_info["transparency"] = i
 | 
					                    self.im_info["transparency"] = i
 | 
				
			||||||
 | 
					            elif _null_palette.match(s):
 | 
				
			||||||
 | 
					                self.im_info["transparency"] = 0
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                self.im_info["transparency"] = s
 | 
					                self.im_info["transparency"] = s
 | 
				
			||||||
        elif self.im_mode == "L":
 | 
					        elif self.im_mode == "L":
 | 
				
			||||||
| 
						 | 
					@ -325,13 +388,17 @@ class PngStream(ChunkStream):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            k, v = s.split(b"\0", 1)
 | 
					            k, v = s.split(b"\0", 1)
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            k = s; v = b"" # fallback for broken tEXt tags
 | 
					            # fallback for broken tEXt tags
 | 
				
			||||||
 | 
					            k = s
 | 
				
			||||||
 | 
					            v = b""
 | 
				
			||||||
        if k:
 | 
					        if k:
 | 
				
			||||||
            if bytes is not str:
 | 
					            if bytes is not str:
 | 
				
			||||||
                k = k.decode('latin-1', 'strict')
 | 
					                k = k.decode('latin-1', 'strict')
 | 
				
			||||||
                v = v.decode('latin-1', 'replace')
 | 
					                v = v.decode('latin-1', 'replace')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.im_info[k] = self.im_text[k] = v
 | 
					            self.im_info[k] = self.im_text[k] = v
 | 
				
			||||||
 | 
					            self.check_text_memory(len(v))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return s
 | 
					        return s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def chunk_zTXt(self, pos, length):
 | 
					    def chunk_zTXt(self, pos, length):
 | 
				
			||||||
| 
						 | 
					@ -341,16 +408,17 @@ class PngStream(ChunkStream):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            k, v = s.split(b"\0", 1)
 | 
					            k, v = s.split(b"\0", 1)
 | 
				
			||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            k = s; v = b""
 | 
					            k = s
 | 
				
			||||||
 | 
					            v = b""
 | 
				
			||||||
        if v:
 | 
					        if v:
 | 
				
			||||||
            comp_method = i8(v[0])
 | 
					            comp_method = i8(v[0])
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            comp_method = 0
 | 
					            comp_method = 0
 | 
				
			||||||
        if comp_method != 0:
 | 
					        if comp_method != 0:
 | 
				
			||||||
            raise SyntaxError("Unknown compression method %s in zTXt chunk" % comp_method)
 | 
					            raise SyntaxError("Unknown compression method %s in zTXt chunk" %
 | 
				
			||||||
        import zlib
 | 
					                              comp_method)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            v = zlib.decompress(v[1:])
 | 
					            v = _safe_zlib_decompress(v[1:])
 | 
				
			||||||
        except zlib.error:
 | 
					        except zlib.error:
 | 
				
			||||||
            v = b""
 | 
					            v = b""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,6 +428,8 @@ class PngStream(ChunkStream):
 | 
				
			||||||
                v = v.decode('latin-1', 'replace')
 | 
					                v = v.decode('latin-1', 'replace')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.im_info[k] = self.im_text[k] = v
 | 
					            self.im_info[k] = self.im_text[k] = v
 | 
				
			||||||
 | 
					            self.check_text_memory(len(v))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return s
 | 
					        return s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def chunk_iTXt(self, pos, length):
 | 
					    def chunk_iTXt(self, pos, length):
 | 
				
			||||||
| 
						 | 
					@ -379,9 +449,8 @@ class PngStream(ChunkStream):
 | 
				
			||||||
            return s
 | 
					            return s
 | 
				
			||||||
        if cf != 0:
 | 
					        if cf != 0:
 | 
				
			||||||
            if cm == 0:
 | 
					            if cm == 0:
 | 
				
			||||||
                import zlib
 | 
					 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    v = zlib.decompress(v)
 | 
					                    v = _safe_zlib_decompress(v)
 | 
				
			||||||
                except zlib.error:
 | 
					                except zlib.error:
 | 
				
			||||||
                    return s
 | 
					                    return s
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
| 
						 | 
					@ -396,15 +465,18 @@ class PngStream(ChunkStream):
 | 
				
			||||||
                return s
 | 
					                return s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)
 | 
					        self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)
 | 
				
			||||||
 | 
					        self.check_text_memory(len(v))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return s
 | 
					        return s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# PNG reader
 | 
					# PNG reader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:8] == _MAGIC
 | 
					    return prefix[:8] == _MAGIC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for PNG images.
 | 
					# Image plugin for PNG images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -460,7 +532,6 @@ class PngImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__idat = length  # used by load_read()
 | 
					        self.__idat = length  # used by load_read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def verify(self):
 | 
					    def verify(self):
 | 
				
			||||||
        "Verify PNG file"
 | 
					        "Verify PNG file"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -509,7 +580,6 @@ class PngImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.fp.read(read_bytes)
 | 
					        return self.fp.read(read_bytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def load_end(self):
 | 
					    def load_end(self):
 | 
				
			||||||
        "internal: finished reading image data"
 | 
					        "internal: finished reading image data"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -538,9 +608,10 @@ _OUTMODES = {
 | 
				
			||||||
    "P;4":  ("P;4",     b'\x04\x03'),
 | 
					    "P;4":  ("P;4",     b'\x04\x03'),
 | 
				
			||||||
    "P":    ("P",       b'\x08\x03'),
 | 
					    "P":    ("P",       b'\x08\x03'),
 | 
				
			||||||
    "RGB":  ("RGB",     b'\x08\x02'),
 | 
					    "RGB":  ("RGB",     b'\x08\x02'),
 | 
				
			||||||
    "RGBA":("RGBA",    b'\x08\x06'),
 | 
					    "RGBA": ("RGBA",    b'\x08\x06'),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def putchunk(fp, cid, *data):
 | 
					def putchunk(fp, cid, *data):
 | 
				
			||||||
    "Write a PNG chunk (including CRC field)"
 | 
					    "Write a PNG chunk (including CRC field)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -551,15 +622,18 @@ def putchunk(fp, cid, *data):
 | 
				
			||||||
    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
 | 
					    hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
 | 
				
			||||||
    fp.write(o16(hi) + o16(lo))
 | 
					    fp.write(o16(hi) + o16(lo))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _idat:
 | 
					
 | 
				
			||||||
 | 
					class _idat(object):
 | 
				
			||||||
    # wrap output from the encoder in IDAT chunks
 | 
					    # wrap output from the encoder in IDAT chunks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, fp, chunk):
 | 
					    def __init__(self, fp, chunk):
 | 
				
			||||||
        self.fp = fp
 | 
					        self.fp = fp
 | 
				
			||||||
        self.chunk = chunk
 | 
					        self.chunk = chunk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def write(self, data):
 | 
					    def write(self, data):
 | 
				
			||||||
        self.chunk(self.fp, b"IDAT", data)
 | 
					        self.chunk(self.fp, b"IDAT", data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
					def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
				
			||||||
    # save an image to disk (called by the save method)
 | 
					    # save an image to disk (called by the save method)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -629,7 +703,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
				
			||||||
            palette_bytes += b'\0'
 | 
					            palette_bytes += b'\0'
 | 
				
			||||||
        chunk(fp, b"PLTE", palette_bytes)
 | 
					        chunk(fp, b"PLTE", palette_bytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))
 | 
					    transparency = im.encoderinfo.get('transparency',
 | 
				
			||||||
 | 
					                                      im.info.get('transparency', None))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if transparency or transparency == 0:
 | 
					    if transparency or transparency == 0:
 | 
				
			||||||
        if im.mode == "P":
 | 
					        if im.mode == "P":
 | 
				
			||||||
| 
						 | 
					@ -658,10 +733,6 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
				
			||||||
            alpha_bytes = 2**bits
 | 
					            alpha_bytes = 2**bits
 | 
				
			||||||
            chunk(fp, b"tRNS", alpha[:alpha_bytes])
 | 
					            chunk(fp, b"tRNS", alpha[:alpha_bytes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if 0:
 | 
					 | 
				
			||||||
        # FIXME: to be supported some day
 | 
					 | 
				
			||||||
        chunk(fp, b"gAMA", o32(int(gamma * 100000.0)))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dpi = im.encoderinfo.get("dpi")
 | 
					    dpi = im.encoderinfo.get("dpi")
 | 
				
			||||||
    if dpi:
 | 
					    if dpi:
 | 
				
			||||||
        chunk(fp, b"pHYs",
 | 
					        chunk(fp, b"pHYs",
 | 
				
			||||||
| 
						 | 
					@ -686,7 +757,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
				
			||||||
        data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
 | 
					        data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
 | 
				
			||||||
        chunk(fp, b"iCCP", data)
 | 
					        chunk(fp, b"iCCP", data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])
 | 
					    ImageFile._save(im, _idat(fp, chunk),
 | 
				
			||||||
 | 
					                    [("zip", (0, 0)+im.size, 0, rawmode)])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chunk(fp, b"IEND", b"")
 | 
					    chunk(fp, b"IEND", b"")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -702,10 +774,12 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 | 
				
			||||||
def getchunks(im, **params):
 | 
					def getchunks(im, **params):
 | 
				
			||||||
    """Return a list of PNG chunks representing this image."""
 | 
					    """Return a list of PNG chunks representing this image."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class collector:
 | 
					    class collector(object):
 | 
				
			||||||
        data = []
 | 
					        data = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def write(self, data):
 | 
					        def write(self, data):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def append(self, chunk):
 | 
					        def append(self, chunk):
 | 
				
			||||||
            self.data.append(chunk)
 | 
					            self.data.append(chunk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,12 +27,13 @@ from PIL import Image, ImageFile
 | 
				
			||||||
b_whitespace = string.whitespace
 | 
					b_whitespace = string.whitespace
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    import locale
 | 
					    import locale
 | 
				
			||||||
    locale_lang,locale_enc = locale.getlocale()
 | 
					    locale_lang, locale_enc = locale.getlocale()
 | 
				
			||||||
    if locale_enc is None:
 | 
					    if locale_enc is None:
 | 
				
			||||||
        locale_lang,locale_enc = locale.getdefaultlocale() 
 | 
					        locale_lang, locale_enc = locale.getdefaultlocale()
 | 
				
			||||||
    b_whitespace = b_whitespace.decode(locale_enc)
 | 
					    b_whitespace = b_whitespace.decode(locale_enc)
 | 
				
			||||||
except: pass
 | 
					except:
 | 
				
			||||||
b_whitespace = b_whitespace.encode('ascii','ignore')
 | 
					    pass
 | 
				
			||||||
 | 
					b_whitespace = b_whitespace.encode('ascii', 'ignore')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODES = {
 | 
					MODES = {
 | 
				
			||||||
    # standard
 | 
					    # standard
 | 
				
			||||||
| 
						 | 
					@ -47,9 +48,11 @@ MODES = {
 | 
				
			||||||
    b"PyCMYK": "CMYK"
 | 
					    b"PyCMYK": "CMYK"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[0:1] == b"P" and prefix[1] in b"0456y"
 | 
					    return prefix[0:1] == b"P" and prefix[1] in b"0456y"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for PBM, PGM, and PPM images.
 | 
					# Image plugin for PBM, PGM, and PPM images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +61,7 @@ class PpmImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    format = "PPM"
 | 
					    format = "PPM"
 | 
				
			||||||
    format_description = "Pbmplus image"
 | 
					    format_description = "Pbmplus image"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _token(self, s = b""):
 | 
					    def _token(self, s=b""):
 | 
				
			||||||
        while True:  # read until next whitespace
 | 
					        while True:  # read until next whitespace
 | 
				
			||||||
            c = self.fp.read(1)
 | 
					            c = self.fp.read(1)
 | 
				
			||||||
            if not c or c in b_whitespace:
 | 
					            if not c or c in b_whitespace:
 | 
				
			||||||
| 
						 | 
					@ -104,12 +107,12 @@ class PpmImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                # maxgrey
 | 
					                # maxgrey
 | 
				
			||||||
                if s > 255:
 | 
					                if s > 255:
 | 
				
			||||||
                    if not mode == 'L':
 | 
					                    if not mode == 'L':
 | 
				
			||||||
                        raise ValueError("Too many colors for band: %s" %s)
 | 
					                        raise ValueError("Too many colors for band: %s" % s)
 | 
				
			||||||
                    if s < 2**16:
 | 
					                    if s < 2**16:
 | 
				
			||||||
                        self.mode = 'I'
 | 
					                        self.mode = 'I'
 | 
				
			||||||
                        rawmode = 'I;16B'
 | 
					                        rawmode = 'I;16B'
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        self.mode = 'I';
 | 
					                        self.mode = 'I'
 | 
				
			||||||
                        rawmode = 'I;32B'
 | 
					                        rawmode = 'I;32B'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.size = xsize, ysize
 | 
					        self.size = xsize, ysize
 | 
				
			||||||
| 
						 | 
					@ -123,6 +126,7 @@ class PpmImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # self.mode = self.im.mode
 | 
					        # self.mode = self.im.mode
 | 
				
			||||||
        # self.size = self.im.size
 | 
					        # self.size = self.im.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,7 +156,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
            fp.write(b"65535\n")
 | 
					            fp.write(b"65535\n")
 | 
				
			||||||
        elif rawmode == "I;32B":
 | 
					        elif rawmode == "I;32B":
 | 
				
			||||||
            fp.write(b"2147483648\n")
 | 
					            fp.write(b"2147483648\n")
 | 
				
			||||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
 | 
					    ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, 1))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # ALTERNATIVE: save via builtin debug function
 | 
					    # ALTERNATIVE: save via builtin debug function
 | 
				
			||||||
    # im._dump(filename)
 | 
					    # im._dump(filename)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,12 +40,14 @@ i8 = _binary.i8
 | 
				
			||||||
i16 = _binary.i16be
 | 
					i16 = _binary.i16be
 | 
				
			||||||
i32 = _binary.i32be
 | 
					i32 = _binary.i32be
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --------------------------------------------------------------------.
 | 
					# --------------------------------------------------------------------.
 | 
				
			||||||
# read PSD images
 | 
					# read PSD images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix[:4] == b"8BPS"
 | 
					    return prefix[:4] == b"8BPS"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Photoshop images.
 | 
					# Image plugin for Photoshop images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,6 +132,10 @@ class PsdImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self._fp = self.fp
 | 
					        self._fp = self.fp
 | 
				
			||||||
        self.frame = 0
 | 
					        self.frame = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return len(self.layers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, layer):
 | 
					    def seek(self, layer):
 | 
				
			||||||
        # seek to given layer (1..max)
 | 
					        # seek to given layer (1..max)
 | 
				
			||||||
        if layer == self.frame:
 | 
					        if layer == self.frame:
 | 
				
			||||||
| 
						 | 
					@ -159,6 +165,7 @@ class PsdImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        if self.mode == "P":
 | 
					        if self.mode == "P":
 | 
				
			||||||
            Image.Image.load(self)
 | 
					            Image.Image.load(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _layerinfo(file):
 | 
					def _layerinfo(file):
 | 
				
			||||||
    # read layerinfo block
 | 
					    # read layerinfo block
 | 
				
			||||||
    layers = []
 | 
					    layers = []
 | 
				
			||||||
| 
						 | 
					@ -166,8 +173,10 @@ def _layerinfo(file):
 | 
				
			||||||
    for i in range(abs(i16(read(2)))):
 | 
					    for i in range(abs(i16(read(2)))):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # bounding box
 | 
					        # bounding box
 | 
				
			||||||
        y0 = i32(read(4)); x0 = i32(read(4))
 | 
					        y0 = i32(read(4))
 | 
				
			||||||
        y1 = i32(read(4)); x1 = i32(read(4))
 | 
					        x0 = i32(read(4))
 | 
				
			||||||
 | 
					        y1 = i32(read(4))
 | 
				
			||||||
 | 
					        x1 = i32(read(4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # image info
 | 
					        # image info
 | 
				
			||||||
        info = []
 | 
					        info = []
 | 
				
			||||||
| 
						 | 
					@ -207,8 +216,10 @@ def _layerinfo(file):
 | 
				
			||||||
        if size:
 | 
					        if size:
 | 
				
			||||||
            length = i32(read(4))
 | 
					            length = i32(read(4))
 | 
				
			||||||
            if length:
 | 
					            if length:
 | 
				
			||||||
                mask_y = i32(read(4)); mask_x = i32(read(4))
 | 
					                mask_y = i32(read(4))
 | 
				
			||||||
                mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
 | 
					                mask_x = i32(read(4))
 | 
				
			||||||
 | 
					                mask_h = i32(read(4)) - mask_y
 | 
				
			||||||
 | 
					                mask_w = i32(read(4)) - mask_x
 | 
				
			||||||
                file.seek(length - 16, 1)
 | 
					                file.seek(length - 16, 1)
 | 
				
			||||||
            combined += length + 4
 | 
					            combined += length + 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,7 +230,8 @@ def _layerinfo(file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            length = i8(read(1))
 | 
					            length = i8(read(1))
 | 
				
			||||||
            if length:
 | 
					            if length:
 | 
				
			||||||
                # Don't know the proper encoding, Latin-1 should be a good guess
 | 
					                # Don't know the proper encoding,
 | 
				
			||||||
 | 
					                # Latin-1 should be a good guess
 | 
				
			||||||
                name = read(length).decode('latin-1', 'replace')
 | 
					                name = read(length).decode('latin-1', 'replace')
 | 
				
			||||||
            combined += length + 1
 | 
					            combined += length + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,6 +251,7 @@ def _layerinfo(file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return layers
 | 
					    return layers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _maketile(file, mode, bbox, channels):
 | 
					def _maketile(file, mode, bbox, channels):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tile = None
 | 
					    tile = None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										113
									
								
								PIL/PyAccess.py
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								PIL/PyAccess.py
									
									
									
									
									
								
							| 
						 | 
					@ -16,7 +16,8 @@
 | 
				
			||||||
#  * Implements the pixel access object following Access.
 | 
					#  * Implements the pixel access object following Access.
 | 
				
			||||||
#  * Does not implement the line functions, as they don't appear to be used
 | 
					#  * Does not implement the line functions, as they don't appear to be used
 | 
				
			||||||
#  * Taking only the tuple form, which is used from python.
 | 
					#  * Taking only the tuple form, which is used from python.
 | 
				
			||||||
#    * Fill.c uses the integer form, but it's still going to use the old Access.c implementation.
 | 
					#    * Fill.c uses the integer form, but it's still going to use the old
 | 
				
			||||||
 | 
					#      Access.c implementation.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
| 
						 | 
					@ -40,7 +41,7 @@ ffi.cdef(defs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PyAccess(object):
 | 
					class PyAccess(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, img, readonly = False):
 | 
					    def __init__(self, img, readonly=False):
 | 
				
			||||||
        vals = dict(img.im.unsafe_ptrs)
 | 
					        vals = dict(img.im.unsafe_ptrs)
 | 
				
			||||||
        self.readonly = readonly
 | 
					        self.readonly = readonly
 | 
				
			||||||
        self.image8 = ffi.cast('unsigned char **', vals['image8'])
 | 
					        self.image8 = ffi.cast('unsigned char **', vals['image8'])
 | 
				
			||||||
| 
						 | 
					@ -50,10 +51,11 @@ class PyAccess(object):
 | 
				
			||||||
        self.ysize = vals['ysize']
 | 
					        self.ysize = vals['ysize']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if DEBUG:
 | 
					        if DEBUG:
 | 
				
			||||||
            print (vals)
 | 
					            print(vals)
 | 
				
			||||||
        self._post_init()
 | 
					        self._post_init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _post_init(): pass
 | 
					    def _post_init(self):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __setitem__(self, xy, color):
 | 
					    def __setitem__(self, xy, color):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -64,9 +66,10 @@ class PyAccess(object):
 | 
				
			||||||
        :param xy: The pixel coordinate, given as (x, y).
 | 
					        :param xy: The pixel coordinate, given as (x, y).
 | 
				
			||||||
        :param value: The pixel value.
 | 
					        :param value: The pixel value.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if self.readonly: raise ValueError('Attempt to putpixel a read only image') 
 | 
					        if self.readonly:
 | 
				
			||||||
        (x,y) = self.check_xy(xy)
 | 
					            raise ValueError('Attempt to putpixel a read only image')
 | 
				
			||||||
        return self.set_pixel(x,y,color)
 | 
					        (x, y) = self.check_xy(xy)
 | 
				
			||||||
 | 
					        return self.set_pixel(x, y, color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __getitem__(self, xy):
 | 
					    def __getitem__(self, xy):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -75,34 +78,38 @@ class PyAccess(object):
 | 
				
			||||||
        images
 | 
					        images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param xy: The pixel coordinate, given as (x, y).
 | 
					        :param xy: The pixel coordinate, given as (x, y).
 | 
				
			||||||
 | 
					        :returns: a pixel value for single band images, a tuple of
 | 
				
			||||||
 | 
					          pixel values for multiband images.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        (x,y) = self.check_xy(xy)
 | 
					        (x, y) = self.check_xy(xy)
 | 
				
			||||||
        return self.get_pixel(x,y)
 | 
					        return self.get_pixel(x, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    putpixel = __setitem__
 | 
					    putpixel = __setitem__
 | 
				
			||||||
    getpixel = __getitem__
 | 
					    getpixel = __getitem__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check_xy(self, xy):
 | 
					    def check_xy(self, xy):
 | 
				
			||||||
        (x,y) = xy
 | 
					        (x, y) = xy
 | 
				
			||||||
        if not (0 <= x < self.xsize and 0 <= y < self.ysize):
 | 
					        if not (0 <= x < self.xsize and 0 <= y < self.ysize):
 | 
				
			||||||
            raise ValueError('pixel location out of range')
 | 
					            raise ValueError('pixel location out of range')
 | 
				
			||||||
        return xy
 | 
					        return xy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccess32_2(PyAccess):
 | 
					class _PyAccess32_2(PyAccess):
 | 
				
			||||||
    """ PA, LA, stored in first and last bytes of a 32 bit word """
 | 
					    """ PA, LA, stored in first and last bytes of a 32 bit word """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
					        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        return (pixel.r, pixel.a)
 | 
					        return (pixel.r, pixel.a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        # tuple
 | 
					        # tuple
 | 
				
			||||||
        pixel.r = min(color[0],255)
 | 
					        pixel.r = min(color[0], 255)
 | 
				
			||||||
        pixel.a = min(color[1],255)
 | 
					        pixel.a = min(color[1], 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccess32_3(PyAccess):
 | 
					class _PyAccess32_3(PyAccess):
 | 
				
			||||||
    """ RGB and friends, stored in the first three bytes of a 32 bit word """
 | 
					    """ RGB and friends, stored in the first three bytes of a 32 bit word """
 | 
				
			||||||
| 
						 | 
					@ -110,33 +117,34 @@ class _PyAccess32_3(PyAccess):
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
					        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        return (pixel.r, pixel.g, pixel.b)
 | 
					        return (pixel.r, pixel.g, pixel.b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        # tuple
 | 
					        # tuple
 | 
				
			||||||
        pixel.r = min(color[0],255)
 | 
					        pixel.r = min(color[0], 255)
 | 
				
			||||||
        pixel.g = min(color[1],255)
 | 
					        pixel.g = min(color[1], 255)
 | 
				
			||||||
        pixel.b = min(color[2],255)
 | 
					        pixel.b = min(color[2], 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccess32_4(PyAccess):
 | 
					class _PyAccess32_4(PyAccess):
 | 
				
			||||||
    """ RGBA etc, all 4 bytes of a 32 bit word """
 | 
					    """ RGBA etc, all 4 bytes of a 32 bit word """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
					        self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        return (pixel.r, pixel.g, pixel.b, pixel.a)
 | 
					        return (pixel.r, pixel.g, pixel.b, pixel.a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        # tuple
 | 
					        # tuple
 | 
				
			||||||
        pixel.r = min(color[0],255)
 | 
					        pixel.r = min(color[0], 255)
 | 
				
			||||||
        pixel.g = min(color[1],255)
 | 
					        pixel.g = min(color[1], 255)
 | 
				
			||||||
        pixel.b = min(color[2],255)
 | 
					        pixel.b = min(color[2], 255)
 | 
				
			||||||
        pixel.a = min(color[3],255)
 | 
					        pixel.a = min(color[3], 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccess8(PyAccess):
 | 
					class _PyAccess8(PyAccess):
 | 
				
			||||||
| 
						 | 
					@ -144,26 +152,27 @@ class _PyAccess8(PyAccess):
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = self.image8
 | 
					        self.pixels = self.image8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        return self.pixels[y][x]
 | 
					        return self.pixels[y][x]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # integer
 | 
					            # integer
 | 
				
			||||||
            self.pixels[y][x] = min(color,255)
 | 
					            self.pixels[y][x] = min(color, 255)
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            # tuple
 | 
					            # tuple
 | 
				
			||||||
            self.pixels[y][x] = min(color[0],255)
 | 
					            self.pixels[y][x] = min(color[0], 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessI16_N(PyAccess):
 | 
					class _PyAccessI16_N(PyAccess):
 | 
				
			||||||
    """ I;16 access, native bitendian without conversion """
 | 
					    """ I;16 access, native bitendian without conversion """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast('unsigned short **', self.image)
 | 
					        self.pixels = ffi.cast('unsigned short **', self.image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        return self.pixels[y][x]
 | 
					        return self.pixels[y][x]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # integer
 | 
					            # integer
 | 
				
			||||||
            self.pixels[y][x] = min(color, 65535)
 | 
					            self.pixels[y][x] = min(color, 65535)
 | 
				
			||||||
| 
						 | 
					@ -171,35 +180,37 @@ class _PyAccessI16_N(PyAccess):
 | 
				
			||||||
            # tuple
 | 
					            # tuple
 | 
				
			||||||
            self.pixels[y][x] = min(color[0], 65535)
 | 
					            self.pixels[y][x] = min(color[0], 65535)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessI16_L(PyAccess):
 | 
					class _PyAccessI16_L(PyAccess):
 | 
				
			||||||
    """ I;16L access, with conversion """
 | 
					    """ I;16L access, with conversion """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
 | 
					        self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        return pixel.l + pixel.r * 256
 | 
					        return pixel.l + pixel.r * 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            color = min(color, 65535)
 | 
					            color = min(color, 65535)
 | 
				
			||||||
        except:
 | 
					        except TypeError:
 | 
				
			||||||
            color = min(color[0], 65535)
 | 
					            color = min(color[0], 65535)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pixel.l = color & 0xFF
 | 
					        pixel.l = color & 0xFF
 | 
				
			||||||
        pixel.r = color >> 8
 | 
					        pixel.r = color >> 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessI16_B(PyAccess):
 | 
					class _PyAccessI16_B(PyAccess):
 | 
				
			||||||
    """ I;16B access, with conversion """
 | 
					    """ I;16B access, with conversion """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
 | 
					        self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        return pixel.l *256  + pixel.r
 | 
					        return pixel.l * 256 + pixel.r
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        pixel = self.pixels[y][x]
 | 
					        pixel = self.pixels[y][x]
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            color = min(color, 65535)
 | 
					            color = min(color, 65535)
 | 
				
			||||||
| 
						 | 
					@ -209,17 +220,19 @@ class _PyAccessI16_B(PyAccess):
 | 
				
			||||||
        pixel.l = color >> 8
 | 
					        pixel.l = color >> 8
 | 
				
			||||||
        pixel.r = color & 0xFF
 | 
					        pixel.r = color & 0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessI32_N(PyAccess):
 | 
					class _PyAccessI32_N(PyAccess):
 | 
				
			||||||
    """ Signed Int32 access, native endian """
 | 
					    """ Signed Int32 access, native endian """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = self.image32
 | 
					        self.pixels = self.image32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        return self.pixels[y][x]
 | 
					        return self.pixels[y][x]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        self.pixels[y][x] = color
 | 
					        self.pixels[y][x] = color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessI32_Swap(PyAccess):
 | 
					class _PyAccessI32_Swap(PyAccess):
 | 
				
			||||||
    """ I;32L/B access, with byteswapping conversion """
 | 
					    """ I;32L/B access, with byteswapping conversion """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -228,24 +241,26 @@ class _PyAccessI32_Swap(PyAccess):
 | 
				
			||||||
    def reverse(self, i):
 | 
					    def reverse(self, i):
 | 
				
			||||||
        orig = ffi.new('int *', i)
 | 
					        orig = ffi.new('int *', i)
 | 
				
			||||||
        chars = ffi.cast('unsigned char *', orig)
 | 
					        chars = ffi.cast('unsigned char *', orig)
 | 
				
			||||||
        chars[0],chars[1],chars[2],chars[3] = chars[3], chars[2],chars[1],chars[0]
 | 
					        chars[0], chars[1], chars[2], chars[3] = chars[3], chars[2], \
 | 
				
			||||||
 | 
					            chars[1], chars[0]
 | 
				
			||||||
        return ffi.cast('int *', chars)[0]
 | 
					        return ffi.cast('int *', chars)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        return self.reverse(self.pixels[y][x])
 | 
					        return self.reverse(self.pixels[y][x])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        self.pixels[y][x] = self.reverse(color)
 | 
					        self.pixels[y][x] = self.reverse(color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _PyAccessF(PyAccess):
 | 
					class _PyAccessF(PyAccess):
 | 
				
			||||||
    """ 32 bit float access """
 | 
					    """ 32 bit float access """
 | 
				
			||||||
    def _post_init(self, *args, **kwargs):
 | 
					    def _post_init(self, *args, **kwargs):
 | 
				
			||||||
        self.pixels = ffi.cast('float **', self.image32)
 | 
					        self.pixels = ffi.cast('float **', self.image32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_pixel(self, x,y):
 | 
					    def get_pixel(self, x, y):
 | 
				
			||||||
        return self.pixels[y][x]
 | 
					        return self.pixels[y][x]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_pixel(self, x,y, color):
 | 
					    def set_pixel(self, x, y, color):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # not a tuple
 | 
					            # not a tuple
 | 
				
			||||||
            self.pixels[y][x] = color
 | 
					            self.pixels[y][x] = color
 | 
				
			||||||
| 
						 | 
					@ -286,13 +301,15 @@ else:
 | 
				
			||||||
    mode_map['I;32L'] = _PyAccessI32_Swap
 | 
					    mode_map['I;32L'] = _PyAccessI32_Swap
 | 
				
			||||||
    mode_map['I;32B'] = _PyAccessI32_N
 | 
					    mode_map['I;32B'] = _PyAccessI32_N
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def new(img, readonly=False):
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def new(img, readonly=False):
 | 
				
			||||||
    access_type = mode_map.get(img.mode, None)
 | 
					    access_type = mode_map.get(img.mode, None)
 | 
				
			||||||
    if not access_type:
 | 
					    if not access_type:
 | 
				
			||||||
        if DEBUG: print ("PyAccess Not Implemented: %s" % img.mode)
 | 
					        if DEBUG:
 | 
				
			||||||
 | 
					            print("PyAccess Not Implemented: %s" % img.mode)
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
    if DEBUG: print ("New PyAccess: %s" % img.mode)
 | 
					    if DEBUG:
 | 
				
			||||||
 | 
					        print("New PyAccess: %s" % img.mode)
 | 
				
			||||||
    return access_type(img, readonly)
 | 
					    return access_type(img, readonly)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ def isInt(f):
 | 
				
			||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return 0
 | 
					            return 0
 | 
				
			||||||
    except:
 | 
					    except ValueError:
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
iforms = [1, 3, -11, -12, -21, -22]
 | 
					iforms = [1, 3, -11, -12, -21, -22]
 | 
				
			||||||
| 
						 | 
					@ -127,12 +127,12 @@ class SpiderImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        if self.istack == 0 and self.imgnumber == 0:
 | 
					        if self.istack == 0 and self.imgnumber == 0:
 | 
				
			||||||
            # stk=0, img=0: a regular 2D image
 | 
					            # stk=0, img=0: a regular 2D image
 | 
				
			||||||
            offset = hdrlen
 | 
					            offset = hdrlen
 | 
				
			||||||
            self.nimages = 1
 | 
					            self._nimages = 1
 | 
				
			||||||
        elif self.istack > 0 and self.imgnumber == 0:
 | 
					        elif self.istack > 0 and self.imgnumber == 0:
 | 
				
			||||||
            # stk>0, img=0: Opening the stack for the first time
 | 
					            # stk>0, img=0: Opening the stack for the first time
 | 
				
			||||||
            self.imgbytes = int(h[12]) * int(h[2]) * 4
 | 
					            self.imgbytes = int(h[12]) * int(h[2]) * 4
 | 
				
			||||||
            self.hdrlen = hdrlen
 | 
					            self.hdrlen = hdrlen
 | 
				
			||||||
            self.nimages = int(h[26])
 | 
					            self._nimages = int(h[26])
 | 
				
			||||||
            # Point to the first image in the stack
 | 
					            # Point to the first image in the stack
 | 
				
			||||||
            offset = hdrlen * 2
 | 
					            offset = hdrlen * 2
 | 
				
			||||||
            self.imgnumber = 1
 | 
					            self.imgnumber = 1
 | 
				
			||||||
| 
						 | 
					@ -154,6 +154,10 @@ class SpiderImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                (self.rawmode, 0, 1))]
 | 
					                (self.rawmode, 0, 1))]
 | 
				
			||||||
        self.__fp = self.fp  # FIXME: hack
 | 
					        self.__fp = self.fp  # FIXME: hack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        return self._nimages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 1st image index is zero (although SPIDER imgnumber starts at 1)
 | 
					    # 1st image index is zero (although SPIDER imgnumber starts at 1)
 | 
				
			||||||
    def tell(self):
 | 
					    def tell(self):
 | 
				
			||||||
        if self.imgnumber < 1:
 | 
					        if self.imgnumber < 1:
 | 
				
			||||||
| 
						 | 
					@ -164,7 +168,7 @@ class SpiderImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
        if self.istack == 0:
 | 
					        if self.istack == 0:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        if frame >= self.nimages:
 | 
					        if frame >= self._nimages:
 | 
				
			||||||
            raise EOFError("attempt to seek past end of file")
 | 
					            raise EOFError("attempt to seek past end of file")
 | 
				
			||||||
        self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
 | 
					        self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
 | 
				
			||||||
        self.fp = self.__fp
 | 
					        self.fp = self.__fp
 | 
				
			||||||
| 
						 | 
					@ -173,11 +177,11 @@ class SpiderImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # returns a byte image after rescaling to 0..255
 | 
					    # returns a byte image after rescaling to 0..255
 | 
				
			||||||
    def convert2byte(self, depth=255):
 | 
					    def convert2byte(self, depth=255):
 | 
				
			||||||
        (min, max) = self.getextrema()
 | 
					        (minimum, maximum) = self.getextrema()
 | 
				
			||||||
        m = 1
 | 
					        m = 1
 | 
				
			||||||
        if max != min:
 | 
					        if maximum != minimum:
 | 
				
			||||||
            m = depth / (max-min)
 | 
					            m = depth / (maximum-minimum)
 | 
				
			||||||
        b = -m * min
 | 
					        b = -m * minimum
 | 
				
			||||||
        return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
 | 
					        return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # returns a ImageTk.PhotoImage object, after rescaling to 0..255
 | 
					    # returns a ImageTk.PhotoImage object, after rescaling to 0..255
 | 
				
			||||||
| 
						 | 
					@ -271,7 +275,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save_spider(im, fp, filename):
 | 
					def _save_spider(im, fp, filename):
 | 
				
			||||||
    # get the filename extension and register it with Image
 | 
					    # get the filename extension and register it with Image
 | 
				
			||||||
    fn, ext = os.path.splitext(filename)
 | 
					    ext = os.path.splitext(filename)[1]
 | 
				
			||||||
    Image.register_extension("SPIDER", ext)
 | 
					    Image.register_extension("SPIDER", ext)
 | 
				
			||||||
    _save(im, fp, filename)
 | 
					    _save(im, fp, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import ContainerIO
 | 
					from PIL import ContainerIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# A file object that provides read access to a given member of a TAR
 | 
					# A file object that provides read access to a given member of a TAR
 | 
				
			||||||
# file.
 | 
					# file.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,9 +42,6 @@ MODES = {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					 | 
				
			||||||
    return prefix[0:1] == b"\0"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Targa files.
 | 
					# Image plugin for Targa files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +55,7 @@ class TgaImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # process header
 | 
					        # process header
 | 
				
			||||||
        s = self.fp.read(18)
 | 
					        s = self.fp.read(18)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        id = i8(s[0])
 | 
					        idlen = i8(s[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        colormaptype = i8(s[1])
 | 
					        colormaptype = i8(s[1])
 | 
				
			||||||
        imagetype = i8(s[2])
 | 
					        imagetype = i8(s[2])
 | 
				
			||||||
| 
						 | 
					@ -70,7 +67,7 @@ class TgaImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.size = i16(s[12:]), i16(s[14:])
 | 
					        self.size = i16(s[12:]), i16(s[14:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # validate header fields
 | 
					        # validate header fields
 | 
				
			||||||
        if id != 0 or colormaptype not in (0, 1) or\
 | 
					        if colormaptype not in (0, 1) or\
 | 
				
			||||||
           self.size[0] <= 0 or self.size[1] <= 0 or\
 | 
					           self.size[0] <= 0 or self.size[1] <= 0 or\
 | 
				
			||||||
           depth not in (1, 8, 16, 24, 32):
 | 
					           depth not in (1, 8, 16, 24, 32):
 | 
				
			||||||
            raise SyntaxError("not a TGA file")
 | 
					            raise SyntaxError("not a TGA file")
 | 
				
			||||||
| 
						 | 
					@ -103,22 +100,25 @@ class TgaImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        if imagetype & 8:
 | 
					        if imagetype & 8:
 | 
				
			||||||
            self.info["compression"] = "tga_rle"
 | 
					            self.info["compression"] = "tga_rle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if idlen:
 | 
				
			||||||
 | 
					            self.info["id_section"] = self.fp.read(idlen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if colormaptype:
 | 
					        if colormaptype:
 | 
				
			||||||
            # read palette
 | 
					            # read palette
 | 
				
			||||||
            start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:])
 | 
					            start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:])
 | 
				
			||||||
            if mapdepth == 16:
 | 
					            if mapdepth == 16:
 | 
				
			||||||
                self.palette = ImagePalette.raw("BGR;16",
 | 
					                self.palette = ImagePalette.raw(
 | 
				
			||||||
                    b"\0"*2*start + self.fp.read(2*size))
 | 
					                    "BGR;16", b"\0"*2*start + self.fp.read(2*size))
 | 
				
			||||||
            elif mapdepth == 24:
 | 
					            elif mapdepth == 24:
 | 
				
			||||||
                self.palette = ImagePalette.raw("BGR",
 | 
					                self.palette = ImagePalette.raw(
 | 
				
			||||||
                    b"\0"*3*start + self.fp.read(3*size))
 | 
					                    "BGR", b"\0"*3*start + self.fp.read(3*size))
 | 
				
			||||||
            elif mapdepth == 32:
 | 
					            elif mapdepth == 32:
 | 
				
			||||||
                self.palette = ImagePalette.raw("BGRA",
 | 
					                self.palette = ImagePalette.raw(
 | 
				
			||||||
                    b"\0"*4*start + self.fp.read(4*size))
 | 
					                    "BGRA", b"\0"*4*start + self.fp.read(4*size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # setup tile descriptor
 | 
					        # setup tile descriptor
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            rawmode = MODES[(imagetype&7, depth)]
 | 
					            rawmode = MODES[(imagetype & 7, depth)]
 | 
				
			||||||
            if imagetype & 8:
 | 
					            if imagetype & 8:
 | 
				
			||||||
                # compressed
 | 
					                # compressed
 | 
				
			||||||
                self.tile = [("tga_rle", (0, 0)+self.size,
 | 
					                self.tile = [("tga_rle", (0, 0)+self.size,
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,7 @@ SAVE = {
 | 
				
			||||||
    "RGBA": ("BGRA", 32, 0, 2),
 | 
					    "RGBA": ("BGRA", 32, 0, 2),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _save(im, fp, filename, check=0):
 | 
					def _save(im, fp, filename, check=0):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -185,13 +186,14 @@ def _save(im, fp, filename, check=0):
 | 
				
			||||||
    if colormaptype:
 | 
					    if colormaptype:
 | 
				
			||||||
        fp.write(im.im.getpalette("RGB", "BGR"))
 | 
					        fp.write(im.im.getpalette("RGB", "BGR"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, orientation))])
 | 
					    ImageFile._save(
 | 
				
			||||||
 | 
					        im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, orientation))])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Registry
 | 
					# Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image.register_open("TGA", TgaImageFile, _accept)
 | 
					Image.register_open("TGA", TgaImageFile)
 | 
				
			||||||
Image.register_save("TGA", _save)
 | 
					Image.register_save("TGA", _save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Image.register_extension("TGA", ".tga")
 | 
					Image.register_extension("TGA", ".tga")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,7 @@ import sys
 | 
				
			||||||
import collections
 | 
					import collections
 | 
				
			||||||
import itertools
 | 
					import itertools
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set these to true to force use of libtiff for reading or writing.
 | 
					# Set these to true to force use of libtiff for reading or writing.
 | 
				
			||||||
READ_LIBTIFF = False
 | 
					READ_LIBTIFF = False
 | 
				
			||||||
| 
						 | 
					@ -149,6 +150,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"),
 | 
				
			||||||
| 
						 | 
					@ -281,6 +283,7 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
        self.tagdata = {}
 | 
					        self.tagdata = {}
 | 
				
			||||||
        self.tagtype = {}  # added 2008-06-05 by Florian Hoech
 | 
					        self.tagtype = {}  # added 2008-06-05 by Florian Hoech
 | 
				
			||||||
        self.next = None
 | 
					        self.next = None
 | 
				
			||||||
 | 
					        self.offset = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return str(self.as_dict())
 | 
					        return str(self.as_dict())
 | 
				
			||||||
| 
						 | 
					@ -291,7 +294,7 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def named(self):
 | 
					    def named(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns the complete tag dictionary, with named tags where posible.
 | 
					        Returns the complete tag dictionary, with named tags where possible.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        from PIL import TiffTags
 | 
					        from PIL import TiffTags
 | 
				
			||||||
        result = {}
 | 
					        result = {}
 | 
				
			||||||
| 
						 | 
					@ -415,6 +418,7 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
        # load tag dictionary
 | 
					        # load tag dictionary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.reset()
 | 
					        self.reset()
 | 
				
			||||||
 | 
					        self.offset = fp.tell()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        i16 = self.i16
 | 
					        i16 = self.i16
 | 
				
			||||||
        i32 = self.i32
 | 
					        i32 = self.i32
 | 
				
			||||||
| 
						 | 
					@ -422,6 +426,11 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
        for i in range(i16(fp.read(2))):
 | 
					        for i in range(i16(fp.read(2))):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ifd = fp.read(12)
 | 
					            ifd = fp.read(12)
 | 
				
			||||||
 | 
					            if len(ifd) != 12:
 | 
				
			||||||
 | 
					                warnings.warn("Possibly corrupt EXIF data.  "
 | 
				
			||||||
 | 
					                              "Expecting to read 12 bytes but only got %d."
 | 
				
			||||||
 | 
					                              % (len(ifd)))
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            tag, typ = i16(ifd), i16(ifd, 2)
 | 
					            tag, typ = i16(ifd), i16(ifd, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -446,7 +455,11 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
            # Get and expand tag value
 | 
					            # Get and expand tag value
 | 
				
			||||||
            if size > 4:
 | 
					            if size > 4:
 | 
				
			||||||
                here = fp.tell()
 | 
					                here = fp.tell()
 | 
				
			||||||
 | 
					                if Image.DEBUG:
 | 
				
			||||||
 | 
					                    print("Tag Location: %s" % here)
 | 
				
			||||||
                fp.seek(i32(ifd, 8))
 | 
					                fp.seek(i32(ifd, 8))
 | 
				
			||||||
 | 
					                if Image.DEBUG:
 | 
				
			||||||
 | 
					                    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:
 | 
				
			||||||
| 
						 | 
					@ -468,7 +481,14 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    print("- value:", self[tag])
 | 
					                    print("- value:", self[tag])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.next = i32(fp.read(4))
 | 
					        ifd = fp.read(4)
 | 
				
			||||||
 | 
					        if len(ifd) != 4:
 | 
				
			||||||
 | 
					            warnings.warn("Possibly corrupt EXIF data.  "
 | 
				
			||||||
 | 
					                          "Expecting to read 4 bytes but only got %d."
 | 
				
			||||||
 | 
					                          % (len(ifd)))
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.next = i32(ifd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # save primitives
 | 
					    # save primitives
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -498,7 +518,7 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
                typ = self.tagtype[tag]
 | 
					                typ = self.tagtype[tag]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if Image.DEBUG:
 | 
					            if Image.DEBUG:
 | 
				
			||||||
                print ("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
 | 
					                print("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if typ == 1:
 | 
					            if typ == 1:
 | 
				
			||||||
                # byte data
 | 
					                # byte data
 | 
				
			||||||
| 
						 | 
					@ -509,6 +529,15 @@ class ImageFileDirectory(collections.MutableMapping):
 | 
				
			||||||
            elif typ == 7:
 | 
					            elif typ == 7:
 | 
				
			||||||
                # untyped data
 | 
					                # untyped data
 | 
				
			||||||
                data = value = b"".join(value)
 | 
					                data = value = b"".join(value)
 | 
				
			||||||
 | 
					            elif typ in (11, 12):
 | 
				
			||||||
 | 
					                # float value
 | 
				
			||||||
 | 
					                tmap = {11: 'f', 12: 'd'}
 | 
				
			||||||
 | 
					                if not isinstance(value, tuple):
 | 
				
			||||||
 | 
					                    value = (value,)
 | 
				
			||||||
 | 
					                a = array.array(tmap[typ], value)
 | 
				
			||||||
 | 
					                if self.prefix != native_prefix:
 | 
				
			||||||
 | 
					                    a.byteswap()
 | 
				
			||||||
 | 
					                data = a.tostring()
 | 
				
			||||||
            elif isStringType(value[0]):
 | 
					            elif isStringType(value[0]):
 | 
				
			||||||
                # string data
 | 
					                # string data
 | 
				
			||||||
                if isinstance(value, tuple):
 | 
					                if isinstance(value, tuple):
 | 
				
			||||||
| 
						 | 
					@ -619,45 +648,63 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.__first = self.__next = self.ifd.i32(ifh, 4)
 | 
					        self.__first = self.__next = self.ifd.i32(ifh, 4)
 | 
				
			||||||
        self.__frame = -1
 | 
					        self.__frame = -1
 | 
				
			||||||
        self.__fp = self.fp
 | 
					        self.__fp = self.fp
 | 
				
			||||||
 | 
					        self._frame_pos = []
 | 
				
			||||||
 | 
					        self._n_frames = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print ("*** TiffImageFile._open ***")
 | 
					            print("*** TiffImageFile._open ***")
 | 
				
			||||||
            print ("- __first:", self.__first)
 | 
					            print("- __first:", self.__first)
 | 
				
			||||||
            print ("- ifh: ", ifh)
 | 
					            print("- ifh: ", ifh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # and load the first frame
 | 
					        # and load the first frame
 | 
				
			||||||
        self._seek(0)
 | 
					        self._seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def n_frames(self):
 | 
				
			||||||
 | 
					        if self._n_frames is None:
 | 
				
			||||||
 | 
					            current = self.tell()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                while True:
 | 
				
			||||||
 | 
					                    self._seek(self.tell() + 1)
 | 
				
			||||||
 | 
					            except EOFError:
 | 
				
			||||||
 | 
					                self._n_frames = self.tell() + 1
 | 
				
			||||||
 | 
					            self.seek(current)
 | 
				
			||||||
 | 
					        return self._n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek(self, frame):
 | 
					    def seek(self, frame):
 | 
				
			||||||
        "Select a given frame as current image"
 | 
					        "Select a given frame as current image"
 | 
				
			||||||
 | 
					        self._seek(max(frame, 0))  # Questionable backwards compatibility.
 | 
				
			||||||
        if frame < 0:
 | 
					        # Create a new core image object on second and
 | 
				
			||||||
            frame = 0
 | 
					        # subsequent frames in the image. Image may be
 | 
				
			||||||
        self._seek(frame)
 | 
					        # different size/mode.
 | 
				
			||||||
 | 
					        Image._decompression_bomb_check(self.size)
 | 
				
			||||||
    def tell(self):
 | 
					        self.im = Image.core.new(self.mode, self.size)
 | 
				
			||||||
        "Return the current frame number"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return self._tell()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _seek(self, frame):
 | 
					    def _seek(self, frame):
 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.fp = self.__fp
 | 
					        self.fp = self.__fp
 | 
				
			||||||
        if frame < self.__frame:
 | 
					        while len(self._frame_pos) <= frame:
 | 
				
			||||||
            # rewind file
 | 
					 | 
				
			||||||
            self.__frame = -1
 | 
					 | 
				
			||||||
            self.__next = self.__first
 | 
					 | 
				
			||||||
        while self.__frame < frame:
 | 
					 | 
				
			||||||
            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:
 | 
				
			||||||
 | 
					                print("Seeking to frame %s, on frame %s, __next %s, location: %s" %
 | 
				
			||||||
 | 
					                      (frame, self.__frame, self.__next, self.fp.tell()))
 | 
				
			||||||
 | 
					            # reset python3 buffered io handle in case fp
 | 
				
			||||||
 | 
					            # was passed to libtiff, invalidating the buffer
 | 
				
			||||||
 | 
					            self.fp.tell()
 | 
				
			||||||
            self.fp.seek(self.__next)
 | 
					            self.fp.seek(self.__next)
 | 
				
			||||||
 | 
					            self._frame_pos.append(self.__next)
 | 
				
			||||||
 | 
					            if Image.DEBUG:
 | 
				
			||||||
 | 
					                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
 | 
				
			||||||
 | 
					        self.fp.seek(self._frame_pos[frame])
 | 
				
			||||||
 | 
					        self.tag.load(self.fp)
 | 
				
			||||||
 | 
					        self.__frame = frame
 | 
				
			||||||
        self._setup()
 | 
					        self._setup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _tell(self):
 | 
					    def tell(self):
 | 
				
			||||||
 | 
					        "Return the current frame number"
 | 
				
			||||||
        return self.__frame
 | 
					        return self.__frame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _decoder(self, rawmode, layer, tile=None):
 | 
					    def _decoder(self, rawmode, layer, tile=None):
 | 
				
			||||||
| 
						 | 
					@ -705,7 +752,8 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # (self._compression, (extents tuple),
 | 
					        # (self._compression, (extents tuple),
 | 
				
			||||||
        #   0, (rawmode, self._compression, fp))
 | 
					        #   0, (rawmode, self._compression, fp))
 | 
				
			||||||
        ignored, extents, ignored_2, args = self.tile[0]
 | 
					        extents = self.tile[0][1]
 | 
				
			||||||
 | 
					        args = self.tile[0][3] + (self.ifd.offset,)
 | 
				
			||||||
        decoder = Image._getdecoder(self.mode, 'libtiff', args,
 | 
					        decoder = Image._getdecoder(self.mode, 'libtiff', args,
 | 
				
			||||||
                                    self.decoderconfig)
 | 
					                                    self.decoderconfig)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -722,21 +770,21 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            #
 | 
					            #
 | 
				
			||||||
            # Rearranging for supporting byteio items, since they have a fileno
 | 
					            # Rearranging for supporting byteio items, since they have a fileno
 | 
				
			||||||
            # that returns an IOError if there's no underlying fp. Easier to
 | 
					            # that returns an IOError if there's no underlying fp. Easier to
 | 
				
			||||||
            # dea. with here by reordering.
 | 
					            # deal with here by reordering.
 | 
				
			||||||
            if Image.DEBUG:
 | 
					            if Image.DEBUG:
 | 
				
			||||||
                print ("have getvalue. just sending in a string from getvalue")
 | 
					                print("have getvalue. just sending in a string from getvalue")
 | 
				
			||||||
            n, err = decoder.decode(self.fp.getvalue())
 | 
					            n, err = decoder.decode(self.fp.getvalue())
 | 
				
			||||||
        elif hasattr(self.fp, "fileno"):
 | 
					        elif hasattr(self.fp, "fileno"):
 | 
				
			||||||
            # we've got a actual file on disk, pass in the fp.
 | 
					            # we've got a actual file on disk, pass in the fp.
 | 
				
			||||||
            if Image.DEBUG:
 | 
					            if Image.DEBUG:
 | 
				
			||||||
                print ("have fileno, calling fileno version of the decoder.")
 | 
					                print("have fileno, calling fileno version of the decoder.")
 | 
				
			||||||
            self.fp.seek(0)
 | 
					            self.fp.seek(0)
 | 
				
			||||||
            # 4 bytes, otherwise the trace might error out
 | 
					            # 4 bytes, otherwise the trace might error out
 | 
				
			||||||
            n, err = decoder.decode(b"fpfp")
 | 
					            n, err = decoder.decode(b"fpfp")
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            # we have something else.
 | 
					            # we have something else.
 | 
				
			||||||
            if Image.DEBUG:
 | 
					            if Image.DEBUG:
 | 
				
			||||||
                print ("don't have fileno or getvalue. just reading")
 | 
					                print("don't have fileno or getvalue. just reading")
 | 
				
			||||||
            # UNDONE -- so much for that buffer size thing.
 | 
					            # UNDONE -- so much for that buffer size thing.
 | 
				
			||||||
            n, err = decoder.decode(self.fp.read())
 | 
					            n, err = decoder.decode(self.fp.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -744,6 +792,7 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        self.readonly = 0
 | 
					        self.readonly = 0
 | 
				
			||||||
        # libtiff closed the fp in a, we need to close self.fp, if possible
 | 
					        # libtiff closed the fp in a, we need to close self.fp, if possible
 | 
				
			||||||
        if hasattr(self.fp, 'close'):
 | 
					        if hasattr(self.fp, 'close'):
 | 
				
			||||||
 | 
					            if not self.__next:
 | 
				
			||||||
                self.fp.close()
 | 
					                self.fp.close()
 | 
				
			||||||
        self.fp = None  # might be shared
 | 
					        self.fp = None  # might be shared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -866,6 +915,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.
 | 
				
			||||||
| 
						 | 
					@ -911,7 +964,7 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
                            (0, min(y, ysize), w, min(y+h, ysize)),
 | 
					                            (0, min(y, ysize), w, min(y+h, ysize)),
 | 
				
			||||||
                            offsets[i], a))
 | 
					                            offsets[i], a))
 | 
				
			||||||
                    if Image.DEBUG:
 | 
					                    if Image.DEBUG:
 | 
				
			||||||
                        print ("tiles: ", self.tile)
 | 
					                        print("tiles: ", self.tile)
 | 
				
			||||||
                    y = y + h
 | 
					                    y = y + h
 | 
				
			||||||
                    if y >= self.size[1]:
 | 
					                    if y >= self.size[1]:
 | 
				
			||||||
                        x = y = 0
 | 
					                        x = y = 0
 | 
				
			||||||
| 
						 | 
					@ -946,14 +999,14 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        # fixup palette descriptor
 | 
					        # fixup palette descriptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.mode == "P":
 | 
					        if self.mode == "P":
 | 
				
			||||||
            palette = [o8(a // 256) for a in self.tag[COLORMAP]]
 | 
					            palette = [o8(b // 256) for b in self.tag[COLORMAP]]
 | 
				
			||||||
            self.palette = ImagePalette.raw("RGB;L", b"".join(palette))
 | 
					            self.palette = ImagePalette.raw("RGB;L", b"".join(palette))
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Write TIFF files
 | 
					# Write TIFF files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# little endian is default except for image modes with
 | 
					# little endian is default except for image modes with
 | 
				
			||||||
# explict big endian byte-order
 | 
					# explicit big endian byte-order
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SAVE_INFO = {
 | 
					SAVE_INFO = {
 | 
				
			||||||
    # mode => rawmode, byteorder, photometrics,
 | 
					    # mode => rawmode, byteorder, photometrics,
 | 
				
			||||||
| 
						 | 
					@ -1045,31 +1098,25 @@ def _save(im, fp, filename):
 | 
				
			||||||
        if "icc_profile" in im.info:
 | 
					        if "icc_profile" in im.info:
 | 
				
			||||||
            ifd[ICCPROFILE] = im.info["icc_profile"]
 | 
					            ifd[ICCPROFILE] = im.info["icc_profile"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if "description" in im.encoderinfo:
 | 
					    for key, name, cvt in [
 | 
				
			||||||
        ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
 | 
					            (IMAGEDESCRIPTION, "description", lambda x: x),
 | 
				
			||||||
    if "resolution" in im.encoderinfo:
 | 
					            (X_RESOLUTION, "resolution", _cvt_res),
 | 
				
			||||||
        ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
 | 
					            (Y_RESOLUTION, "resolution", _cvt_res),
 | 
				
			||||||
            = _cvt_res(im.encoderinfo["resolution"])
 | 
					            (X_RESOLUTION, "x_resolution", _cvt_res),
 | 
				
			||||||
    if "x resolution" in im.encoderinfo:
 | 
					            (Y_RESOLUTION, "y_resolution", _cvt_res),
 | 
				
			||||||
        ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
 | 
					            (RESOLUTION_UNIT, "resolution_unit",
 | 
				
			||||||
    if "y resolution" in im.encoderinfo:
 | 
					             lambda x: {"inch": 2, "cm": 3, "centimeter": 3}.get(x, 1)),
 | 
				
			||||||
        ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
 | 
					            (SOFTWARE, "software", lambda x: x),
 | 
				
			||||||
    if "resolution unit" in im.encoderinfo:
 | 
					            (DATE_TIME, "date_time", lambda x: x),
 | 
				
			||||||
        unit = im.encoderinfo["resolution unit"]
 | 
					            (ARTIST, "artist", lambda x: x),
 | 
				
			||||||
        if unit == "inch":
 | 
					            (COPYRIGHT, "copyright", lambda x: x)]:
 | 
				
			||||||
            ifd[RESOLUTION_UNIT] = 2
 | 
					        name_with_spaces = name.replace("_", " ")
 | 
				
			||||||
        elif unit == "cm" or unit == "centimeter":
 | 
					        if "_" in name and name_with_spaces in im.encoderinfo:
 | 
				
			||||||
            ifd[RESOLUTION_UNIT] = 3
 | 
					            warnings.warn("%r is deprecated; use %r instead" %
 | 
				
			||||||
        else:
 | 
					                          (name_with_spaces, name), DeprecationWarning)
 | 
				
			||||||
            ifd[RESOLUTION_UNIT] = 1
 | 
					            ifd[key] = cvt(im.encoderinfo[name.replace("_", " ")])
 | 
				
			||||||
    if "software" in im.encoderinfo:
 | 
					        if name in im.encoderinfo:
 | 
				
			||||||
        ifd[SOFTWARE] = im.encoderinfo["software"]
 | 
					            ifd[key] = cvt(im.encoderinfo[name])
 | 
				
			||||||
    if "date time" in im.encoderinfo:
 | 
					 | 
				
			||||||
        ifd[DATE_TIME] = im.encoderinfo["date time"]
 | 
					 | 
				
			||||||
    if "artist" in im.encoderinfo:
 | 
					 | 
				
			||||||
        ifd[ARTIST] = im.encoderinfo["artist"]
 | 
					 | 
				
			||||||
    if "copyright" in im.encoderinfo:
 | 
					 | 
				
			||||||
        ifd[COPYRIGHT] = im.encoderinfo["copyright"]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dpi = im.encoderinfo.get("dpi")
 | 
					    dpi = im.encoderinfo.get("dpi")
 | 
				
			||||||
    if dpi:
 | 
					    if dpi:
 | 
				
			||||||
| 
						 | 
					@ -1102,12 +1149,15 @@ def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if libtiff:
 | 
					    if libtiff:
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print ("Saving using libtiff encoder")
 | 
					            print("Saving using libtiff encoder")
 | 
				
			||||||
            print (ifd.items())
 | 
					            print(ifd.items())
 | 
				
			||||||
        _fp = 0
 | 
					        _fp = 0
 | 
				
			||||||
        if hasattr(fp, "fileno"):
 | 
					        if hasattr(fp, "fileno"):
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
                fp.seek(0)
 | 
					                fp.seek(0)
 | 
				
			||||||
                _fp = os.dup(fp.fileno())
 | 
					                _fp = os.dup(fp.fileno())
 | 
				
			||||||
 | 
					            except io.UnsupportedOperation:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # ICC Profile crashes.
 | 
					        # ICC Profile crashes.
 | 
				
			||||||
        blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE]
 | 
					        blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE]
 | 
				
			||||||
| 
						 | 
					@ -1132,8 +1182,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
 | 
				
			||||||
| 
						 | 
					@ -1154,7 +1207,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
                    atts[k] = v
 | 
					                    atts[k] = v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if Image.DEBUG:
 | 
					        if Image.DEBUG:
 | 
				
			||||||
            print (atts)
 | 
					            print(atts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # libtiff always expects the bytes in native order.
 | 
					        # libtiff always expects the bytes in native order.
 | 
				
			||||||
        # we're storing image byte order. So, if the rawmode
 | 
					        # we're storing image byte order. So, if the rawmode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,6 @@ TAGS = {
 | 
				
			||||||
    50716: "BlackLevelDeltaV",
 | 
					    50716: "BlackLevelDeltaV",
 | 
				
			||||||
    50717: "WhiteLevel",
 | 
					    50717: "WhiteLevel",
 | 
				
			||||||
    50718: "DefaultScale",
 | 
					    50718: "DefaultScale",
 | 
				
			||||||
    50741: "BestQualityScale",  # FIXME! Dictionary contains duplicate keys 50741
 | 
					 | 
				
			||||||
    50719: "DefaultCropOrigin",
 | 
					    50719: "DefaultCropOrigin",
 | 
				
			||||||
    50720: "DefaultCropSize",
 | 
					    50720: "DefaultCropSize",
 | 
				
			||||||
    50778: "CalibrationIlluminant1",
 | 
					    50778: "CalibrationIlluminant1",
 | 
				
			||||||
| 
						 | 
					@ -279,9 +278,10 @@ TAGS = {
 | 
				
			||||||
    50737: "ChromaBlurRadius",
 | 
					    50737: "ChromaBlurRadius",
 | 
				
			||||||
    50738: "AntiAliasStrength",
 | 
					    50738: "AntiAliasStrength",
 | 
				
			||||||
    50740: "DNGPrivateData",
 | 
					    50740: "DNGPrivateData",
 | 
				
			||||||
    50741: "MakerNoteSafety",  # FIXME! Dictionary contains duplicate keys 50741
 | 
					    50741: "MakerNoteSafety",
 | 
				
			||||||
 | 
					    50780: "BestQualityScale",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ImageJ
 | 
					    # ImageJ
 | 
				
			||||||
    50838: "ImageJMetaDataByteCounts",  # private tag registered with Adobe
 | 
					    50838: "ImageJMetaDataByteCounts",  # private tag registered with Adobe
 | 
				
			||||||
    50839: "ImageJMetaData",  # private tag registered with Adobe
 | 
					    50839: "ImageJMetaData",  # private tag registered with Adobe
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
# -*- coding: iso-8859-1 -*-
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# The Python Imaging Library.
 | 
					# The Python Imaging Library.
 | 
				
			||||||
# $Id$
 | 
					# $Id$
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -33,6 +31,7 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i32 = _binary.i32le
 | 
					i32 = _binary.i32le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Load texture from a Quake2 WAL texture file.
 | 
					# Load texture from a Quake2 WAL texture file.
 | 
				
			||||||
# <p>
 | 
					# <p>
 | 
				
			||||||
| 
						 | 
					@ -75,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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,8 @@ class WebPImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    format_description = "WebP image"
 | 
					    format_description = "WebP image"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open(self):
 | 
					    def _open(self):
 | 
				
			||||||
        data, width, height, self.mode, icc_profile, exif = _webp.WebPDecode(self.fp.read())
 | 
					        data, width, height, self.mode, icc_profile, exif = \
 | 
				
			||||||
 | 
					            _webp.WebPDecode(self.fp.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if icc_profile:
 | 
					        if icc_profile:
 | 
				
			||||||
            self.info["icc_profile"] = icc_profile
 | 
					            self.info["icc_profile"] = icc_profile
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ _handler = None
 | 
				
			||||||
if str != bytes:
 | 
					if str != bytes:
 | 
				
			||||||
    long = int
 | 
					    long = int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Install application-specific WMF image handler.
 | 
					# Install application-specific WMF image handler.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -36,7 +37,7 @@ def register_handler(handler):
 | 
				
			||||||
if hasattr(Image.core, "drawwmf"):
 | 
					if hasattr(Image.core, "drawwmf"):
 | 
				
			||||||
    # install default handler (windows only)
 | 
					    # install default handler (windows only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class WmfHandler:
 | 
					    class WmfHandler(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def open(self, im):
 | 
					        def open(self, im):
 | 
				
			||||||
            im.mode = "RGB"
 | 
					            im.mode = "RGB"
 | 
				
			||||||
| 
						 | 
					@ -56,6 +57,7 @@ if hasattr(Image.core, "drawwmf"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
word = _binary.i16le
 | 
					word = _binary.i16le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def short(c, o=0):
 | 
					def short(c, o=0):
 | 
				
			||||||
    v = word(c, o)
 | 
					    v = word(c, o)
 | 
				
			||||||
    if v >= 32768:
 | 
					    if v >= 32768:
 | 
				
			||||||
| 
						 | 
					@ -64,6 +66,7 @@ def short(c, o=0):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dword = _binary.i32le
 | 
					dword = _binary.i32le
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# --------------------------------------------------------------------
 | 
					# --------------------------------------------------------------------
 | 
				
			||||||
# Read WMF file
 | 
					# Read WMF file
 | 
				
			||||||
| 
						 | 
					@ -74,6 +77,7 @@ def _accept(prefix):
 | 
				
			||||||
        prefix[:4] == b"\x01\x00\x00\x00"
 | 
					        prefix[:4] == b"\x01\x00\x00\x00"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for Windows metafiles.
 | 
					# Image plugin for Windows metafiles.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,8 +99,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
            inch = word(s, 14)
 | 
					            inch = word(s, 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # get bounding box
 | 
					            # get bounding box
 | 
				
			||||||
            x0 = short(s, 6); y0 = short(s, 8)
 | 
					            x0 = short(s, 6)
 | 
				
			||||||
            x1 = short(s, 10); y1 = short(s, 12)
 | 
					            y0 = short(s, 8)
 | 
				
			||||||
 | 
					            x1 = short(s, 10)
 | 
				
			||||||
 | 
					            y1 = short(s, 12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # normalize size to 72 dots per inch
 | 
					            # normalize size to 72 dots per inch
 | 
				
			||||||
            size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
 | 
					            size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
 | 
				
			||||||
| 
						 | 
					@ -115,8 +121,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
 | 
				
			||||||
            # enhanced metafile
 | 
					            # enhanced metafile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # get bounding box
 | 
					            # get bounding box
 | 
				
			||||||
            x0 = dword(s, 8); y0 = dword(s, 12)
 | 
					            x0 = dword(s, 8)
 | 
				
			||||||
            x1 = dword(s, 16); y1 = dword(s, 20)
 | 
					            y0 = dword(s, 12)
 | 
				
			||||||
 | 
					            x1 = dword(s, 16)
 | 
				
			||||||
 | 
					            y1 = dword(s, 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # get frame (in 0.01 millimeter units)
 | 
					            # get frame (in 0.01 millimeter units)
 | 
				
			||||||
            frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36)
 | 
					            frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ for r in range(8):
 | 
				
			||||||
        for b in range(4):
 | 
					        for b in range(4):
 | 
				
			||||||
            PALETTE = PALETTE + (o8((r*255)//7)+o8((g*255)//7)+o8((b*255)//3))
 | 
					            PALETTE = PALETTE + (o8((r*255)//7)+o8((g*255)//7)+o8((b*255)//3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for XV thumbnail images.
 | 
					# Image plugin for XV thumbnail images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,9 +35,11 @@ xbm_head = re.compile(
 | 
				
			||||||
    b"[\\000-\\377]*_bits\\[\\]"
 | 
					    b"[\\000-\\377]*_bits\\[\\]"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _accept(prefix):
 | 
					def _accept(prefix):
 | 
				
			||||||
    return prefix.lstrip()[:7] == b"#define"
 | 
					    return prefix.lstrip()[:7] == b"#define"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# Image plugin for X11 bitmaps.
 | 
					# Image plugin for X11 bitmaps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,7 +83,7 @@ def _save(im, fp, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fp.write(b"static char im_bits[] = {\n")
 | 
					    fp.write(b"static char im_bits[] = {\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)])
 | 
					    ImageFile._save(im, fp, [("xbm", (0, 0)+im.size, 0, None)])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fp.write(b"};\n")
 | 
					    fp.write(b"};\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.9.0.dev0'  # Pillow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_plugins = ['BmpImagePlugin',
 | 
					_plugins = ['BmpImagePlugin',
 | 
				
			||||||
            'BufrStubImagePlugin',
 | 
					            'BufrStubImagePlugin',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,21 +11,24 @@
 | 
				
			||||||
# See the README file for information on usage and redistribution.
 | 
					# See the README file for information on usage and redistribution.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from struct import unpack, pack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if bytes is str:
 | 
					if bytes is str:
 | 
				
			||||||
    def i8(c):
 | 
					    def i8(c):
 | 
				
			||||||
        return ord(c)
 | 
					        return ord(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def o8(i):
 | 
					    def o8(i):
 | 
				
			||||||
        return chr(i&255)
 | 
					        return chr(i & 255)
 | 
				
			||||||
else:
 | 
					else:
 | 
				
			||||||
    def i8(c):
 | 
					    def i8(c):
 | 
				
			||||||
        return c if c.__class__ is int else c[0]
 | 
					        return c if c.__class__ is int else c[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def o8(i):
 | 
					    def o8(i):
 | 
				
			||||||
        return bytes((i&255,))
 | 
					        return bytes((i & 255,))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Input, le = little endian, be = big endian
 | 
					# Input, le = little endian, be = big endian
 | 
				
			||||||
#TODO: replace with more readable struct.unpack equivalent
 | 
					# TODO: replace with more readable struct.unpack equivalent
 | 
				
			||||||
def i16le(c, o=0):
 | 
					def i16le(c, o=0):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Converts a 2-bytes (16 bits) string to an integer.
 | 
					    Converts a 2-bytes (16 bits) string to an integer.
 | 
				
			||||||
| 
						 | 
					@ -33,7 +36,8 @@ def i16le(c, o=0):
 | 
				
			||||||
    c: string containing bytes to convert
 | 
					    c: string containing bytes to convert
 | 
				
			||||||
    o: offset of bytes to convert in string
 | 
					    o: offset of bytes to convert in string
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    return i8(c[o]) | (i8(c[o+1])<<8)
 | 
					    return unpack("<H", c[o:o+2])[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def i32le(c, o=0):
 | 
					def i32le(c, o=0):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -42,24 +46,31 @@ def i32le(c, o=0):
 | 
				
			||||||
    c: string containing bytes to convert
 | 
					    c: string containing bytes to convert
 | 
				
			||||||
    o: offset of bytes to convert in string
 | 
					    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)
 | 
					    return unpack("<I", c[o:o+4])[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def i16be(c, o=0):
 | 
					def i16be(c, o=0):
 | 
				
			||||||
    return (i8(c[o])<<8) | i8(c[o+1])
 | 
					    return unpack(">H", c[o:o+2])[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def i32be(c, o=0):
 | 
					def i32be(c, o=0):
 | 
				
			||||||
    return (i8(c[o])<<24) | (i8(c[o+1])<<16) | (i8(c[o+2])<<8) | i8(c[o+3])
 | 
					    return unpack(">I", c[o:o+4])[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Output, le = little endian, be = big endian
 | 
					# Output, le = little endian, be = big endian
 | 
				
			||||||
def o16le(i):
 | 
					def o16le(i):
 | 
				
			||||||
    return o8(i) + o8(i>>8)
 | 
					    return pack("<H", i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def o32le(i):
 | 
					def o32le(i):
 | 
				
			||||||
    return o8(i) + o8(i>>8) + o8(i>>16) + o8(i>>24)
 | 
					    return pack("<I", i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def o16be(i):
 | 
					def o16be(i):
 | 
				
			||||||
    return o8(i>>8) + o8(i)
 | 
					    return pack(">H", i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def o32be(i):
 | 
					def o32be(i):
 | 
				
			||||||
    return o8(i>>24) + o8(i>>16) + o8(i>>8) + o8(i)
 | 
					    return pack(">I", i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										67
									
								
								PIL/features.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								PIL/features.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					modules = {
 | 
				
			||||||
 | 
					    "pil": "PIL._imaging",
 | 
				
			||||||
 | 
					    "tkinter": "PIL._imagingtk",
 | 
				
			||||||
 | 
					    "freetype2": "PIL._imagingft",
 | 
				
			||||||
 | 
					    "littlecms2": "PIL._imagingcms",
 | 
				
			||||||
 | 
					    "webp": "PIL._webp",
 | 
				
			||||||
 | 
					    "transp_webp": ("WEBP", "WebPDecoderBuggyAlpha")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_module(feature):
 | 
				
			||||||
 | 
					    if feature not in modules:
 | 
				
			||||||
 | 
					        raise ValueError("Unknown module %s" % feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    module = modules[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    method_to_call = None
 | 
				
			||||||
 | 
					    if type(module) is tuple:
 | 
				
			||||||
 | 
					        module, method_to_call = module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        imported_module = __import__(module)
 | 
				
			||||||
 | 
					    except ImportError:
 | 
				
			||||||
 | 
					        # If a method is being checked, None means that
 | 
				
			||||||
 | 
					        # rather than the method failing, the module required for the method
 | 
				
			||||||
 | 
					        # failed to be imported first
 | 
				
			||||||
 | 
					        return None if method_to_call else False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if method_to_call:
 | 
				
			||||||
 | 
					        method = getattr(imported_module, method_to_call)
 | 
				
			||||||
 | 
					        return method() is True
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_supported_modules():
 | 
				
			||||||
 | 
					    supported_modules = []
 | 
				
			||||||
 | 
					    for feature in modules:
 | 
				
			||||||
 | 
					        if check_module(feature):
 | 
				
			||||||
 | 
					            supported_modules.append(feature)
 | 
				
			||||||
 | 
					    return supported_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					codecs = {
 | 
				
			||||||
 | 
					    "jpg": "jpeg",
 | 
				
			||||||
 | 
					    "jpg_2000": "jpeg2k",
 | 
				
			||||||
 | 
					    "zlib": "zip",
 | 
				
			||||||
 | 
					    "libtiff": "libtiff"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_codec(feature):
 | 
				
			||||||
 | 
					    if feature not in codecs:
 | 
				
			||||||
 | 
					        raise ValueError("Unknown codec %s" % feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    codec = codecs[feature]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return codec + "_encoder" in dir(Image.core)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_supported_codecs():
 | 
				
			||||||
 | 
					    supported_codecs = []
 | 
				
			||||||
 | 
					    for feature in codecs:
 | 
				
			||||||
 | 
					        if check_codec(feature):
 | 
				
			||||||
 | 
					            supported_codecs.append(feature)
 | 
				
			||||||
 | 
					    return supported_codecs
 | 
				
			||||||
							
								
								
									
										38
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								README.rst
									
									
									
									
									
								
							| 
						 | 
					@ -1,22 +1,48 @@
 | 
				
			||||||
Pillow
 | 
					Pillow
 | 
				
			||||||
======
 | 
					======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*Python Imaging Library (Fork)*
 | 
					Python Imaging Library (Fork)
 | 
				
			||||||
 | 
					-----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Pillow is the "friendly" PIL fork by `Alex Clark and Contributors <https://github.com/python-pillow/Pillow/graphs/contributors>`_. PIL is the Python Imaging Library by Fredrik Lundh and Contributors. For more information, please `read the documentation <http://pillow.readthedocs.org/>`_,  `check the changelog <https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst>`_ and `find out how to contribute <https://github.com/python-pillow/Pillow/blob/master/CONTRIBUTING.md>`_.
 | 
					Pillow is the "friendly PIL fork" by `Alex Clark and Contributors <https://github.com/python-pillow/Pillow/graphs/contributors>`_. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. image:: https://travis-ci.org/python-pillow/Pillow.svg?branch=master
 | 
					.. 
 | 
				
			||||||
 | 
					   image:: https://travis-ci.org/python-pillow/Pillow.svg?branch=master
 | 
				
			||||||
   :target: https://travis-ci.org/python-pillow/Pillow
 | 
					   :target: https://travis-ci.org/python-pillow/Pillow
 | 
				
			||||||
   :alt: Travis CI build status
 | 
					   :alt: Travis CI build status (Linux)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. image:: https://pypip.in/v/Pillow/badge.png
 | 
					.. 
 | 
				
			||||||
 | 
					   image:: https://pypip.in/v/Pillow/badge.png
 | 
				
			||||||
    :target: https://pypi.python.org/pypi/Pillow/
 | 
					    :target: https://pypi.python.org/pypi/Pillow/
 | 
				
			||||||
    :alt: Latest PyPI version
 | 
					    :alt: Latest PyPI version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. image:: https://pypip.in/d/Pillow/badge.png
 | 
					.. 
 | 
				
			||||||
 | 
					   image:: https://pypip.in/d/Pillow/badge.png
 | 
				
			||||||
    :target: https://pypi.python.org/pypi/Pillow/
 | 
					    :target: https://pypi.python.org/pypi/Pillow/
 | 
				
			||||||
    :alt: Number of PyPI downloads
 | 
					    :alt: Number of PyPI downloads
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
 | 
					.. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
 | 
				
			||||||
  :target: https://coveralls.io/r/python-pillow/Pillow?branch=master
 | 
					  :target: https://coveralls.io/r/python-pillow/Pillow?branch=master
 | 
				
			||||||
 | 
					   :alt: Code coverage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. image:: https://landscape.io/github/python-pillow/Pillow/master/landscape.png
 | 
				
			||||||
 | 
					   :target: https://landscape.io/github/python-pillow/Pillow/master
 | 
				
			||||||
 | 
					   :alt: Code health
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More Information
 | 
				
			||||||
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `Changelog <https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - `Pre-fork <https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst#02b5---117-1995-2010>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `Contribute <https://github.com/python-pillow/Pillow/blob/master/CONTRIBUTING.md>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - `Issues <https://github.com/python-pillow/Pillow/issues>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `Documentation <http://pillow.readthedocs.org/>`_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - `About <http://pillow.readthedocs.org/about.html>`_
 | 
				
			||||||
 | 
					  - `Guides <http://pillow.readthedocs.org/guides.html>`_
 | 
				
			||||||
 | 
					  - `Installation <http://pillow.readthedocs.org/installation.html>`_
 | 
				
			||||||
 | 
					  - `Reference <http://pillow.readthedocs.org/reference/index.html>`_
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										105
									
								
								RELEASING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								RELEASING.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					# Release Checklist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Main Release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Released quarterly on the first day of January, April, July, October.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [ ] Open a release ticket e.g. https://github.com/python-pillow/Pillow/issues/1174
 | 
				
			||||||
 | 
					* [ ] Develop and prepare release in ``master`` branch.
 | 
				
			||||||
 | 
					* [ ] Check [Travis CI](https://travis-ci.org/python-pillow/Pillow) to confirm passing tests in ``master`` branch.
 | 
				
			||||||
 | 
					* [ ] In compliance with https://www.python.org/dev/peps/pep-0440/, update version identifier in: 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    PIL/__init__.py setup.py _imaging.c
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Update `CHANGES.rst`.
 | 
				
			||||||
 | 
					* [ ] Run pre-release check via `make pre`.
 | 
				
			||||||
 | 
					* [ ] Create branch and tag for release e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ git branch 2.9.x
 | 
				
			||||||
 | 
					    $ git tag 2.9.0
 | 
				
			||||||
 | 
					    $ git push --all
 | 
				
			||||||
 | 
					    $ git push --tags
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload source distributions e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ make sdistup
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload [binary distributions](#binary-distributions)
 | 
				
			||||||
 | 
					* [ ] Manually hide old versions on PyPI as needed, such that only the latest main release is visible when viewing https://pypi.python.org/pypi/Pillow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Point Release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Released as needed for security, installation or critical bug fixes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [ ] Make necessary changes in ``master`` branch.
 | 
				
			||||||
 | 
					* [ ] Update `CHANGES.rst`. 
 | 
				
			||||||
 | 
					* [ ] Cherry pick individual commits from ``master`` branch to release branch e.g. ``2.9.x``.
 | 
				
			||||||
 | 
					* [ ] Check [Travis CI](https://travis-ci.org/python-pillow/Pillow) to confirm passing tests in release branch e.g. ``2.9.x``.
 | 
				
			||||||
 | 
					* [ ] Checkout release branch e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    git checkout -t remotes/origin/2.9.x
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] In compliance with https://www.python.org/dev/peps/pep-0440/, update version identifier in: 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    PIL/__init__.py setup.py _imaging.c
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Run pre-release check via `make pre`.
 | 
				
			||||||
 | 
					* [ ] Create tag for release e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ git tag 2.9.1
 | 
				
			||||||
 | 
					    $ git push --tags
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload source distributions e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ make sdistup
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload [binary distributions](#binary-distributions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Embargoed Release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Released as needed privately to individual vendors for critical security-related bug fixes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [ ] Prepare patch for all versions that will get a fix. Test against local installations.
 | 
				
			||||||
 | 
					* [ ] Commit against master, cherry pick to affected release branches.
 | 
				
			||||||
 | 
					* [ ] Run local test matrix on each release & Python version.
 | 
				
			||||||
 | 
					* [ ] Privately send to distros.
 | 
				
			||||||
 | 
					* [ ] Run pre-release check via `make pre`
 | 
				
			||||||
 | 
					* [ ] Amend any commits with the CVE #
 | 
				
			||||||
 | 
					* [ ] On release date, tag and push to GitHub.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    git checkout 2.5.x
 | 
				
			||||||
 | 
					    git tag 2.5.3
 | 
				
			||||||
 | 
					    git push origin 2.5.x
 | 
				
			||||||
 | 
					    git push origin --tags
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload source distributions e.g.:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ make sdistup
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Create and upload [binary distributions](#binary-distributions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Binary Distributions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Windows
 | 
				
			||||||
 | 
					* [ ] Contact @cgohlke for Windows binaries via release ticket e.g. https://github.com/python-pillow/Pillow/issues/1174.
 | 
				
			||||||
 | 
					* [ ] Download and extract tarball from @cgohlke and ``twine upload *``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### OS X
 | 
				
			||||||
 | 
					* [ ] Use the [Pillow OS X Wheel Builder](https://github.com/python-pillow/pillow-wheels):
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    $ git checkout https://github.com/python-pillow/pillow-wheels
 | 
				
			||||||
 | 
					    $ cd pillow-wheels
 | 
				
			||||||
 | 
					    $ git submodule init
 | 
				
			||||||
 | 
					    $ git submodule update
 | 
				
			||||||
 | 
					    $ cd Pillow
 | 
				
			||||||
 | 
					    $ git fetch --all
 | 
				
			||||||
 | 
					    $ git commit -a -m "Pillow -> 2.9.0"
 | 
				
			||||||
 | 
					    $ git push
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [ ] Download distributions from the [Pillow OS X Wheel Builder container](http://cdf58691c5cf45771290-6a3b6a0f5f6ab91aadc447b2a897dd9a.r50.cf2.rackcdn.com/) and ``twine upload *``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Publicize Release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [ ] Announce release availability via [Twitter](https://twitter.com/pythonpillow) e.g. https://twitter.com/aclark4life/status/583366798302691328.
 | 
				
			||||||
							
								
								
									
										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])
 | 
					 | 
				
			||||||
| 
						 | 
					@ -63,20 +63,3 @@ explode.py
 | 
				
			||||||
--------------------------------------------------------------------
 | 
					--------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Split a sequence file into individual frames.
 | 
					Split a sequence file into individual frames.
 | 
				
			||||||
 | 
					 | 
				
			||||||
image2py.py
 | 
					 | 
				
			||||||
--------------------------------------------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Convert an image to a Python module containing an IMAGE variable.
 | 
					 | 
				
			||||||
Note that the module using the module must include JPEG and ZIP
 | 
					 | 
				
			||||||
decoders, unless the -u option is used.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
olesummary.py
 | 
					 | 
				
			||||||
--------------------------------------------------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Uses the OleFileIO module to dump the summary information from an OLE
 | 
					 | 
				
			||||||
structured storage file.  This works with most OLE files, including
 | 
					 | 
				
			||||||
Word documents, FlashPix images, etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Note that datetime fields currently show the number of seconds since
 | 
					 | 
				
			||||||
January 1st, 1601.
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
import base64
 | 
					import base64
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,9 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    from tkinter import *
 | 
					    from tkinter import Tk, Toplevel, Frame, Label, Scale, HORIZONTAL
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    from Tkinter import *
 | 
					    from Tkinter import Tk, Toplevel, Frame, Label, Scale, HORIZONTAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageTk, ImageEnhance
 | 
					from PIL import Image, ImageTk, ImageEnhance
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ import sys
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# enhancer widget
 | 
					# enhancer widget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Enhance(Frame):
 | 
					class Enhance(Frame):
 | 
				
			||||||
    def __init__(self, master, image, name, enhancer, lo, hi):
 | 
					    def __init__(self, master, image, name, enhancer, lo, hi):
 | 
				
			||||||
        Frame.__init__(self, master)
 | 
					        Frame.__init__(self, master)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,11 +9,13 @@
 | 
				
			||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
import os, sys
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Interval:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, interval = "0"):
 | 
					class Interval(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, interval="0"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.setinterval(interval)
 | 
					        self.setinterval(interval)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user