Merge branch 'issue199' into devel
This commit is contained in:
commit
869f8e9e3e
5 changed files with 52 additions and 29 deletions
|
|
@ -17,7 +17,6 @@ codestreams.
|
||||||
# the base Segment class.
|
# the base Segment class.
|
||||||
# pylint: disable=R0903
|
# pylint: disable=R0903
|
||||||
|
|
||||||
import collections
|
|
||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -28,30 +27,18 @@ import numpy as np
|
||||||
from .core import LRCP, RLCP, RPCL, PCRL, CPRL
|
from .core import LRCP, RLCP, RPCL, PCRL, CPRL
|
||||||
from .core import WAVELET_XFORM_9X7_IRREVERSIBLE
|
from .core import WAVELET_XFORM_9X7_IRREVERSIBLE
|
||||||
from .core import WAVELET_XFORM_5X3_REVERSIBLE
|
from .core import WAVELET_XFORM_5X3_REVERSIBLE
|
||||||
|
from .core import _Keydefaultdict
|
||||||
from .lib import openjp2 as opj2
|
from .lib import openjp2 as opj2
|
||||||
|
|
||||||
class _keydefaultdict(collections.defaultdict):
|
|
||||||
"""Unlisted keys help form their own error message.
|
|
||||||
|
|
||||||
Normally defaultdict uses a factory function with no input arguments, but
|
|
||||||
that's not quite the behavior we want.
|
|
||||||
"""
|
|
||||||
def __missing__(self, key):
|
|
||||||
if self.default_factory is None:
|
|
||||||
raise KeyError(key)
|
|
||||||
else:
|
|
||||||
ret = self[key] = self.default_factory(key)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
_factory = lambda x: '{0} (invalid)'.format(x)
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
_PROGRESSION_ORDER_DISPLAY = _keydefaultdict(_factory,
|
_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory,
|
||||||
{ LRCP: 'LRCP',
|
{ LRCP: 'LRCP',
|
||||||
RLCP: 'RLCP',
|
RLCP: 'RLCP',
|
||||||
RPCL: 'RPCL',
|
RPCL: 'RPCL',
|
||||||
PCRL: 'PCRL',
|
PCRL: 'PCRL',
|
||||||
CPRL: 'CPRL'})
|
CPRL: 'CPRL'})
|
||||||
|
|
||||||
_WAVELET_TRANSFORM_DISPLAY = _keydefaultdict(_factory,
|
_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory,
|
||||||
{ WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
{ WAVELET_XFORM_9X7_IRREVERSIBLE: '9-7 irreversible',
|
||||||
WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'})
|
WAVELET_XFORM_5X3_REVERSIBLE: '5-3 reversible'})
|
||||||
|
|
||||||
|
|
@ -64,7 +51,7 @@ _PROFILE_4 = 4
|
||||||
_KNOWN_PROFILES = [_NO_PROFILE, _PROFILE_0, _PROFILE_1, _PROFILE_3, _PROFILE_4]
|
_KNOWN_PROFILES = [_NO_PROFILE, _PROFILE_0, _PROFILE_1, _PROFILE_3, _PROFILE_4]
|
||||||
|
|
||||||
# How to display the codestream profile.
|
# How to display the codestream profile.
|
||||||
_CAPABILITIES_DISPLAY = _keydefaultdict(_factory,
|
_CAPABILITIES_DISPLAY = _Keydefaultdict(_factory,
|
||||||
{ _NO_PROFILE: 'no profile',
|
{ _NO_PROFILE: 'no profile',
|
||||||
_PROFILE_0: '0',
|
_PROFILE_0: '0',
|
||||||
_PROFILE_1: '1',
|
_PROFILE_1: '1',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
"""Core definitions to be shared amongst the modules.
|
"""Core definitions to be shared amongst the modules.
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import lxml.etree as ET
|
import lxml.etree as ET
|
||||||
|
|
||||||
|
class _Keydefaultdict(collections.defaultdict):
|
||||||
|
"""Unlisted keys help form their own error message.
|
||||||
|
|
||||||
|
Normally defaultdict uses a factory function with no input arguments, but
|
||||||
|
that's not quite the behavior we want.
|
||||||
|
"""
|
||||||
|
def __missing__(self, key):
|
||||||
|
if self.default_factory is None:
|
||||||
|
raise KeyError(key)
|
||||||
|
else:
|
||||||
|
ret = self[key] = self.default_factory(key)
|
||||||
|
return ret
|
||||||
|
|
||||||
# Progression order
|
# Progression order
|
||||||
LRCP = 0
|
LRCP = 0
|
||||||
RLCP = 1
|
RLCP = 1
|
||||||
|
|
@ -57,24 +71,26 @@ YCC = 18
|
||||||
E_SRGB = 20
|
E_SRGB = 20
|
||||||
ROMM_RGB = 21
|
ROMM_RGB = 21
|
||||||
|
|
||||||
_COLORSPACE_MAP_DISPLAY = {
|
_factory = lambda x: '{0} (unrecognized)'.format(x)
|
||||||
CMYK: 'CMYK',
|
_COLORSPACE_MAP_DISPLAY = _Keydefaultdict(_factory,
|
||||||
SRGB: 'sRGB',
|
{ CMYK: 'CMYK',
|
||||||
GREYSCALE: 'greyscale',
|
SRGB: 'sRGB',
|
||||||
YCC: 'YCC',
|
GREYSCALE: 'greyscale',
|
||||||
E_SRGB: 'e-sRGB',
|
YCC: 'YCC',
|
||||||
ROMM_RGB: 'ROMM-RGB'}
|
E_SRGB: 'e-sRGB',
|
||||||
|
ROMM_RGB: 'ROMM-RGB'} )
|
||||||
|
|
||||||
# enumerated color channel types
|
# enumerated color channel types
|
||||||
COLOR = 0
|
COLOR = 0
|
||||||
OPACITY = 1
|
OPACITY = 1
|
||||||
PRE_MULTIPLIED_OPACITY = 2
|
PRE_MULTIPLIED_OPACITY = 2
|
||||||
_UNSPECIFIED = 65535
|
_UNSPECIFIED = 65535
|
||||||
_COLOR_TYPE_MAP_DISPLAY = {
|
_factory = lambda x: '{0} (invalid)'.format(x)
|
||||||
COLOR: 'color',
|
_COLOR_TYPE_MAP_DISPLAY = _Keydefaultdict(_factory,
|
||||||
OPACITY: 'opacity',
|
{ COLOR: 'color',
|
||||||
PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
|
OPACITY: 'opacity',
|
||||||
_UNSPECIFIED: 'unspecified'}
|
PRE_MULTIPLIED_OPACITY: 'pre-multiplied opacity',
|
||||||
|
_UNSPECIFIED: 'unspecified'})
|
||||||
|
|
||||||
# color channel definitions.
|
# color channel definitions.
|
||||||
RED = 1
|
RED = 1
|
||||||
|
|
|
||||||
|
|
@ -419,6 +419,9 @@ class ColourSpecificationBox(Jp2kBox):
|
||||||
# enumerated colour space
|
# enumerated colour space
|
||||||
read_buffer = fptr.read(4)
|
read_buffer = fptr.read(4)
|
||||||
colorspace, = struct.unpack('>I', read_buffer)
|
colorspace, = struct.unpack('>I', read_buffer)
|
||||||
|
if colorspace not in _COLORSPACE_MAP_DISPLAY.keys():
|
||||||
|
msg = "Unrecognized colorspace: {0}".format(colorspace)
|
||||||
|
warnings.warn(msg)
|
||||||
icc_profile = None
|
icc_profile = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -758,6 +758,13 @@ class TestJp2k_2_1(unittest.TestCase):
|
||||||
class TestJp2kOpjDataRoot(unittest.TestCase):
|
class TestJp2kOpjDataRoot(unittest.TestCase):
|
||||||
"""These tests should be run by just about all configuration."""
|
"""These tests should be run by just about all configuration."""
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.hexversion < 0x03000000, "Test requires Python 3.3+")
|
||||||
|
def test_invalid_colorspace(self):
|
||||||
|
"""Should warn in case of invalid colorspace."""
|
||||||
|
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||||
|
with self.assertWarns(UserWarning):
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
|
||||||
def test_no_cxform_pclr_jp2(self):
|
def test_no_cxform_pclr_jp2(self):
|
||||||
"""Indices for pclr jpxfile if no color transform"""
|
"""Indices for pclr jpxfile if no color transform"""
|
||||||
filename = opj_data_file('input/conformance/file9.jp2')
|
filename = opj_data_file('input/conformance/file9.jp2')
|
||||||
|
|
|
||||||
|
|
@ -653,6 +653,16 @@ class TestPrintingOpjDataRoot(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_invalid_colorspace(self):
|
||||||
|
"""An invalid colorspace shouldn't cause an error."""
|
||||||
|
filename = opj_data_file('input/nonregression/edf_c2_1103421.jp2')
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
jp2 = Jp2k(filename)
|
||||||
|
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||||
|
print(jp2)
|
||||||
|
|
||||||
|
|
||||||
def test_bad_rsiz(self):
|
def test_bad_rsiz(self):
|
||||||
"""Should still be able to print if rsiz is bad, issue196"""
|
"""Should still be able to print if rsiz is bad, issue196"""
|
||||||
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
filename = opj_data_file('input/nonregression/edf_c2_1002767.jp2')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue