mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-07 13:54:45 +03:00
Merge from master
This commit is contained in:
commit
e97f36be32
15
CHANGES.rst
15
CHANGES.rst
|
@ -4,6 +4,21 @@ Changelog (Pillow)
|
|||
2.5.0 (unreleased)
|
||||
------------------
|
||||
|
||||
- Fix test_imagedraw failures #727
|
||||
[cgohlke]
|
||||
|
||||
- Fix AttributeError: class Image has no attribute 'DEBUG' #726
|
||||
[cgohlke]
|
||||
|
||||
- Fix msvc warning: 'inline' : macro redefinition #725
|
||||
[cgohlke]
|
||||
|
||||
- Cleanup #654
|
||||
[dvska, hugovk, wiredfool]
|
||||
|
||||
- 16-bit monochrome support for JPEG2000
|
||||
[videan42]
|
||||
|
||||
- Fixed ImagePalette.save
|
||||
[brightpisces]
|
||||
|
||||
|
|
17
MANIFEST.in
17
MANIFEST.in
|
@ -2,6 +2,7 @@ include *.c
|
|||
include *.h
|
||||
include *.py
|
||||
include *.rst
|
||||
include .coveragerc
|
||||
include .gitattributes
|
||||
include .travis.yml
|
||||
include Makefile
|
||||
|
@ -28,28 +29,42 @@ recursive-include Sane CHANGES
|
|||
recursive-include Sane README
|
||||
recursive-include Scripts *.py
|
||||
recursive-include Scripts README
|
||||
recursive-include Tests *.bdf
|
||||
recursive-include Tests *.bin
|
||||
recursive-include Tests *.bmp
|
||||
recursive-include Tests *.doc
|
||||
recursive-include Tests *.eps
|
||||
recursive-include Tests *.fli
|
||||
recursive-include Tests *.gif
|
||||
recursive-include Tests *.gnuplot
|
||||
recursive-include Tests *.html
|
||||
recursive-include Tests *.icm
|
||||
recursive-include Tests *.icns
|
||||
recursive-include Tests *.ico
|
||||
recursive-include Tests *.j2k
|
||||
recursive-include Tests *.jp2
|
||||
recursive-include Tests *.jpg
|
||||
recursive-include Tests *.lut
|
||||
recursive-include Tests *.pbm
|
||||
recursive-include Tests *.pcf
|
||||
recursive-include Tests *.pcx
|
||||
recursive-include Tests *.pgm
|
||||
recursive-include Tests *.pil
|
||||
recursive-include Tests *.png
|
||||
recursive-include Tests *.ppm
|
||||
recursive-include Tests *.psd
|
||||
recursive-include Tests *.py
|
||||
recursive-include Tests *.spider
|
||||
recursive-include Tests *.tar
|
||||
recursive-include Tests *.tif
|
||||
recursive-include Tests *.tiff
|
||||
recursive-include Tests *.ttf
|
||||
recursive-include Tests *.txt
|
||||
recursive-include Tests *.webp
|
||||
recursive-include Tests *.xpm
|
||||
recursive-include Tk *.c
|
||||
recursive-include Tk *.txt
|
||||
recursive-include Tk *.rst
|
||||
recursive-include depends *.sh
|
||||
recursive-include docs *.bat
|
||||
recursive-include docs *.gitignore
|
||||
|
@ -64,3 +79,5 @@ recursive-include docs COPYING
|
|||
recursive-include docs LICENSE
|
||||
recursive-include libImaging *.c
|
||||
recursive-include libImaging *.h
|
||||
recursive-include Sane *.rst
|
||||
recursive-include Scripts *.rst
|
||||
|
|
1
Makefile
1
Makefile
|
@ -1,7 +1,6 @@
|
|||
pre:
|
||||
bin/python setup.py develop
|
||||
bin/python selftest.py
|
||||
bin/python Tests/run.py
|
||||
check-manifest
|
||||
pyroma .
|
||||
viewdoc
|
||||
|
|
|
@ -40,7 +40,10 @@ def _parse_codestream(fp):
|
|||
|
||||
size = (xsiz - xosiz, ysiz - yosiz)
|
||||
if csiz == 1:
|
||||
mode = 'L'
|
||||
if (yrsiz[0] & 0x7f) > 8:
|
||||
mode = 'I;16'
|
||||
else:
|
||||
mode = 'L'
|
||||
elif csiz == 2:
|
||||
mode = 'LA'
|
||||
elif csiz == 3:
|
||||
|
@ -78,6 +81,7 @@ def _parse_jp2_header(fp):
|
|||
|
||||
size = None
|
||||
mode = None
|
||||
bpc = None
|
||||
|
||||
hio = io.BytesIO(header)
|
||||
while True:
|
||||
|
@ -95,7 +99,9 @@ def _parse_jp2_header(fp):
|
|||
= struct.unpack('>IIHBBBB', content)
|
||||
size = (width, height)
|
||||
if unkc:
|
||||
if nc == 1:
|
||||
if nc == 1 and (bpc & 0x7f) > 8:
|
||||
mode = 'I;16'
|
||||
elif nc == 1:
|
||||
mode = 'L'
|
||||
elif nc == 2:
|
||||
mode = 'LA'
|
||||
|
@ -109,13 +115,19 @@ def _parse_jp2_header(fp):
|
|||
if meth == 1:
|
||||
cs = struct.unpack('>I', content[3:7])[0]
|
||||
if cs == 16: # sRGB
|
||||
if nc == 3:
|
||||
if nc == 1 and (bpc & 0x7f) > 8:
|
||||
mode = 'I;16'
|
||||
elif nc == 1:
|
||||
mode = 'L'
|
||||
elif nc == 3:
|
||||
mode = 'RGB'
|
||||
elif nc == 4:
|
||||
mode = 'RGBA'
|
||||
break
|
||||
elif cs == 17: # grayscale
|
||||
if nc == 1:
|
||||
if nc == 1 and (bpc & 0x7f) > 8:
|
||||
mode = 'I;16'
|
||||
elif nc == 1:
|
||||
mode = 'L'
|
||||
elif nc == 2:
|
||||
mode = 'LA'
|
||||
|
@ -129,10 +141,10 @@ def _parse_jp2_header(fp):
|
|||
|
||||
return (size, mode)
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for JPEG2000 images.
|
||||
|
||||
|
||||
class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||
format = "JPEG2000"
|
||||
format_description = "JPEG 2000 (ISO 15444)"
|
||||
|
@ -174,7 +186,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
|||
f.seek(pos, 0)
|
||||
except:
|
||||
length = -1
|
||||
|
||||
|
||||
self.tile = [('jpeg2k', (0, 0) + self.size, 0,
|
||||
(self.codec, self.reduce, self.layers, fd, length))]
|
||||
|
||||
|
|
17
PIL/tests.py
17
PIL/tests.py
|
@ -1,17 +0,0 @@
|
|||
import unittest
|
||||
|
||||
|
||||
class PillowTests(unittest.TestCase):
|
||||
"""
|
||||
Can we start moving the test suite here?
|
||||
"""
|
||||
|
||||
def test_suite_should_move_here(self):
|
||||
"""
|
||||
Great idea!
|
||||
"""
|
||||
assert True is True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
20
Tests/README.md
Normal file
20
Tests/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
Pillow test files.
|
||||
|
||||
Test scripts are named `test_xxx.py` and use the `unittest` module. A base class and helper functions can be found in `helper.py`.
|
||||
|
||||
Run the tests from the root of the Pillow source distribution:
|
||||
|
||||
python selftest.py
|
||||
nosetests Tests/test_*.py
|
||||
|
||||
Or with coverage:
|
||||
|
||||
coverage run --append --include=PIL/* selftest.py
|
||||
coverage run --append --include=PIL/* -m nose Tests/test_*.py
|
||||
coverage report
|
||||
coverage html
|
||||
open htmlcov/index.html
|
||||
|
||||
To run an individual test:
|
||||
|
||||
python Tests/test_image.py
|
|
@ -1,14 +0,0 @@
|
|||
Minimalistic PIL test framework.
|
||||
|
||||
Test scripts are named "test_xxx" and are supposed to output "ok". That's it. To run the tests::
|
||||
|
||||
python setup.py develop
|
||||
|
||||
Run the tests from the root of the Pillow source distribution:
|
||||
|
||||
python selftest.py
|
||||
python Tests/run.py --installed
|
||||
|
||||
To run an individual test:
|
||||
|
||||
python Tests/test_image.py
|
|
@ -1,23 +1,25 @@
|
|||
from tester import *
|
||||
from helper import *
|
||||
|
||||
# not running this test by default. No DOS against travis.
|
||||
# Not running this test by default. No DOS against Travis CI.
|
||||
|
||||
from PIL import PyAccess
|
||||
from PIL import Image
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def iterate_get(size, access):
|
||||
(w,h) = size
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x,y)]
|
||||
access[(x, y)]
|
||||
|
||||
|
||||
def iterate_set(size, access):
|
||||
(w,h) = size
|
||||
(w, h) = size
|
||||
for x in range(w):
|
||||
for y in range(h):
|
||||
access[(x,y)] = (x %256,y%256,0)
|
||||
access[(x, y)] = (x % 256, y % 256, 0)
|
||||
|
||||
|
||||
def timer(func, label, *args):
|
||||
iterations = 5000
|
||||
|
@ -25,27 +27,34 @@ def timer(func, label, *args):
|
|||
for x in range(iterations):
|
||||
func(*args)
|
||||
if time.time()-starttime > 10:
|
||||
print ("%s: breaking at %s iterations, %.6f per iteration"%(label, x+1, (time.time()-starttime)/(x+1.0)))
|
||||
print("%s: breaking at %s iterations, %.6f per iteration" % (
|
||||
label, x+1, (time.time()-starttime)/(x+1.0)))
|
||||
break
|
||||
if x == iterations-1:
|
||||
endtime = time.time()
|
||||
print ("%s: %.4f s %.6f per iteration" %(label, endtime-starttime, (endtime-starttime)/(x+1.0)))
|
||||
print("%s: %.4f s %.6f per iteration" % (
|
||||
label, endtime-starttime, (endtime-starttime)/(x+1.0)))
|
||||
|
||||
def test_direct():
|
||||
im = lena()
|
||||
im.load()
|
||||
#im = Image.new( "RGB", (2000,2000), (1,3,2))
|
||||
caccess = im.im.pixel_access(False)
|
||||
access = PyAccess.new(im, False)
|
||||
|
||||
assert_equal(caccess[(0,0)], access[(0,0)])
|
||||
class BenchCffiAccess(PillowTestCase):
|
||||
|
||||
print ("Size: %sx%s" % im.size)
|
||||
timer(iterate_get, 'PyAccess - get', im.size, access)
|
||||
timer(iterate_set, 'PyAccess - set', im.size, access)
|
||||
timer(iterate_get, 'C-api - get', im.size, caccess)
|
||||
timer(iterate_set, 'C-api - set', im.size, caccess)
|
||||
|
||||
|
||||
def test_direct(self):
|
||||
im = lena()
|
||||
im.load()
|
||||
# im = Image.new( "RGB", (2000, 2000), (1, 3, 2))
|
||||
caccess = im.im.pixel_access(False)
|
||||
access = PyAccess.new(im, False)
|
||||
|
||||
|
||||
self.assertEqual(caccess[(0, 0)], access[(0, 0)])
|
||||
|
||||
print ("Size: %sx%s" % im.size)
|
||||
timer(iterate_get, 'PyAccess - get', im.size, access)
|
||||
timer(iterate_set, 'PyAccess - set', im.size, access)
|
||||
timer(iterate_get, 'C-api - get', im.size, caccess)
|
||||
timer(iterate_set, 'C-api - set', im.size, caccess)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
# End of file
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import sys
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
import tester
|
||||
import helper
|
||||
import timeit
|
||||
|
||||
|
||||
def bench(mode):
|
||||
im = tester.lena(mode)
|
||||
im = helper.lena(mode)
|
||||
get = im.im.getpixel
|
||||
xy = 50, 50 # position shouldn't really matter
|
||||
xy = 50, 50 # position shouldn't really matter
|
||||
t0 = timeit.default_timer()
|
||||
for i in range(1000000):
|
||||
get(xy)
|
||||
|
|
150
Tests/helper.py
150
Tests/helper.py
|
@ -132,59 +132,11 @@ class PillowTestCase(unittest.TestCase):
|
|||
self.addCleanup(self.delete_tempfile, path)
|
||||
return path
|
||||
|
||||
# # require that deprecation warnings are triggered
|
||||
# import warnings
|
||||
# warnings.simplefilter('default')
|
||||
# # temporarily turn off resource warnings that warn about unclosed
|
||||
# # files in the test scripts.
|
||||
# try:
|
||||
# warnings.filterwarnings("ignore", category=ResourceWarning)
|
||||
# except NameError:
|
||||
# # we expect a NameError on py2.x, since it doesn't have ResourceWarnings.
|
||||
# pass
|
||||
# helpers
|
||||
|
||||
import sys
|
||||
py3 = (sys.version_info >= (3, 0))
|
||||
|
||||
# # some test helpers
|
||||
#
|
||||
# _target = None
|
||||
# _tempfiles = []
|
||||
# _logfile = None
|
||||
#
|
||||
#
|
||||
# def success():
|
||||
# import sys
|
||||
# success.count += 1
|
||||
# if _logfile:
|
||||
# print(sys.argv[0], success.count, failure.count, file=_logfile)
|
||||
# return True
|
||||
#
|
||||
#
|
||||
# def failure(msg=None, frame=None):
|
||||
# import sys
|
||||
# import linecache
|
||||
# failure.count += 1
|
||||
# if _target:
|
||||
# if frame is None:
|
||||
# frame = sys._getframe()
|
||||
# while frame.f_globals.get("__name__") != _target.__name__:
|
||||
# frame = frame.f_back
|
||||
# location = (frame.f_code.co_filename, frame.f_lineno)
|
||||
# prefix = "%s:%d: " % location
|
||||
# line = linecache.getline(*location)
|
||||
# print(prefix + line.strip() + " failed:")
|
||||
# if msg:
|
||||
# print("- " + msg)
|
||||
# if _logfile:
|
||||
# print(sys.argv[0], success.count, failure.count, file=_logfile)
|
||||
# return False
|
||||
#
|
||||
# success.count = failure.count = 0
|
||||
#
|
||||
|
||||
|
||||
# helpers
|
||||
|
||||
def fromstring(data):
|
||||
from io import BytesIO
|
||||
|
@ -202,6 +154,9 @@ def tostring(im, format, **options):
|
|||
def lena(mode="RGB", cache={}):
|
||||
from PIL import Image
|
||||
im = None
|
||||
# FIXME: Implement caching to reduce reading from disk but so an original
|
||||
# copy is returned each time and the cached image isn't modified by tests
|
||||
# (for fast, isolated, repeatable tests).
|
||||
# im = cache.get(mode)
|
||||
if im is None:
|
||||
if mode == "RGB":
|
||||
|
@ -215,99 +170,4 @@ def lena(mode="RGB", cache={}):
|
|||
# cache[mode] = im
|
||||
return im
|
||||
|
||||
|
||||
# def assert_image_completely_equal(a, b, msg=None):
|
||||
# if a != b:
|
||||
# failure(msg or "images different")
|
||||
# else:
|
||||
# success()
|
||||
#
|
||||
#
|
||||
# # test runner
|
||||
#
|
||||
# def run():
|
||||
# global _target, _tests, run
|
||||
# import sys
|
||||
# import traceback
|
||||
# _target = sys.modules["__main__"]
|
||||
# run = None # no need to run twice
|
||||
# tests = []
|
||||
# for name, value in list(vars(_target).items()):
|
||||
# if name[:5] == "test_" and type(value) is type(success):
|
||||
# tests.append((value.__code__.co_firstlineno, name, value))
|
||||
# tests.sort() # sort by line
|
||||
# for lineno, name, func in tests:
|
||||
# try:
|
||||
# _tests = []
|
||||
# func()
|
||||
# for func, args in _tests:
|
||||
# func(*args)
|
||||
# except:
|
||||
# t, v, tb = sys.exc_info()
|
||||
# tb = tb.tb_next
|
||||
# if tb:
|
||||
# failure(frame=tb.tb_frame)
|
||||
# traceback.print_exception(t, v, tb)
|
||||
# else:
|
||||
# print("%s:%d: cannot call test function: %s" % (
|
||||
# sys.argv[0], lineno, v))
|
||||
# failure.count += 1
|
||||
#
|
||||
#
|
||||
# def yield_test(function, *args):
|
||||
# # collect delayed/generated tests
|
||||
# _tests.append((function, args))
|
||||
#
|
||||
#
|
||||
# def skip(msg=None):
|
||||
# import os
|
||||
# print("skip")
|
||||
# os._exit(0) # don't run exit handlers
|
||||
#
|
||||
#
|
||||
# def ignore(pattern):
|
||||
# """Tells the driver to ignore messages matching the pattern, for the
|
||||
# duration of the current test."""
|
||||
# print('ignore: %s' % pattern)
|
||||
#
|
||||
#
|
||||
# def _setup():
|
||||
# global _logfile
|
||||
#
|
||||
# import sys
|
||||
# if "--coverage" in sys.argv:
|
||||
# # Temporary: ignore PendingDeprecationWarning from Coverage (Py3.4)
|
||||
# with warnings.catch_warnings():
|
||||
# warnings.simplefilter("ignore")
|
||||
# import coverage
|
||||
# cov = coverage.coverage(auto_data=True, include="PIL/*")
|
||||
# cov.start()
|
||||
#
|
||||
# def report():
|
||||
# if run:
|
||||
# run()
|
||||
# if success.count and not failure.count:
|
||||
# print("ok")
|
||||
# # only clean out tempfiles if test passed
|
||||
# import os
|
||||
# import os.path
|
||||
# import tempfile
|
||||
# for file in _tempfiles:
|
||||
# try:
|
||||
# os.remove(file)
|
||||
# except OSError:
|
||||
# pass # report?
|
||||
# temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
|
||||
# try:
|
||||
# os.rmdir(temp_root)
|
||||
# except OSError:
|
||||
# pass
|
||||
#
|
||||
# import atexit
|
||||
# atexit.register(report)
|
||||
#
|
||||
# if "--log" in sys.argv:
|
||||
# _logfile = open("test.log", "a")
|
||||
#
|
||||
#
|
||||
# _setup()
|
||||
# End of file
|
||||
|
|
BIN
Tests/images/16bit.cropped.j2k
Normal file
BIN
Tests/images/16bit.cropped.j2k
Normal file
Binary file not shown.
BIN
Tests/images/16bit.cropped.jp2
Normal file
BIN
Tests/images/16bit.cropped.jp2
Normal file
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
from tester import *
|
||||
from helper import *
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
|
@ -6,32 +6,37 @@ from tester import *
|
|||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32 bit machine, as well as any smallish things (like
|
||||
# raspberrypis).
|
||||
# Raspberry Pis).
|
||||
|
||||
from PIL import Image
|
||||
try:
|
||||
import numpy as np
|
||||
except:
|
||||
skip()
|
||||
|
||||
ydim = 32769
|
||||
xdim = 48000
|
||||
f = tempfile('temp.png')
|
||||
sys.exit("Skipping: Numpy not installed")
|
||||
|
||||
def _write_png(xdim,ydim):
|
||||
dtype = np.uint8
|
||||
a = np.zeros((xdim, ydim), dtype=dtype)
|
||||
im = Image.fromarray(a, 'L')
|
||||
im.save(f)
|
||||
success()
|
||||
|
||||
def test_large():
|
||||
""" succeeded prepatch"""
|
||||
_write_png(xdim,ydim)
|
||||
def test_2gpx():
|
||||
"""failed prepatch"""
|
||||
_write_png(xdim,xdim)
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
|
||||
class LargeMemoryNumpyTest(PillowTestCase):
|
||||
|
||||
def _write_png(self, xdim, ydim):
|
||||
dtype = np.uint8
|
||||
a = np.zeros((xdim, ydim), dtype=dtype)
|
||||
f = self.tempfile('temp.png')
|
||||
im = Image.fromarray(a, 'L')
|
||||
im.save(f)
|
||||
|
||||
def test_large(self):
|
||||
""" succeeded prepatch"""
|
||||
self._write_png(XDIM, YDIM)
|
||||
|
||||
def test_2gpx(self):
|
||||
"""failed prepatch"""
|
||||
self._write_png(XDIM, XDIM)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
# End of file
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from tester import *
|
||||
from helper import *
|
||||
|
||||
# This test is not run automatically.
|
||||
#
|
||||
|
@ -6,22 +6,31 @@ from tester import *
|
|||
# second test. Running this automatically would amount to a denial of
|
||||
# service on our testing infrastructure. I expect this test to fail
|
||||
# on any 32 bit machine, as well as any smallish things (like
|
||||
# raspberrypis). It does succeed on a 3gb Ubuntu 12.04x64 VM on python
|
||||
# 2.7 an 3.2
|
||||
# Raspberry Pis). It does succeed on a 3gb Ubuntu 12.04x64 VM on Python
|
||||
# 2.7 an 3.2.
|
||||
|
||||
from PIL import Image
|
||||
ydim = 32769
|
||||
xdim = 48000
|
||||
f = tempfile('temp.png')
|
||||
YDIM = 32769
|
||||
XDIM = 48000
|
||||
|
||||
def _write_png(xdim,ydim):
|
||||
im = Image.new('L',(xdim,ydim),(0))
|
||||
im.save(f)
|
||||
success()
|
||||
|
||||
def test_large():
|
||||
""" succeeded prepatch"""
|
||||
_write_png(xdim,ydim)
|
||||
def test_2gpx():
|
||||
"""failed prepatch"""
|
||||
_write_png(xdim,xdim)
|
||||
class LargeMemoryTest(PillowTestCase):
|
||||
|
||||
def _write_png(self, xdim, ydim):
|
||||
f = self.tempfile('temp.png')
|
||||
im = Image.new('L', (xdim, ydim), (0))
|
||||
im.save(f)
|
||||
|
||||
def test_large(self):
|
||||
""" succeeded prepatch"""
|
||||
self._write_png(XDIM, YDIM)
|
||||
|
||||
def test_2gpx(self):
|
||||
"""failed prepatch"""
|
||||
self._write_png(XDIM, XDIM)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
# End of file
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# brute-force search for access descriptor hash table
|
||||
|
||||
import random
|
||||
|
||||
modes = [
|
||||
"1",
|
||||
"L", "LA",
|
||||
|
@ -13,12 +11,14 @@ modes = [
|
|||
"YCbCr",
|
||||
]
|
||||
|
||||
|
||||
def hash(s, i):
|
||||
# djb2 hash: multiply by 33 and xor character
|
||||
for c in s:
|
||||
i = (((i<<5) + i) ^ ord(c)) & 0xffffffff
|
||||
i = (((i << 5) + i) ^ ord(c)) & 0xffffffff
|
||||
return i
|
||||
|
||||
|
||||
def check(size, i0):
|
||||
h = [None] * size
|
||||
for m in modes:
|
||||
|
|
135
Tests/run.py
135
Tests/run.py
|
@ -1,135 +0,0 @@
|
|||
from __future__ import print_function
|
||||
|
||||
# minimal test runner
|
||||
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
root = os.path.dirname(__file__)
|
||||
except NameError:
|
||||
root = os.path.dirname(sys.argv[0])
|
||||
|
||||
if not os.path.isfile("PIL/Image.py"):
|
||||
print("***", "please run this script from the PIL development directory as")
|
||||
print("***", "$ python Tests/run.py")
|
||||
sys.exit(1)
|
||||
|
||||
print("-"*68)
|
||||
|
||||
python_options = []
|
||||
tester_options = []
|
||||
|
||||
if "--installed" not in sys.argv:
|
||||
os.environ["PYTHONPATH"] = "."
|
||||
|
||||
if "--coverage" in sys.argv:
|
||||
tester_options.append("--coverage")
|
||||
|
||||
if "--log" in sys.argv:
|
||||
tester_options.append("--log")
|
||||
|
||||
files = glob.glob(os.path.join(root, "test_*.py"))
|
||||
files.sort()
|
||||
|
||||
success = failure = 0
|
||||
include = [x for x in sys.argv[1:] if x[:2] != "--"]
|
||||
skipped = []
|
||||
failed = []
|
||||
|
||||
python_options = " ".join(python_options)
|
||||
tester_options = " ".join(tester_options)
|
||||
|
||||
ignore_re = re.compile('^ignore: (.*)$', re.MULTILINE)
|
||||
|
||||
for file in files:
|
||||
test, ext = os.path.splitext(os.path.basename(file))
|
||||
if include and test not in include:
|
||||
continue
|
||||
print("running", test, "...")
|
||||
# 2>&1 works on unix and on modern windowses. we might care about
|
||||
# very old Python versions, but not ancient microsoft products :-)
|
||||
out = os.popen("%s %s -u %s %s 2>&1" % (
|
||||
sys.executable, python_options, file, tester_options
|
||||
))
|
||||
result = out.read()
|
||||
|
||||
result_lines = result.splitlines()
|
||||
if len(result_lines):
|
||||
if result_lines[0] == "ignore_all_except_last_line":
|
||||
result = result_lines[-1]
|
||||
|
||||
# Extract any ignore patterns
|
||||
ignore_pats = ignore_re.findall(result)
|
||||
result = ignore_re.sub('', result)
|
||||
|
||||
try:
|
||||
def fix_re(p):
|
||||
if not p.startswith('^'):
|
||||
p = '^' + p
|
||||
if not p.endswith('$'):
|
||||
p += '$'
|
||||
return p
|
||||
|
||||
ignore_res = [re.compile(fix_re(p), re.MULTILINE) for p in ignore_pats]
|
||||
except:
|
||||
print('(bad ignore patterns %r)' % ignore_pats)
|
||||
ignore_res = []
|
||||
|
||||
for r in ignore_res:
|
||||
result = r.sub('', result)
|
||||
|
||||
result = result.strip()
|
||||
|
||||
if result == "ok":
|
||||
result = None
|
||||
elif result == "skip":
|
||||
print("---", "skipped") # FIXME: driver should include a reason
|
||||
skipped.append(test)
|
||||
continue
|
||||
elif not result:
|
||||
result = "(no output)"
|
||||
status = out.close()
|
||||
if status or result:
|
||||
if status:
|
||||
print("=== error", status)
|
||||
if result:
|
||||
if result[-3:] == "\nok":
|
||||
# if there's an ok at the end, it's not really ok
|
||||
result = result[:-3]
|
||||
print(result)
|
||||
failed.append(test)
|
||||
else:
|
||||
success += 1
|
||||
|
||||
print("-"*68)
|
||||
|
||||
temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
|
||||
tempfiles = glob.glob(os.path.join(temp_root, "temp_*"))
|
||||
if tempfiles:
|
||||
print("===", "remaining temporary files")
|
||||
for file in tempfiles:
|
||||
print(file)
|
||||
print("-"*68)
|
||||
|
||||
|
||||
def tests(n):
|
||||
if n == 1:
|
||||
return "1 test"
|
||||
else:
|
||||
return "%d tests" % n
|
||||
|
||||
if skipped:
|
||||
print("---", tests(len(skipped)), "skipped:")
|
||||
print(", ".join(skipped))
|
||||
if failed:
|
||||
failure = len(failed)
|
||||
print("***", tests(failure), "of", (success + failure), "failed:")
|
||||
print(", ".join(failed))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(tests(success), "passed.")
|
|
@ -120,6 +120,42 @@ class TestFileJpeg2k(PillowTestCase):
|
|||
self.assertEqual(j2k.mode, 'RGBA')
|
||||
self.assertEqual(jp2.mode, 'RGBA')
|
||||
|
||||
def test_16bit_monochrome_has_correct_mode(self):
|
||||
|
||||
j2k = Image.open('Tests/images/16bit.cropped.j2k')
|
||||
jp2 = Image.open('Tests/images/16bit.cropped.jp2')
|
||||
|
||||
j2k.load()
|
||||
jp2.load()
|
||||
|
||||
self.assertEqual(j2k.mode, 'I;16')
|
||||
self.assertEqual(jp2.mode, 'I;16')
|
||||
|
||||
def test_16bit_monchrome_jp2_like_tiff(self):
|
||||
|
||||
tiff_16bit = Image.open('Tests/images/16bit.cropped.tif')
|
||||
jp2 = Image.open('Tests/images/16bit.cropped.jp2')
|
||||
self.assert_image_similar(jp2, tiff_16bit, 1e-3)
|
||||
|
||||
def test_16bit_monchrome_j2k_like_tiff(self):
|
||||
|
||||
tiff_16bit = Image.open('Tests/images/16bit.cropped.tif')
|
||||
j2k = Image.open('Tests/images/16bit.cropped.j2k')
|
||||
self.assert_image_similar(j2k, tiff_16bit, 1e-3)
|
||||
|
||||
def test_16bit_j2k_roundtrips(self):
|
||||
|
||||
j2k = Image.open('Tests/images/16bit.cropped.j2k')
|
||||
im = self.roundtrip(j2k)
|
||||
self.assert_image_equal(im, j2k)
|
||||
|
||||
def test_16bit_jp2_roundtrips(self):
|
||||
|
||||
jp2 = Image.open('Tests/images/16bit.cropped.jp2')
|
||||
im = self.roundtrip(jp2)
|
||||
self.assert_image_equal(im, jp2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
|
|
388
Tests/tester.py
388
Tests/tester.py
|
@ -1,388 +0,0 @@
|
|||
from __future__ import print_function
|
||||
|
||||
# require that deprecation warnings are triggered
|
||||
import warnings
|
||||
warnings.simplefilter('default')
|
||||
# temporarily turn off resource warnings that warn about unclosed
|
||||
# files in the test scripts.
|
||||
try:
|
||||
warnings.filterwarnings("ignore", category=ResourceWarning)
|
||||
except NameError:
|
||||
# we expect a NameError on py2.x, since it doesn't have ResourceWarnings.
|
||||
pass
|
||||
|
||||
import sys
|
||||
py3 = (sys.version_info >= (3, 0))
|
||||
|
||||
# some test helpers
|
||||
|
||||
_target = None
|
||||
_tempfiles = []
|
||||
_logfile = None
|
||||
|
||||
|
||||
def success():
|
||||
import sys
|
||||
success.count += 1
|
||||
if _logfile:
|
||||
print(sys.argv[0], success.count, failure.count, file=_logfile)
|
||||
return True
|
||||
|
||||
|
||||
def failure(msg=None, frame=None):
|
||||
import sys
|
||||
import linecache
|
||||
failure.count += 1
|
||||
if _target:
|
||||
if frame is None:
|
||||
frame = sys._getframe()
|
||||
while frame.f_globals.get("__name__") != _target.__name__:
|
||||
frame = frame.f_back
|
||||
location = (frame.f_code.co_filename, frame.f_lineno)
|
||||
prefix = "%s:%d: " % location
|
||||
line = linecache.getline(*location)
|
||||
print(prefix + line.strip() + " failed:")
|
||||
if msg:
|
||||
print("- " + msg)
|
||||
if _logfile:
|
||||
print(sys.argv[0], success.count, failure.count, file=_logfile)
|
||||
return False
|
||||
|
||||
success.count = failure.count = 0
|
||||
|
||||
|
||||
# predicates
|
||||
|
||||
def assert_true(v, msg=None):
|
||||
if v:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %r, expected true value" % v)
|
||||
|
||||
|
||||
def assert_false(v, msg=None):
|
||||
if v:
|
||||
failure(msg or "got %r, expected false value" % v)
|
||||
else:
|
||||
success()
|
||||
|
||||
|
||||
def assert_equal(a, b, msg=None):
|
||||
if a == b:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %r, expected %r" % (a, b))
|
||||
|
||||
|
||||
def assert_almost_equal(a, b, msg=None, eps=1e-6):
|
||||
if abs(a-b) < eps:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %r, expected %r" % (a, b))
|
||||
|
||||
|
||||
def assert_deep_equal(a, b, msg=None):
|
||||
try:
|
||||
if len(a) == len(b):
|
||||
if all([x == y for x, y in zip(a, b)]):
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %s, expected %s" % (a, b))
|
||||
else:
|
||||
failure(msg or "got length %s, expected %s" % (len(a), len(b)))
|
||||
except:
|
||||
assert_equal(a, b, msg)
|
||||
|
||||
|
||||
def assert_greater(a, b, msg=None):
|
||||
if a > b:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "%r unexpectedly not greater than %r" % (a, b))
|
||||
|
||||
|
||||
def assert_greater_equal(a, b, msg=None):
|
||||
if a >= b:
|
||||
success()
|
||||
else:
|
||||
failure(
|
||||
msg or "%r unexpectedly not greater than or equal to %r" % (a, b))
|
||||
|
||||
|
||||
def assert_less(a, b, msg=None):
|
||||
if a < b:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "%r unexpectedly not less than %r" % (a, b))
|
||||
|
||||
|
||||
def assert_less_equal(a, b, msg=None):
|
||||
if a <= b:
|
||||
success()
|
||||
else:
|
||||
failure(
|
||||
msg or "%r unexpectedly not less than or equal to %r" % (a, b))
|
||||
|
||||
|
||||
def assert_is_instance(a, b, msg=None):
|
||||
if isinstance(a, b):
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %r, expected %r" % (type(a), b))
|
||||
|
||||
|
||||
def assert_in(a, b, msg=None):
|
||||
if a in b:
|
||||
success()
|
||||
else:
|
||||
failure(msg or "%r unexpectedly not in %r" % (a, b))
|
||||
|
||||
|
||||
def assert_match(v, pattern, msg=None):
|
||||
import re
|
||||
if re.match(pattern, v):
|
||||
success()
|
||||
else:
|
||||
failure(msg or "got %r, doesn't match pattern %r" % (v, pattern))
|
||||
|
||||
|
||||
def assert_exception(exc_class, func):
|
||||
import sys
|
||||
import traceback
|
||||
try:
|
||||
func()
|
||||
except exc_class:
|
||||
success()
|
||||
except:
|
||||
failure("expected %r exception, got %r" % (
|
||||
exc_class.__name__, sys.exc_info()[0].__name__))
|
||||
traceback.print_exc()
|
||||
else:
|
||||
failure("expected %r exception, got no exception" % exc_class.__name__)
|
||||
|
||||
|
||||
def assert_no_exception(func):
|
||||
import sys
|
||||
import traceback
|
||||
try:
|
||||
func()
|
||||
except:
|
||||
failure("expected no exception, got %r" % sys.exc_info()[0].__name__)
|
||||
traceback.print_exc()
|
||||
else:
|
||||
success()
|
||||
|
||||
|
||||
def assert_warning(warn_class, func):
|
||||
# note: this assert calls func three times!
|
||||
import warnings
|
||||
|
||||
def warn_error(message, category=UserWarning, **options):
|
||||
raise category(message)
|
||||
|
||||
def warn_ignore(message, category=UserWarning, **options):
|
||||
pass
|
||||
warn = warnings.warn
|
||||
result = None
|
||||
try:
|
||||
warnings.warn = warn_ignore
|
||||
assert_no_exception(func)
|
||||
result = func()
|
||||
warnings.warn = warn_error
|
||||
assert_exception(warn_class, func)
|
||||
finally:
|
||||
warnings.warn = warn # restore
|
||||
return result
|
||||
|
||||
# helpers
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
def fromstring(data):
|
||||
from PIL import Image
|
||||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def tostring(im, format, **options):
|
||||
out = BytesIO()
|
||||
im.save(out, format, **options)
|
||||
return out.getvalue()
|
||||
|
||||
|
||||
def lena(mode="RGB", cache={}):
|
||||
from PIL import Image
|
||||
im = cache.get(mode)
|
||||
if im is None:
|
||||
if mode == "RGB":
|
||||
im = Image.open("Tests/images/lena.ppm")
|
||||
elif mode == "F":
|
||||
im = lena("L").convert(mode)
|
||||
elif mode[:4] == "I;16":
|
||||
im = lena("I").convert(mode)
|
||||
else:
|
||||
im = lena("RGB").convert(mode)
|
||||
cache[mode] = im
|
||||
return im
|
||||
|
||||
|
||||
def assert_image(im, mode, size, msg=None):
|
||||
if mode is not None and im.mode != mode:
|
||||
failure(msg or "got mode %r, expected %r" % (im.mode, mode))
|
||||
elif size is not None and im.size != size:
|
||||
failure(msg or "got size %r, expected %r" % (im.size, size))
|
||||
else:
|
||||
success()
|
||||
|
||||
|
||||
def assert_image_equal(a, b, msg=None):
|
||||
if a.mode != b.mode:
|
||||
failure(msg or "got mode %r, expected %r" % (a.mode, b.mode))
|
||||
elif a.size != b.size:
|
||||
failure(msg or "got size %r, expected %r" % (a.size, b.size))
|
||||
elif a.tobytes() != b.tobytes():
|
||||
failure(msg or "got different content")
|
||||
else:
|
||||
success()
|
||||
|
||||
|
||||
def assert_image_completely_equal(a, b, msg=None):
|
||||
if a != b:
|
||||
failure(msg or "images different")
|
||||
else:
|
||||
success()
|
||||
|
||||
|
||||
def assert_image_similar(a, b, epsilon, msg=None):
|
||||
epsilon = float(epsilon)
|
||||
if a.mode != b.mode:
|
||||
return failure(msg or "got mode %r, expected %r" % (a.mode, b.mode))
|
||||
elif a.size != b.size:
|
||||
return failure(msg or "got size %r, expected %r" % (a.size, b.size))
|
||||
diff = 0
|
||||
try:
|
||||
ord(b'0')
|
||||
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
|
||||
diff += abs(ord(abyte)-ord(bbyte))
|
||||
except:
|
||||
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
|
||||
diff += abs(abyte-bbyte)
|
||||
ave_diff = float(diff)/(a.size[0]*a.size[1])
|
||||
if epsilon < ave_diff:
|
||||
return failure(
|
||||
msg or "average pixel value difference %.4f > epsilon %.4f" % (
|
||||
ave_diff, epsilon))
|
||||
else:
|
||||
return success()
|
||||
|
||||
|
||||
def tempfile(template, *extra):
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import tempfile
|
||||
files = []
|
||||
root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
|
||||
try:
|
||||
os.mkdir(root)
|
||||
except OSError:
|
||||
pass
|
||||
for temp in (template,) + extra:
|
||||
assert temp[:5] in ("temp.", "temp_")
|
||||
name = os.path.basename(sys.argv[0])
|
||||
name = temp[:4] + os.path.splitext(name)[0][4:]
|
||||
name = name + "_%d" % len(_tempfiles) + temp[4:]
|
||||
name = os.path.join(root, name)
|
||||
files.append(name)
|
||||
_tempfiles.extend(files)
|
||||
return files[0]
|
||||
|
||||
|
||||
# test runner
|
||||
|
||||
def run():
|
||||
global _target, _tests, run
|
||||
import sys
|
||||
import traceback
|
||||
_target = sys.modules["__main__"]
|
||||
run = None # no need to run twice
|
||||
tests = []
|
||||
for name, value in list(vars(_target).items()):
|
||||
if name[:5] == "test_" and type(value) is type(success):
|
||||
tests.append((value.__code__.co_firstlineno, name, value))
|
||||
tests.sort() # sort by line
|
||||
for lineno, name, func in tests:
|
||||
try:
|
||||
_tests = []
|
||||
func()
|
||||
for func, args in _tests:
|
||||
func(*args)
|
||||
except:
|
||||
t, v, tb = sys.exc_info()
|
||||
tb = tb.tb_next
|
||||
if tb:
|
||||
failure(frame=tb.tb_frame)
|
||||
traceback.print_exception(t, v, tb)
|
||||
else:
|
||||
print("%s:%d: cannot call test function: %s" % (
|
||||
sys.argv[0], lineno, v))
|
||||
failure.count += 1
|
||||
|
||||
|
||||
def yield_test(function, *args):
|
||||
# collect delayed/generated tests
|
||||
_tests.append((function, args))
|
||||
|
||||
|
||||
def skip(msg=None):
|
||||
import os
|
||||
print("skip")
|
||||
os._exit(0) # don't run exit handlers
|
||||
|
||||
|
||||
def ignore(pattern):
|
||||
"""Tells the driver to ignore messages matching the pattern, for the
|
||||
duration of the current test."""
|
||||
print('ignore: %s' % pattern)
|
||||
|
||||
|
||||
def _setup():
|
||||
global _logfile
|
||||
|
||||
import sys
|
||||
if "--coverage" in sys.argv:
|
||||
# Temporary: ignore PendingDeprecationWarning from Coverage (Py3.4)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
import coverage
|
||||
cov = coverage.coverage(auto_data=True, include="PIL/*")
|
||||
cov.start()
|
||||
|
||||
def report():
|
||||
if run:
|
||||
run()
|
||||
if success.count and not failure.count:
|
||||
print("ok")
|
||||
# only clean out tempfiles if test passed
|
||||
import os
|
||||
import os.path
|
||||
import tempfile
|
||||
for file in _tempfiles:
|
||||
try:
|
||||
os.remove(file)
|
||||
except OSError:
|
||||
pass # report?
|
||||
temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
|
||||
try:
|
||||
os.rmdir(temp_root)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
import atexit
|
||||
atexit.register(report)
|
||||
|
||||
if "--log" in sys.argv:
|
||||
_logfile = open("test.log", "a")
|
||||
|
||||
|
||||
_setup()
|
|
@ -135,6 +135,56 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
||||
int shift = 16 - in->comps[0].prec;
|
||||
int offset = in->comps[0].sgnd ? 1 << (in->comps[0].prec - 1) : 0;
|
||||
int csiz = (in->comps[0].prec + 7) >> 3;
|
||||
|
||||
unsigned x, y;
|
||||
|
||||
if (csiz == 3)
|
||||
csiz = 4;
|
||||
|
||||
if (shift < 0)
|
||||
offset += 1 << (-shift - 1);
|
||||
|
||||
switch (csiz) {
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x)
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x)
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x)
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
|
@ -466,6 +516,8 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
|
||||
static const struct j2k_decode_unpacker j2k_unpackers[] = {
|
||||
{ "L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l },
|
||||
{ "I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
|
||||
{ "I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
|
||||
{ "LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la },
|
||||
{ "RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb },
|
||||
|
|
|
@ -88,6 +88,22 @@ j2k_pack_l(Imaging im, UINT8 *buf,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
j2k_pack_i16(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
UINT8 *ptr = buf;
|
||||
unsigned x,y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
*ptr++ = *data++;
|
||||
*ptr++ = *data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2k_pack_la(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
|
@ -247,6 +263,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
|||
j2k_pack_tile_t pack;
|
||||
int ret = -1;
|
||||
|
||||
unsigned prec = 8;
|
||||
unsigned bpp = 8;
|
||||
|
||||
stream = opj_stream_default_create(OPJ_FALSE);
|
||||
|
||||
if (!stream) {
|
||||
|
@ -271,6 +290,18 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
|||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_l;
|
||||
} else if (strcmp (im->mode, "I;16") == 0){
|
||||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_i16;
|
||||
prec = 16;
|
||||
bpp = 12;
|
||||
} else if (strcmp (im->mode, "I;16B") == 0){
|
||||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_i16;
|
||||
prec = 16;
|
||||
bpp = 12;
|
||||
} else if (strcmp (im->mode, "LA") == 0) {
|
||||
components = 2;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
|
@ -298,8 +329,8 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
|||
image_params[n].w = im->xsize;
|
||||
image_params[n].h = im->ysize;
|
||||
image_params[n].x0 = image_params[n].y0 = 0;
|
||||
image_params[n].prec = 8;
|
||||
image_params[n].bpp = 8;
|
||||
image_params[n].prec = prec;
|
||||
image_params[n].bpp = bpp;
|
||||
image_params[n].sgnd = 0;
|
||||
}
|
||||
|
||||
|
@ -442,7 +473,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
|||
|
||||
num_tiles = tiles_x * tiles_y;
|
||||
|
||||
state->buffer = malloc (tile_width * tile_height * components);
|
||||
state->buffer = malloc (tile_width * tile_height * components * prec / 8);
|
||||
|
||||
tile_ndx = 0;
|
||||
for (y = 0; y < tiles_y; ++y) {
|
||||
|
@ -474,7 +505,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
|||
|
||||
pack(im, state->buffer, pixx, pixy, pixw, pixh);
|
||||
|
||||
data_size = pixw * pixh * components;
|
||||
data_size = pixw * pixh * components * prec / 8;
|
||||
|
||||
if (!opj_write_tile(codec, tile_ndx++, state->buffer,
|
||||
data_size, stream)) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user