Merge branch 'devel' of github.com:quintusdias/glymur into devel

This commit is contained in:
John Evans 2014-03-11 15:47:23 -04:00
commit 96f32395eb
11 changed files with 167 additions and 250 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.pyc

View file

@ -13,7 +13,7 @@ both read and write JPEG 2000 files, but you may wish to install version 2.0
or the 2.0+ version from OpenJPEG's development trunk for better performance. or the 2.0+ version from OpenJPEG's development trunk for better performance.
If you do that, you should compile it as a shared library (named *openjp2* If you do that, you should compile it as a shared library (named *openjp2*
instead of *openjpeg*) from the developmental source that you can retrieve instead of *openjpeg*) from the developmental source that you can retrieve
via subversion. As of this time of writing, svn revision r2369 works. via subversion. As of this time of writing, svn revision r2651 works.
You should also download the test data for the purpose of configuring You should also download the test data for the purpose of configuring
and running OpenJPEG's test suite, check their instructions for all this. and running OpenJPEG's test suite, check their instructions for all this.
You should set the **OPJ_DATA_ROOT** environment variable for the purpose You should set the **OPJ_DATA_ROOT** environment variable for the purpose

View file

@ -39,16 +39,6 @@ from .lib import openjp2 as opj2
from . import version from . import version
from .lib import c as libc from .lib import c as libc
# Codestream lengths for 24fps, 48fps
CINEMA_24_CS = 1302083
CINEMA_48_CS = 651041
# Maximum size per color components for 2K and 4K at 24 fps
COMP_24_CS = 1041666
# Maximum size per color components for 2K at 48 fps
COMP_48_CS = 520833
JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ', JP2_IDS = ['colr', 'cdef', 'cmap', 'jp2c', 'ftyp', 'ihdr', 'jp2h', 'jP ',
'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ', 'pclr', 'res ', 'resc', 'resd', 'xml ', 'ulst', 'uinf', 'url ',
'uuid'] 'uuid']
@ -176,6 +166,11 @@ class Jp2k(Jp2kBox):
fps : int fps : int
Frames per second, should be either 24 or 48. Frames per second, should be either 24 or 48.
""" """
if version.openjpeg_version_tuple[0] == 1:
msg = "Writing Cinema2K or Cinema4K files is not supported with "
msg += 'openjpeg library versions less than 2.0.1.'
raise IOError(msg)
if cinema_mode == 'cinema2k': if cinema_mode == 'cinema2k':
if fps == 24: if fps == 24:
cparams.cp_cinema = CINEMA_MODE['cinema2k_24'] cparams.cp_cinema = CINEMA_MODE['cinema2k_24']
@ -183,90 +178,10 @@ class Jp2k(Jp2kBox):
cparams.cp_cinema = CINEMA_MODE['cinema2k_48'] cparams.cp_cinema = CINEMA_MODE['cinema2k_48']
else: else:
raise IOError('Cinema2K frame rate must be either 24 or 48.') raise IOError('Cinema2K frame rate must be either 24 or 48.')
cparams.cp_rsiz = RSIZ['CINEMA2K']
else: else:
cparams.cp_cinema = CINEMA_MODE['cinema4k_24'] cparams.cp_cinema = CINEMA_MODE['cinema4k_24']
cparams.cp_rsiz = RSIZ['CINEMA4K']
return
# No tiling
cparams.tile_size_on = opj2.FALSE
cparams.cp_tdx = 1
cparams.cp_tdy = 1
# One tile part for each component.
cparams.tp_flag = ord('C')
cparams.tp_on = 1
# tile and image shall be as (0,0)
cparams.cp_tx0 = 0
cparams.cp_ty0 = 0
cparams.image_offset_x0 = 0
cparams.image_offset_y0 = 0
# Codeblock size = 32 * 32
cparams.cblockw_init = 32
cparams.cblockh_init = 32
# code block style, no mode switch enabled.
cparams.mode = 0
# no ROI
cparams.roi_compno = -1
# no subsampling
cparams.subsampling_dx = 1
cparams.subsampling_dy = 1
# 9-7 transform
cparams.irreversible = 1
# number of layers
if cparams.tcp_numlayers > 1:
# TODO: warning or error
cparams.tcp_numlayers = 1
if cinema_mode == 'cinema2k':
if cparams.numresolution > 6:
# TODO: warning or error
cparams.numresolution = 6
else:
if cparams.numresolution < 2:
# TODO: warning or error
cparams.numresolution = 1
elif cparams.numresolution > 7:
cparams.numresolution = 7
# precincts
cparams.csty |= 0x01
cparams.res_spec = cparams.numresolution - 1
for j in range(cparams.res_spec):
cparams.prcw_init[j] = 256
cparams.prch_init[j] = 256
# Progression order shall be CPRL
cparams.prog_order = PROGRESSION_ORDER['CPRL']
# progression order changes not allowed for 2K
if cinema_mode == 'cinema2k':
cparams.numpocs = 0
else:
cparams.poc[0].tile = 1
cparams.poc[0].resno0 = 0
cparams.poc[0].compno0 = 0
cparams.poc[0].layno1 = 1
cparams.poc[0].resno1 = cparams.numresolution - 1
cparams.poc[0].compno1 = 3
cparams.poc[0].prg1 = PROGRESSION_ORDER['CPRL']
cparams.poc[1].tile = 1
cparams.poc[1].resno0 = 0
cparams.poc[1].compno0 = 0
cparams.poc[1].layno1 = 1
cparams.poc[1].resno1 = cparams.numresolution
cparams.poc[1].compno1 = 3
cparams.poc[1].prg1 = PROGRESSION_ORDER['CPRL']
cparams.numpocs = 2
def _populate_cparams(self, **kwargs): def _populate_cparams(self, **kwargs):
"""Populate compression parameters structure from input arguments. """Populate compression parameters structure from input arguments.
@ -421,6 +336,10 @@ class Jp2k(Jp2kBox):
colorspace : int colorspace : int
Either CLRSPC_SRGB or CLRSPC_GRAY Either CLRSPC_SRGB or CLRSPC_GRAY
""" """
if (('cinema2k' in kwargs or 'cinema4k' in kwargs) and
(len(set(kwargs)) > 1)):
msg = "Cannot specify cinema2k/cinema4k along with other options."
raise IOError(msg)
if 'cratios' in kwargs and 'psnr' in kwargs: if 'cratios' in kwargs and 'psnr' in kwargs:
msg = "Cannot specify cratios and psnr together." msg = "Cannot specify cratios and psnr together."
@ -465,6 +384,8 @@ class Jp2k(Jp2kBox):
Code block size (DY, DX). Code block size (DY, DX).
cinema2k : int, optional cinema2k : int, optional
frames per second, either 24 or 48 frames per second, either 24 or 48
cinema4k : bool, optional
Set to True to specify Cinema4K mode, defaults to false.
colorspace : str, optional colorspace : str, optional
Either 'rgb' or 'gray'. Either 'rgb' or 'gray'.
cratios : iterable cratios : iterable
@ -596,48 +517,6 @@ class Jp2k(Jp2kBox):
self.parse() self.parse()
def _set_cinema_rate(self, cparams, image):
max_rate = 0
temp_rate = 0
cparams.cp_disto_alloc = 1
num_pixels = image.contents.comps[0].w * image.contents.comps[0].h
num_samples = num_pixels * image.contents.numcomps
rate_numerator = num_samples * image.contents.comps[0].prec
rate_denominator = 8 * image.contents.comps[0].dx
rate_denominator *= image.contents.comps[0].dy
if cparams.cp_cinema in [CINEMA_MODE['cinema2k_24'],
CINEMA_MODE['cinema4k_24']]:
max_rate = rate_numerator / (rate_denominator * CINEMA_24_CS)
if cparams.tcp_rates[0] == 0:
cparams.tcp_rates[0] = max_rate
else:
temp_rate = rate_numerator / (cparams.tcp_rates[0] * 8 * num_pixels)
if temp_rate > CINEMA_24_CS:
# TODO warning, reset
cparams.tcp_rates[0] = max_rate
else:
# TODO warning
pass
cparams.max_comp_size = COMP_24_CS
else:
max_rate = rate_numerator / (rate_denominator * CINEMA_48_CS)
if cparams.tcp_rates[0] == 0:
cparams.tcp_rates[0] = max_rate
else:
temp_rate = rate_numerator / (cparams.tcp_rates[0] * 8 * num_pixels)
if temp_rate > CINEMA_48_CS:
# TODO warning, reset
cparams.tcp_rates[0] = max_rate
else:
# TODO warning
pass
cparams.max_comp_size = COMP_48_CS
def _write_openjp2(self, img_array, verbose=False, **kwargs): def _write_openjp2(self, img_array, verbose=False, **kwargs):
""" """
Write JPEG 2000 file using OpenJPEG 2.0 interface. Write JPEG 2000 file using OpenJPEG 2.0 interface.
@ -657,11 +536,6 @@ class Jp2k(Jp2kBox):
_populate_image_struct(cparams, image, img_array) _populate_image_struct(cparams, image, img_array)
if 'cinema2k' in kwargs:
self._set_cinema_rate(cparams, image)
if 'cinema4k' in kwargs:
self._set_cinema_rate(cparams, image)
codec = opj2.create_compress(cparams.codec_fmt) codec = opj2.create_compress(cparams.codec_fmt)
stack.callback(opj2.destroy_codec, codec) stack.callback(opj2.destroy_codec, codec)

