Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
John Evans
1631408b50 complies with flake8 2014-12-13 12:17:59 -05:00
7 changed files with 126 additions and 138 deletions

View file

@ -1,19 +1,20 @@
"""glymur - read, write, and interrogate JPEG 2000 files """glymur - read, write, and interrogate JPEG 2000 files
""" """
import sys
import unittest import unittest
from glymur import version from glymur import version
__version__ = version.version __version__ = version.version
from .jp2k import Jp2k from .jp2k import Jp2k
from .jp2box import ( from .jp2box import (get_printoptions, set_printoptions,
get_printoptions, set_printoptions, get_parseoptions, set_parseoptions)
get_parseoptions, set_parseoptions
)
from . import data from . import data
__all__ = [Jp2k, get_printoptions, set_printoptions, get_parseoptions,
set_parseoptions, data]
def runtests(): def runtests():
"""Discover and run all tests for the glymur package. """Discover and run all tests for the glymur package.
""" """

View file

@ -3,8 +3,6 @@
Part of glymur. Part of glymur.
""" """
from collections import OrderedDict from collections import OrderedDict
import pprint
import re
import struct import struct
import sys import sys
import warnings import warnings

View file

@ -31,16 +31,12 @@ from .core import (LRCP, RLCP, RPCL, PCRL, CPRL,
from .lib import openjp2 as opj2 from .lib import openjp2 as opj2
_factory = lambda x: '{0} (invalid)'.format(x) _factory = lambda x: '{0} (invalid)'.format(x)
_PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory, _x = {LRCP: 'LRCP', RLCP: 'RLCP', RPCL: 'RPCL', PCRL: 'PCRL', CPRL: 'CPRL'}
{ LRCP: 'LRCP', _PROGRESSION_ORDER_DISPLAY = _Keydefaultdict(_factory, _x)
RLCP: 'RLCP',
RPCL: 'RPCL',
PCRL: 'PCRL',
CPRL: 'CPRL'})
_WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, _x = {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'}) _WAVELET_TRANSFORM_DISPLAY = _Keydefaultdict(_factory, _x)
_NO_PROFILE = 0 _NO_PROFILE = 0
_PROFILE_0 = 1 _PROFILE_0 = 1
@ -51,12 +47,12 @@ _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, _x = {_NO_PROFILE: 'no profile',
{ _NO_PROFILE: 'no profile', _PROFILE_0: '0',
_PROFILE_0: '0', _PROFILE_1: '1',
_PROFILE_1: '1', _PROFILE_3: 'Cinema 2K',
_PROFILE_3: 'Cinema 2K', _PROFILE_4: 'Cinema 4K'}
_PROFILE_4: 'Cinema 4K'}) _CAPABILITIES_DISPLAY = _Keydefaultdict(_factory, _x)
# Need a catch-all list of valid markers. # Need a catch-all list of valid markers.
# See table A-1 in ISO/IEC FCD15444-1. # See table A-1 in ISO/IEC FCD15444-1.
@ -694,7 +690,7 @@ class Codestream(object):
try: try:
num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0]) num_tiles_x = (xysiz[0] - xyosiz[0]) / (xytsiz[0] - xytosiz[0])
num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1]) num_tiles_y = (xysiz[1] - xyosiz[1]) / (xytsiz[1] - xytosiz[1])
except ZeroDivisionError as err: except ZeroDivisionError:
warnings.warn("Invalid tile dimensions.") warnings.warn("Invalid tile dimensions.")
else: else:
numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y) numtiles = math.ceil(num_tiles_x) * math.ceil(num_tiles_y)

View file

@ -3,7 +3,6 @@ Entry point for console script jp2dump.
""" """
import argparse import argparse
import os import os
import sys
import warnings import warnings
from . import Jp2k, set_printoptions, lib from . import Jp2k, set_printoptions, lib

View file

@ -1,8 +1,6 @@
"""Core definitions to be shared amongst the modules. """Core definitions to be shared amongst the modules.
""" """
import collections import collections
import copy
import lxml.etree as ET
class _Keydefaultdict(collections.defaultdict): class _Keydefaultdict(collections.defaultdict):

View file

@ -44,11 +44,11 @@ _METHOD_DISPLAY = {
VENDOR_COLOR_METHOD: 'vendor color method'} VENDOR_COLOR_METHOD: 'vendor color method'}
_factory = lambda x: '{0} (invalid)'.format(x) _factory = lambda x: '{0} (invalid)'.format(x)
_APPROX_DISPLAY = _Keydefaultdict(_factory, _x = {1: 'accurately represents correct colorspace definition',
{1: 'accurately represents correct colorspace definition', 2: 'approximates correct colorspace definition, exceptional quality',
2: 'approximates correct colorspace definition, exceptional quality', 3: 'approximates correct colorspace definition, reasonable quality',
3: 'approximates correct colorspace definition, reasonable quality', 4: 'approximates correct colorspace definition, poor quality'}
4: 'approximates correct colorspace definition, poor quality'}) _APPROX_DISPLAY = _Keydefaultdict(_factory, _x)
class Jp2kBox(object): class Jp2kBox(object):
@ -1983,7 +1983,6 @@ class PaletteBox(Jp2kBox):
*bps_signed) *bps_signed)
fptr.write(write_buffer) fptr.write(write_buffer)
bps = self.bits_per_component
# All components are the same. Writing is straightforward. # All components are the same. Writing is straightforward.
if self.bits_per_component[0] <= 8: if self.bits_per_component[0] <= 8:
write_buffer = memoryview(self.palette.astype(np.uint8)) write_buffer = memoryview(self.palette.astype(np.uint8))
@ -2023,13 +2022,10 @@ class PaletteBox(Jp2kBox):
# Ok the palette has the same datatype for all columns. We should # Ok the palette has the same datatype for all columns. We should
# be able to efficiently read it. # be able to efficiently read it.
if bps[0] <= 8: if bps[0] <= 8:
nbytes_per_row = ncols
dtype = np.uint8 dtype = np.uint8
elif bps[0] <= 16: elif bps[0] <= 16:
nbytes_per_row = 2 * ncols
dtype = np.uint16 dtype = np.uint16
elif bps[0] <= 32: elif bps[0] <= 32:
nbytes_per_row = 3 * ncols
dtype = np.uint32 dtype = np.uint32
palette = np.frombuffer(read_buffer[3 + ncols:], dtype=dtype) palette = np.frombuffer(read_buffer[3 + ncols:], dtype=dtype)
@ -2060,93 +2056,93 @@ class PaletteBox(Jp2kBox):
# Map rreq codes to display text. # Map rreq codes to display text.
_READER_REQUIREMENTS_DISPLAY = { _READER_REQUIREMENTS_DISPLAY = {
0: 'File not completely understood', 0: 'File not completely understood',
1: 'Deprecated - contains no extensions', 1: 'Deprecated - contains no extensions',
2: 'Contains multiple composition layers', 2: 'Contains multiple composition layers',
3: 'Deprecated - codestream is compressed using JPEG 2000 and requires ' 3: 'Deprecated - codestream is compressed using JPEG 2000 and requires '
+ 'at least a Profile 0 decoder as defind in ITU-T Rec. T.800 ' + 'at least a Profile 0 decoder as defind in ITU-T Rec. T.800 '
+ '| ISO/IEC 15444-1, A.10 Table A.45', + '| ISO/IEC 15444-1, A.10 Table A.45',
4: 'JPEG 2000 Part 1 Profile 1 codestream', 4: 'JPEG 2000 Part 1 Profile 1 codestream',
5: 'Unrestricted JPEG 2000 Part 1 codestream, ITU-T Rec. T.800 ' 5: 'Unrestricted JPEG 2000 Part 1 codestream, ITU-T Rec. T.800 '
+ '| ISO/IEC 15444-1', + '| ISO/IEC 15444-1',
6: 'Unrestricted JPEG 2000 Part 2 codestream', 6: 'Unrestricted JPEG 2000 Part 2 codestream',
7: 'JPEG codestream as defined in ISO/IEC 10918-1', 7: 'JPEG codestream as defined in ISO/IEC 10918-1',
8: 'Deprecated - does not contain opacity', 8: 'Deprecated - does not contain opacity',
9: 'Non-premultiplied opacity channel', 9: 'Non-premultiplied opacity channel',
10: 'Premultiplied opacity channel', 10: 'Premultiplied opacity channel',
11: 'Chroma-key based opacity', 11: 'Chroma-key based opacity',
12: 'Deprecated - codestream is contiguous', 12: 'Deprecated - codestream is contiguous',
13: 'Fragmented codestream where all fragments are in file and in order', 13: 'Fragmented codestream where all fragments are in file and in order',
14: 'Fragmented codestream where all fragments are in file ' 14: 'Fragmented codestream where all fragments are in file '
+ 'but are out of order', + 'but are out of order',
15: 'Fragmented codestream where not all fragments are within the file ' 15: 'Fragmented codestream where not all fragments are within the file '
+ 'but are all in locally accessible files', + 'but are all in locally accessible files',
16: 'Fragmented codestream where some fragments may be accessible ' 16: 'Fragmented codestream where some fragments may be accessible '
+ 'only through a URL specified network connection', + 'only through a URL specified network connection',
17: 'Compositing required to produce rendered result from multiple ' 17: 'Compositing required to produce rendered result from multiple '
+ 'compositing layers', + 'compositing layers',
18: 'Deprecated - support for compositing is not required', 18: 'Deprecated - support for compositing is not required',
19: 'Deprecated - contains multiple, discrete layers that should not ' 19: 'Deprecated - contains multiple, discrete layers that should not '
+ 'be combined through either animation or compositing', + 'be combined through either animation or compositing',
20: 'Deprecated - compositing layers each contain only a single ' 20: 'Deprecated - compositing layers each contain only a single '
+ 'codestream', + 'codestream',
21: 'At least one compositing layer consists of multiple codestreams', 21: 'At least one compositing layer consists of multiple codestreams',
22: 'Deprecated - all compositing layers are in the same colourspace', 22: 'Deprecated - all compositing layers are in the same colourspace',
23: 'Colourspace transformations are required to combine compositing ' 23: 'Colourspace transformations are required to combine compositing '
+ 'layers; not all compositing layers are in the same colourspace', + 'layers; not all compositing layers are in the same colourspace',
24: 'Deprecated - rendered result created without using animation', 24: 'Deprecated - rendered result created without using animation',
25: 'Deprecated - animated, but first layer covers entire area and is ' 25: 'Deprecated - animated, but first layer covers entire area and is '
+ 'opaque', + 'opaque',
26: 'First animation layer does not cover entire rendered result', 26: 'First animation layer does not cover entire rendered result',
27: 'Deprecated - animated, and no layer is reused', 27: 'Deprecated - animated, and no layer is reused',
28: 'Reuse of animation layers', 28: 'Reuse of animation layers',
29: 'Deprecated - animated, but layers are reused', 29: 'Deprecated - animated, but layers are reused',
30: 'Some animated frames are non-persistent', 30: 'Some animated frames are non-persistent',
31: 'Deprecated - rendered result created without using scaling', 31: 'Deprecated - rendered result created without using scaling',
32: 'Rendered result involves scaling within a layer', 32: 'Rendered result involves scaling within a layer',
33: 'Rendered result involves scaling between layers', 33: 'Rendered result involves scaling between layers',
34: 'ROI metadata', 34: 'ROI metadata',
35: 'IPR metadata', 35: 'IPR metadata',
36: 'Content metadata', 36: 'Content metadata',
37: 'History metadata', 37: 'History metadata',
38: 'Creation metadata', 38: 'Creation metadata',
39: 'JPX digital signatures', 39: 'JPX digital signatures',
40: 'JPX checksums', 40: 'JPX checksums',
41: 'Desires Graphics Arts Reproduction specified', 41: 'Desires Graphics Arts Reproduction specified',
42: 'Deprecated - compositing layer uses palettized colour', 42: 'Deprecated - compositing layer uses palettized colour',
43: 'Deprecated - compositing layer uses restricted ICC profile', 43: 'Deprecated - compositing layer uses restricted ICC profile',
44: 'Compositing layer uses Any ICC profile', 44: 'Compositing layer uses Any ICC profile',
45: 'Deprecated - compositing layer uses sRGB enumerated colourspace', 45: 'Deprecated - compositing layer uses sRGB enumerated colourspace',
46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace', 46: 'Deprecated - compositing layer uses sRGB-grey enumerated colourspace',
47: 'BiLevel 1 enumerated colourspace', 47: 'BiLevel 1 enumerated colourspace',
48: 'BiLevel 2 enumerated colourspace', 48: 'BiLevel 2 enumerated colourspace',
49: 'YCbCr 1 enumerated colourspace', 49: 'YCbCr 1 enumerated colourspace',
50: 'YCbCr 2 enumerated colourspace', 50: 'YCbCr 2 enumerated colourspace',
51: 'YCbCr 3 enumerated colourspace', 51: 'YCbCr 3 enumerated colourspace',
52: 'PhotoYCC enumerated colourspace', 52: 'PhotoYCC enumerated colourspace',
53: 'YCCK enumerated colourspace', 53: 'YCCK enumerated colourspace',
54: 'CMY enumerated colourspace', 54: 'CMY enumerated colourspace',
55: 'CMYK enumerated colorspace', 55: 'CMYK enumerated colorspace',
56: 'CIELab enumerated colourspace with default parameters', 56: 'CIELab enumerated colourspace with default parameters',
57: 'CIELab enumerated colourspace with non-default parameters', 57: 'CIELab enumerated colourspace with non-default parameters',
58: 'CIEJab enumerated colourspace with default parameters', 58: 'CIEJab enumerated colourspace with default parameters',
59: 'CIEJab enumerated colourspace with non-default parameters', 59: 'CIEJab enumerated colourspace with non-default parameters',
60: 'e-sRGB enumerated colorspace', 60: 'e-sRGB enumerated colorspace',
61: 'ROMM_RGB enumerated colorspace', 61: 'ROMM_RGB enumerated colorspace',
62: 'Non-square samples', 62: 'Non-square samples',
63: 'Deprecated - compositing layers have labels', 63: 'Deprecated - compositing layers have labels',
64: 'Deprecated - codestreams have labels', 64: 'Deprecated - codestreams have labels',
65: 'Deprecated - compositing layers have different colour spaces', 65: 'Deprecated - compositing layers have different colour spaces',
66: 'Deprecated - compositing layers have different metadata', 66: 'Deprecated - compositing layers have different metadata',
67: 'GIS metadata XML box', 67: 'GIS metadata XML box',
68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8', 68: 'JPSEC extensions in codestream as specified by ISO/IEC 15444-8',
69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10', 69: 'JP3D extensions in codestream as specified by ISO/IEC 15444-10',
70: 'Deprecated - compositing layer uses sYCC enumerated colour space', 70: 'Deprecated - compositing layer uses sYCC enumerated colour space',
71: 'e-sYCC enumerated colourspace', 71: 'e-sYCC enumerated colourspace',
72: 'JPEG 2000 Part 2 codestream as restricted by baseline conformance ' 72: 'JPEG 2000 Part 2 codestream as restricted by baseline conformance '
+ 'requirements in M.9.2.3', + 'requirements in M.9.2.3',
73: 'YPbPr(1125/60) enumerated colourspace', 73: 'YPbPr(1125/60) enumerated colourspace',
74: 'YPbPr(1250/50) enumerated colourspace'} 74: 'YPbPr(1250/50) enumerated colourspace'}
class ReaderRequirementsBox(Jp2kBox): class ReaderRequirementsBox(Jp2kBox):
@ -2209,7 +2205,8 @@ class ReaderRequirementsBox(Jp2kBox):
if _printoptions['short'] is True: if _printoptions['short'] is True:
return msg return msg
msg += '\n Fully Understands Aspect Mask: 0x{0:x}'.format(self.fuam) msg += '\n Fully Understands Aspect Mask: 0x{0:x}'
msg = msg.format(self.fuam)
msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm) msg += '\n Display Completely Mask: 0x{0:x}'.format(self.dcm)
msg += '\n Standard Features and Masks:' msg += '\n Standard Features and Masks:'
@ -2265,8 +2262,8 @@ class ReaderRequirementsBox(Jp2kBox):
standard_flag, standard_mask = data standard_flag, standard_mask = data
nflags = len(standard_flag) nflags = len(standard_flag)
vendor_offset = 1 + 2 * mask_length + 2 \ vendor_offset = (1 + 2 * mask_length + 2
+ (2 + mask_length) * nflags + (2 + mask_length) * nflags)
data = _parse_vendor_features(read_buffer[vendor_offset:], data = _parse_vendor_features(read_buffer[vendor_offset:],
mask_length) mask_length)
vendor_feature, vendor_mask = data vendor_feature, vendor_mask = data
@ -2323,7 +2320,7 @@ def _parse_rreq3(read_buffer, length, offset):
read_buffer = read_buffer[9 + num_standard_features * 10:] read_buffer = read_buffer[9 + num_standard_features * 10:]
for j in range(num_vendor_features): for j in range(num_vendor_features):
uslice = slice(j * entry_length, (j + 1) * entry_length) uslice = slice(j * entry_length, (j + 1) * entry_length)
ubuffer = read_buffer[slice] ubuffer = read_buffer[uslice]
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16])) vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
lst = struct.unpack('>BBB', ubuffer[16:]) lst = struct.unpack('>BBB', ubuffer[16:])
@ -3168,6 +3165,7 @@ class UUIDBox(Jp2kBox):
""" """
box_id = 'uuid' box_id = 'uuid'
longname = 'UUID' longname = 'UUID'
_xmp_uuid = uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')
def __init__(self, the_uuid, raw_data, length=0, offset=-1): def __init__(self, the_uuid, raw_data, length=0, offset=-1):
""" """
@ -3227,8 +3225,7 @@ class UUIDBox(Jp2kBox):
else: else:
msg += ' (unknown)' msg += ' (unknown)'
if (((_printoptions['xml'] is False) and if ((_printoptions['xml'] is False) and (self.uuid == self._xmp_uuid)):
(self.uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac')))):
# If it's an XMP UUID, don't print the XML contents. # If it's an XMP UUID, don't print the XML contents.
return msg return msg

View file

@ -13,10 +13,10 @@ import sys
# pylint: disable=E0611 # pylint: disable=E0611
if sys.hexversion >= 0x03030000: if sys.hexversion >= 0x03030000:
from contextlib import ExitStack from contextlib import ExitStack
from itertools import compress, filterfalse from itertools import filterfalse
else: else:
from contextlib2 import ExitStack from contextlib2 import ExitStack
from itertools import compress, ifilterfalse as filterfalse from itertools import ifilterfalse as filterfalse
from collections import Counter from collections import Counter
import ctypes import ctypes
@ -517,12 +517,12 @@ class Jp2k(Jp2kBox):
# set image offset and reference grid # set image offset and reference grid
image.contents.x0 = self._cparams.image_offset_x0 image.contents.x0 = self._cparams.image_offset_x0
image.contents.y0 = self._cparams.image_offset_y0 image.contents.y0 = self._cparams.image_offset_y0
image.contents.x1 = image.contents.x0 \ image.contents.x1 = (image.contents.x0
+ (numcols - 1) * self._cparams.subsampling_dx \ + (numcols - 1) * self._cparams.subsampling_dx
+ 1 + 1)
image.contents.y1 = image.contents.y0 \ image.contents.y1 = (image.contents.y0
+ (numrows - 1) * self._cparams.subsampling_dy \ + (numrows - 1) * self._cparams.subsampling_dy
+ 1 + 1)
# Stage the image data to the openjpeg data structure. # Stage the image data to the openjpeg data structure.
for k in range(0, numlayers): for k in range(0, numlayers):
@ -832,7 +832,7 @@ class Jp2k(Jp2kBox):
raise IOError(msg) raise IOError(msg)
# Find the first codestream in the file. # Find the first codestream in the file.
jp2c = [box for box in self.box if box.box_id == 'jp2c'] jp2c = [_box for _box in self.box if _box.box_id == 'jp2c']
offset = jp2c[0].offset offset = jp2c[0].offset
# Ready to write the codestream. # Ready to write the codestream.
@ -1435,7 +1435,6 @@ class Jp2k(Jp2kBox):
codestream = Codestream(fptr, self.length, codestream = Codestream(fptr, self.length,
header_only=header_only) header_only=header_only)
else: else:
ftyp = self.box[1]
box = [x for x in self.box if x.box_id == 'jp2c'] box = [x for x in self.box if x.box_id == 'jp2c']
fptr.seek(box[0].offset) fptr.seek(box[0].offset)
read_buffer = fptr.read(8) read_buffer = fptr.read(8)