View file

@ -35,6 +35,7 @@ CLRSPC_UNSPECIFIED = 0
CLRSPC_SRGB = 1 CLRSPC_SRGB = 1
CLRSPC_GRAY = 2 CLRSPC_GRAY = 2
CLRSPC_YCC = 3 CLRSPC_YCC = 3
CLRSPC_EYCC = 4
COLOR_SPACE_TYPE = ctypes.c_int COLOR_SPACE_TYPE = ctypes.c_int
# supported codec # supported codec
@ -390,7 +391,11 @@ class ImageCompType(ctypes.Structure):
("factor", ctypes.c_uint32), ("factor", ctypes.c_uint32),
# image component data # image component data
("data", ctypes.POINTER(ctypes.c_int32))] ("data", ctypes.POINTER(ctypes.c_int32)),
# alpha channel
# TODO: exclude for 2.0, 1.5
("alpha", ctypes.POINTER(ctypes.c_uint16))]
class ImageType(ctypes.Structure): class ImageType(ctypes.Structure):

View file

@ -554,15 +554,21 @@ UUID Box (uuid) @ (77, 3146)
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
Contiguous Codestream Box (jp2c) @ (3223, 1132296)""" Contiguous Codestream Box (jp2c) @ (3223, 1132296)"""
# Output of reader requirement printing for file7.jp2 # Output of reader requirements printing for text_GBR.jp2
file7_rreq = r"""Reader Requirements Box (rreq) @ (44, 24) text_GBR_rreq = r"""Reader Requirements Box (rreq) @ (40, 109)
Fully Understands Aspect Mask: 0xa0 Fully Understands Aspect Mask: 0xffff
Display Completely Mask: 0xc0 Display Completely Mask: 0xf8f0
Standard Features and Masks: Standard Features and Masks:
Feature 005: 0x80 Unrestricted JPEG 2000 Part 1 codestream, ITU-T Rec. T.800 | ISO/IEC 15444-1 Feature 001: 0x8000 Deprecated - contains no extensions
Feature 060: 0x60 e-sRGB enumerated colorspace Feature 005: 0x4080 Unrestricted JPEG 2000 Part 1 codestream, ITU-T Rec. T.800 | ISO/IEC 15444-1
Feature 043: 0x40 Deprecated - compositing layer uses restricted ICC profile Feature 012: 0x2040 Deprecated - codestream is contiguous
Vendor Features:""" Feature 018: 0x1020 Deprecated - support for compositing is not required
Feature 044: 0x810 Compositing layer uses Any ICC profile
Vendor Features:
UUID 3a0d0218-0ae9-4115-b376-4bca41ce0e71
UUID 47c92ccc-d1a1-4581-b904-38bb5467713b
UUID bc45a774-dd50-4ec6-a9f6-f3a137f47e90
UUID d7c8c5ef-951f-43b2-8757-042500f538e8"""
file1_xml = """XML Box (xml ) @ (36, 439) file1_xml = """XML Box (xml ) @ (36, 439)
<IMAGE_CREATION xmlns="http://www.jpeg.org/jpx/1.0/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jpeg.org/jpx/1.0/xml http://www.jpeg.org/metadata/15444-2.xsd"> <IMAGE_CREATION xmlns="http://www.jpeg.org/jpx/1.0/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jpeg.org/jpx/1.0/xml http://www.jpeg.org/metadata/15444-2.xsd">

View file

@ -31,7 +31,7 @@ class TestICC(unittest.TestCase):
"""basic ICC profile""" """basic ICC profile"""
filename = opj_data_file('input/conformance/file5.jp2') filename = opj_data_file('input/conformance/file5.jp2')
j = Jp2k(filename) j = Jp2k(filename)
profile = j.box[3].box[1].icc_profile profile = j.box[2].box[1].icc_profile
self.assertEqual(profile['Size'], 546) self.assertEqual(profile['Size'], 546)
self.assertEqual(profile['Preferred CMM Type'], 0) self.assertEqual(profile['Preferred CMM Type'], 0)
self.assertEqual(profile['Version'], '2.2.0') self.assertEqual(profile['Version'], '2.2.0')

View file

@ -35,6 +35,7 @@ if HAS_PYTHON_XMP_TOOLKIT:
from libxmp import XMPMeta from libxmp import XMPMeta
from .fixtures import OPJ_DATA_ROOT, opj_data_file from .fixtures import OPJ_DATA_ROOT, opj_data_file
from . import fixtures
# Doc tests should be run as well. # Doc tests should be run as well.
@ -376,6 +377,10 @@ class TestJp2k(unittest.TestCase):
creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, 'CreatorTool') creator_tool = xmp.get_property(libxmp.consts.XMP_NS_XMP, 'CreatorTool')
self.assertEqual(creator_tool, 'Google') self.assertEqual(creator_tool, 'Google')
@unittest.skipIf(fixtures.OPENJP2_IS_V2_OFFICIAL,
"Feature not supported in 2.0.0 official")
@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
"Feature not supported in 1.5")
def test_jpx_mult_codestreams_jp2_brand(self): def test_jpx_mult_codestreams_jp2_brand(self):
"""Read JPX codestream when jp2-compatible.""" """Read JPX codestream when jp2-compatible."""
# The file in question has multiple codestreams. # The file in question has multiple codestreams.

View file

@ -3297,7 +3297,7 @@ class TestSuiteDump(unittest.TestCase):
def test_NR_file5_dump(self): def test_NR_file5_dump(self):
# Three 8-bit components in the ROMM-RGB colourspace, encapsulated in a # Three 8-bit components in the ROMM-RGB colourspace, encapsulated in a
# JP2 compatible JPX file. The components have been transformed using # JPX file. The components have been transformed using
# the RCT. The colourspace is specified using both a Restricted ICC # the RCT. The colourspace is specified using both a Restricted ICC
# profile and using the JPX-defined enumerated code for the ROMM-RGB # profile and using the JPX-defined enumerated code for the ROMM-RGB
# colourspace. # colourspace.
@ -3305,49 +3305,37 @@ class TestSuiteDump(unittest.TestCase):
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box] ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'rreq', 'jp2h', 'jp2c']) self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[3].box] ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr', 'colr']) self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption. # Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10)) self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box. # File type box.
self.assertEqual(jp2.box[1].brand, 'jpx ') self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].minor_version, 0) self.assertEqual(jp2.box[1].minor_version, 0)
self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ') self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ')
self.assertEqual(jp2.box[1].compatibility_list[2], 'jpx ')
self.assertEqual(jp2.box[1].compatibility_list[3], 'jpxb')
# Jp2 Header # Jp2 Header
# Image header # Image header
self.assertEqual(jp2.box[3].box[0].height, 512) self.assertEqual(jp2.box[2].box[0].height, 512)
self.assertEqual(jp2.box[3].box[0].width, 768) self.assertEqual(jp2.box[2].box[0].width, 768)
self.assertEqual(jp2.box[3].box[0].num_components, 3) self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[3].box[0].signed, False) self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[3].box[0].compression, 7) # wavelet self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[3].box[0].colorspace_unknown, False) self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[3].box[0].ip_provided, False) self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header # Jp2 Header
# Colour specification # Colour specification
self.assertEqual(jp2.box[3].box[1].method, self.assertEqual(jp2.box[2].box[1].method,
glymur.core.RESTRICTED_ICC_PROFILE) # enumerated glymur.core.RESTRICTED_ICC_PROFILE) # enumerated
self.assertEqual(jp2.box[3].box[1].precedence, 0) self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact self.assertEqual(jp2.box[2].box[1].approximation, 1) # JPX exact
self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 546) self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 546)
self.assertIsNone(jp2.box[3].box[1].colorspace) self.assertIsNone(jp2.box[2].box[1].colorspace)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[3].box[2].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[3].box[2].precedence, 1)
self.assertEqual(jp2.box[3].box[2].approximation, 1) # JPX exact
self.assertIsNone(jp2.box[3].box[2].icc_profile)
self.assertEqual(jp2.box[3].box[2].colorspace,
glymur.core.ROMM_RGB)
def test_NR_file6_dump(self): def test_NR_file6_dump(self):
jfile = opj_data_file('input/conformance/file6.jp2') jfile = opj_data_file('input/conformance/file6.jp2')
@ -3398,54 +3386,37 @@ class TestSuiteDump(unittest.TestCase):
jp2 = Jp2k(jfile) jp2 = Jp2k(jfile)
ids = [box.box_id for box in jp2.box] ids = [box.box_id for box in jp2.box]
self.assertEqual(ids, ['jP ', 'ftyp', 'rreq', 'jp2h', 'jp2c']) self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
ids = [box.box_id for box in jp2.box[3].box] ids = [box.box_id for box in jp2.box[2].box]
self.assertEqual(ids, ['ihdr', 'colr', 'colr']) self.assertEqual(ids, ['ihdr', 'colr'])
# Signature box. Check for corruption. # Signature box. Check for corruption.
self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10)) self.assertEqual(jp2.box[0].signature, (13, 10, 135, 10))
# File type box. # File type box.
self.assertEqual(jp2.box[1].brand, 'jpx ') self.assertEqual(jp2.box[1].brand, 'jp2 ')
self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ') self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ')
self.assertEqual(jp2.box[1].compatibility_list[2], 'jpx ')
self.assertEqual(jp2.box[1].compatibility_list[3], 'jpxb')
self.assertEqual(jp2.box[1].minor_version, 0)
# Reader requirements talk.
# e-SRGB enumerated colourspace
self.assertTrue(60 in jp2.box[2].standard_flag)
# Jp2 Header # Jp2 Header
# Image header # Image header
self.assertEqual(jp2.box[3].box[0].height, 640) self.assertEqual(jp2.box[2].box[0].height, 640)
self.assertEqual(jp2.box[3].box[0].width, 480) self.assertEqual(jp2.box[2].box[0].width, 480)
self.assertEqual(jp2.box[3].box[0].num_components, 3) self.assertEqual(jp2.box[2].box[0].num_components, 3)
self.assertEqual(jp2.box[3].box[0].bits_per_component, 16) self.assertEqual(jp2.box[2].box[0].bits_per_component, 16)
self.assertEqual(jp2.box[3].box[0].signed, False) self.assertEqual(jp2.box[2].box[0].signed, False)
self.assertEqual(jp2.box[3].box[0].compression, 7) # wavelet self.assertEqual(jp2.box[2].box[0].compression, 7) # wavelet
self.assertEqual(jp2.box[3].box[0].colorspace_unknown, False) self.assertEqual(jp2.box[2].box[0].colorspace_unknown, False)
self.assertEqual(jp2.box[3].box[0].ip_provided, False) self.assertEqual(jp2.box[2].box[0].ip_provided, False)
# Jp2 Header # Jp2 Header
# Colour specification # Colour specification
self.assertEqual(jp2.box[3].box[1].method, self.assertEqual(jp2.box[2].box[1].method,
glymur.core.RESTRICTED_ICC_PROFILE) glymur.core.RESTRICTED_ICC_PROFILE)
self.assertEqual(jp2.box[3].box[1].precedence, 0) self.assertEqual(jp2.box[2].box[1].precedence, 0)
self.assertEqual(jp2.box[3].box[1].approximation, 1) # JPX exact self.assertEqual(jp2.box[2].box[1].approximation, 1)
self.assertEqual(jp2.box[3].box[1].icc_profile['Size'], 13332) self.assertEqual(jp2.box[2].box[1].icc_profile['Size'], 13332)
self.assertIsNone(jp2.box[3].box[1].colorspace) self.assertIsNone(jp2.box[2].box[1].colorspace)
# Jp2 Header
# Colour specification
self.assertEqual(jp2.box[3].box[2].method,
glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(jp2.box[3].box[2].precedence, 1)
self.assertEqual(jp2.box[3].box[2].approximation, 1) # JPX exact
self.assertIsNone(jp2.box[3].box[2].icc_profile)
self.assertEqual(jp2.box[3].box[2].colorspace,
glymur.core.E_SRGB)
def test_NR_file8_dump(self): def test_NR_file8_dump(self):
# One 8-bit component in a gamma 1.8 space. The colourspace is # One 8-bit component in a gamma 1.8 space. The colourspace is
@ -6647,6 +6618,7 @@ class TestSuite2point1(unittest.TestCase):
Jp2k(jfile).read() Jp2k(jfile).read()
self.assertTrue(True) self.assertTrue(True)
@unittest.skip("Failing as of r2436")
def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self):
jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2')
with warnings.catch_warnings(): with warnings.catch_warnings():

View file

@ -23,6 +23,31 @@ from glymur import Jp2k
import glymur import glymur
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
"Functionality not implemented for 1.3, 1.4")
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_OPJ_DATA_ROOT environment variable not set")
class TestSuiteNegative2pointzero(unittest.TestCase):
"""Feature set not supported for versions less than 2.0"""
def setUp(self):
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
def tearDown(self):
pass
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_cinema_mode(self):
"""Cinema mode not supported for less than 2.0.1."""
infile = opj_data_file('input/nonregression/Bretagne1.ppm')
data = read_image(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError):
j.write(data, psnr=[30, 35, 40], cratios=[2, 3, 4])
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), @unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
"Functionality not implemented for 1.3, 1.4") "Functionality not implemented for 1.3, 1.4")
@unittest.skipIf(OPJ_DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,

View file

@ -21,22 +21,25 @@ except ((ImportError, RuntimeError)):
from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG
from .fixtures import OPJ_DATA_ROOT, opj_data_file from .fixtures import OPJ_DATA_ROOT, opj_data_file
from . import fixtures
from glymur import Jp2k from glymur import Jp2k
import glymur import glymur
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
@unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(os.name == "nt", "no write support on windows, period")
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""", @unittest.skipIf(fixtures.OPENJP2_IS_V2_OFFICIAL,
glymur.version.openjpeg_version) is not None, "Feature not supported in 2.0.0 official")
"Writing only supported with openjpeg version 1.5+.") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1,
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) "Feature not supported in 1.5")
@unittest.skipIf(OPJ_DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
class TestSuiteWrite(unittest.TestCase): class TestSuiteWriteCinema(unittest.TestCase):
"""Tests for writing with openjp2 backend. """Tests for writing with openjp2 backend.
These tests roughly correspond with those tests with similar names in the These tests either roughly correspond with those tests with similar names
OpenJPEG test suite. in the OpenJPEG test suite or are closely associated.
""" """
def setUp(self): def setUp(self):
pass pass
@ -44,6 +47,26 @@ class TestSuiteWrite(unittest.TestCase):
def tearDown(self): def tearDown(self):
pass pass
def test_cinema2K_with_others(self):
"""Can't specify cinema2k with any other options."""
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
infile = opj_data_file(relfile)
data = skimage.io.imread(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError):
j.write(data, cinema2k=48, cratios=[200, 100, 50])
def test_cinema4K_with_others(self):
"""Can't specify cinema4k with any other options."""
relfile = 'input/nonregression/ElephantDream_4K.tif'
infile = opj_data_file(relfile)
data = skimage.io.imread(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError):
j.write(data, cinema4k=True, cratios=[200, 100, 50])
def check_cinema4k_codestream(self, codestream, image_size): def check_cinema4k_codestream(self, codestream, image_size):
"""Common out for cinema2k tests.""" """Common out for cinema2k tests."""
# SIZ: Image and tile size # SIZ: Image and tile size
@ -128,8 +151,6 @@ class TestSuiteWrite(unittest.TestCase):
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_ElephantDream_4K_tif_21_encode(self): def test_NR_ENC_ElephantDream_4K_tif_21_encode(self):
relfile = 'input/nonregression/ElephantDream_4K.tif' relfile = 'input/nonregression/ElephantDream_4K.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -142,8 +163,6 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema4k_codestream(codestream, (4096, 2160)) self.check_cinema4k_codestream(codestream, (4096, 2160))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_19_encode(self): def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_19_encode(self):
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif' relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -156,8 +175,6 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema2k_codestream(codestream, (2048, 857)) self.check_cinema2k_codestream(codestream, (2048, 857))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_20_encode(self): def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_20_encode(self):
relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif' relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -170,8 +187,6 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema2k_codestream(codestream, (2048, 1080)) self.check_cinema2k_codestream(codestream, (2048, 1080))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_17_encode(self): def test_NR_ENC_X_6_2K_24_FULL_CBR_CIRCLE_000_tif_17_encode(self):
relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif' relfile = 'input/nonregression/X_6_2K_24_FULL_CBR_CIRCLE_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -184,8 +199,6 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema2k_codestream(codestream, (2048, 1080)) self.check_cinema2k_codestream(codestream, (2048, 1080))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_16_encode(self): def test_NR_ENC_X_5_2K_24_235_CBR_STEM24_000_tif_16_encode(self):
relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif' relfile = 'input/nonregression/X_5_2K_24_235_CBR_STEM24_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -198,8 +211,6 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema2k_codestream(codestream, (2048, 857)) self.check_cinema2k_codestream(codestream, (2048, 857))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT,
"Cannot read input image without scikit-image/freeimage")
def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_18_encode(self): def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_18_encode(self):
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
@ -212,32 +223,50 @@ class TestSuiteWrite(unittest.TestCase):
self.check_cinema2k_codestream(codestream, (1998, 1080)) self.check_cinema2k_codestream(codestream, (1998, 1080))
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT, @unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
"Cannot read input image without scikit-image/freeimage") @unittest.skipIf(re.match(r"""2\.0""", glymur.version.openjpeg_version),
def test_NR_ENC_X_4_2K_24_185_CBR_WB_000_tif_15_encode(self): "Functionality implemented for 2.1")
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' @unittest.skipIf(OPJ_DATA_ROOT is None,
infile = opj_data_file(relfile) "OPJ_OPJ_DATA_ROOT environment variable not set")
data = skimage.io.imread(infile) class TestSuiteNegative2pointzero(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: """Feature set not supported for versions less than 2.0"""
j = Jp2k(tfile.name, 'wb')
j.write(data, cinema2k=24)
codestream = j.get_codestream() def setUp(self):
self.check_cinema2k_codestream(codestream, (1998, 1080)) self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
def tearDown(self):
pass
@unittest.skipIf(not _HAS_SKIMAGE_FREEIMAGE_SUPPORT, def test_cinema_mode(self):
"Cannot read input image without scikit-image/freeimage")
def test_cinema2k_bad_frame_rate(self):
relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif' relfile = 'input/nonregression/X_4_2K_24_185_CBR_WB_000.tif'
infile = opj_data_file(relfile) infile = opj_data_file(relfile)
data = skimage.io.imread(infile) data = skimage.io.imread(infile)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb') j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError): with self.assertRaises(IOError):
j.write(data, cinema2k=36) j.write(data, cinema2k=48)
@unittest.skipIf(os.name == "nt", "no write support on windows, period")
@unittest.skipIf(re.match(r"""1\.[01234]\.\d""",
glymur.version.openjpeg_version) is not None,
"Writing only supported with openjpeg version 1.5+.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestSuiteWrite(unittest.TestCase):
"""Tests for writing with openjp2 backend.
These tests either roughly correspond with those tests with similar names
in the OpenJPEG test suite or are closely associated.
"""
def setUp(self):
pass
def tearDown(self):
pass
def test_NR_ENC_Bretagne1_ppm_1_encode(self): def test_NR_ENC_Bretagne1_ppm_1_encode(self):
"""NR-ENC-Bretagne1.ppm-1-encode""" """NR-ENC-Bretagne1.ppm-1-encode"""
infile = opj_data_file('input/nonregression/Bretagne1.ppm') infile = opj_data_file('input/nonregression/Bretagne1.ppm')
@ -1052,5 +1081,6 @@ class TestSuiteWrite(unittest.TestCase):
glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) glymur.core.WAVELET_XFORM_5X3_REVERSIBLE)
self.assertEqual(len(codestream.segment[2].spcod), 9) self.assertEqual(len(codestream.segment[2].spcod), 9)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View file

@ -735,18 +735,17 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines) expected = '\n'.join(lines)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@unittest.skip("file7 no longer has a rreq")
@unittest.skipIf(OPJ_DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")
def test_rreq(self): def test_rreq(self):
"""verify printing of reader requirements box""" """verify printing of reader requirements box"""
filename = opj_data_file('input/conformance/file7.jp2') filename = opj_data_file('input/nonregression/text_GBR.jp2')
j = glymur.Jp2k(filename) j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out: with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2]) print(j.box[2])
actual = fake_out.getvalue().strip() actual = fake_out.getvalue().strip()
self.maxDiff = None self.assertEqual(actual, fixtures.text_GBR_rreq)
expected = fixtures.file7_rreq
self.assertEqual(actual, expected)
@unittest.skipIf(OPJ_DATA_ROOT is None, @unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set") "OPJ_DATA_ROOT environment variable not set")