Merge branch 'issue99' into devel

This commit is contained in:
John Evans 2013-08-13 18:47:30 -04:00
commit 24de4a442a
23 changed files with 3034 additions and 2471 deletions

View file

@ -1,3 +1,7 @@
Aug 13, 2013 - v0.3.1 Exposed mantissa, exponent, and guard_bits fields in QCC
and QCD segments. Exposed layers and code_block_size in COD segment.
Exposed precinct_size in COC segment.
Jul 31, 2013 - v0.3.0 Added support for official 2.0.0.
Jul 27, 2013 - v0.2.8 Fixed inconsistency regarding configuration

View file

@ -8,6 +8,8 @@ from .jp2dump import jp2dump
from . import data
# unittest2 only in python-2.6 (pylint/python2.7 issue)
# pylint: disable=F0401
def runtests():
"""Discover and run all tests for the glymur package.
"""

View file

@ -3,7 +3,19 @@
The module contains classes used to store information parsed from JPEG 2000
codestreams.
"""
# pylint: disable=C0302,R0902,R0903,R0913
# The number of lines in the module is long and that's ok. It would not help
# matters to move anything out to another file.
# pylint: disable=C0302
# "Too many instance attributes", "Too many arguments"
# Some segments just have a lot of information.
# It doesn't make sense to subclass just for that.
# pylint: disable=R0902,R0913
# "Too few public methods" Some segments don't define any new methods from
# the base Segment class.
# pylint: disable=R0903
import math
import struct
@ -775,12 +787,15 @@ class Segment(object):
length : int
Length of marker segment in bytes. This number does not include the
two bytes constituting the marker.
data : bytes iterable or None
Uninterpreted buffer of raw bytes, only used where a segment is not
well understood.
"""
def __init__(self, marker_id='', offset=-1, length=-1, data=None):
self.marker_id = marker_id
self.offset = offset
self.length = length
self._data = data
self.data = data
def __str__(self):
msg = '{0} marker segment @ ({1}, {2})'.format(self.marker_id,
@ -807,6 +822,8 @@ class COCsegment(Segment):
Coding style for this component.
spcoc : byte array
Coding style parameters for this component.
precinct_size : list of tuples
Dimensions of precinct.
References
----------
@ -820,13 +837,13 @@ class COCsegment(Segment):
self.scoc = scoc
self.spcoc = spcoc
self._code_block_size = (4 * math.pow(2, self.spcoc[2]),
4 * math.pow(2, self.spcoc[1]))
self.code_block_size = (4 * math.pow(2, self.spcoc[2]),
4 * math.pow(2, self.spcoc[1]))
if len(self.spcoc) > 5:
self._precinct_size = _parse_precinct_size(self.spcoc[5:])
self.precinct_size = _parse_precinct_size(self.spcoc[5:])
else:
self._precinct_size = None
self.precinct_size = None
self.length = length
self.offset = offset
@ -847,16 +864,16 @@ class COCsegment(Segment):
msg += '\n Code block height, width: ({1} x {2})'
msg += '\n Wavelet transform: {3}'
msg = msg.format(self.spcoc[0] + 1,
int(self._code_block_size[0]),
int(self._code_block_size[1]),
int(self.code_block_size[0]),
int(self.code_block_size[1]),
_WAVELET_TRANSFORM_DISPLAY[self.spcoc[4]])
msg += '\n '
msg += _context_string(self.spcoc[3])
if self._precinct_size is not None:
if self.precinct_size is not None:
msg += '\n Precinct size: '
for pps in self._precinct_size:
for pps in self.precinct_size:
msg += '(%d, %d)'.format(pps)
return msg
@ -876,10 +893,16 @@ class CODsegment(Segment):
two bytes constituting the marker.
scod : int
Default coding style.
layers : int
Quality layers.
code_block_size : tuple
Size of code block.
spcod : bytes
Coding style parameters, including quality layers, multicomponent
transform usage, decomposition levels, code block size, style of code-
block passes, and which wavelet transform is used.
Encoded coding style parameters, including quality layers,
multi component transform usage, decomposition levels, code block size,
style of code-block passes, and which wavelet transform is used.
precinct_size : list of tuples
Dimensions of precinct.
References
----------
@ -895,7 +918,7 @@ class CODsegment(Segment):
self.offset = offset
params = struct.unpack('>BHBBBBBB', self.spcod[0:9])
self._layers = params[1]
self.layers = params[1]
self._numresolutions = params[3]
if params[3] > opj2.J2K_MAXRLVLS:
@ -906,12 +929,12 @@ class CODsegment(Segment):
cblk_width = 4 * math.pow(2, params[4])
cblk_height = 4 * math.pow(2, params[5])
code_block_size = (cblk_height, cblk_width)
self._code_block_size = code_block_size
self.code_block_size = code_block_size
if len(self.spcod) > 9:
self._precinct_size = _parse_precinct_size(self.spcod[9:])
self.precinct_size = _parse_precinct_size(self.spcod[9:])
else:
self._precinct_size = None
self.precinct_size = None
def __str__(self):
msg = Segment.__str__(self)
@ -944,18 +967,18 @@ class CODsegment(Segment):
msg += '\n '.join(lines)
msg = msg.format(_PROGRESSION_ORDER_DISPLAY[self.spcod[0]],
self._layers,
self.layers,
mct,
self.spcod[4] + 1,
int(self._code_block_size[0]),
int(self._code_block_size[1]),
int(self.code_block_size[0]),
int(self.code_block_size[1]),
_WAVELET_TRANSFORM_DISPLAY[self.spcod[8]])
msg += '\n Precinct size: '
if self._precinct_size is None:
if self.precinct_size is None:
msg += 'default, 2^15 x 2^15'
else:
for pps in self._precinct_size:
for pps in self.precinct_size:
msg += '({0}, {1})'.format(pps[0], pps[1])
msg += '\n '
@ -1195,8 +1218,8 @@ class PPMsegment(Segment):
Segment.__init__(self, marker_id='PPM')
self.zppm = zppm
# both Nppm and Ippms information stored in _data
self._data = data
# both Nppm and Ippms information stored in data
self.data = data
self.length = length
self.offset = offset
@ -1205,7 +1228,7 @@ class PPMsegment(Segment):
msg = Segment.__str__(self)
msg += '\n Index: {0}'
msg += '\n Data: {1} uninterpreted bytes'
msg = msg.format(self.zppm, len(self._data))
msg = msg.format(self.zppm, len(self.data))
return msg
@ -1265,6 +1288,10 @@ class QCCsegment(Segment):
Quantization style for this component.
spqcc : iterable bytes
Quantization value for each sub-band.
mantissa, exponent : iterable
Defines quantization factors.
guard_bits : int
Number of guard bits.
References
----------
@ -1280,18 +1307,18 @@ class QCCsegment(Segment):
self.length = length
self.offset = offset
self._mantissa, self._exponent = parse_quantization(self.spqcc,
self.mantissa, self.exponent = parse_quantization(self.spqcc,
self.sqcc)
self._guard_bits = (self.sqcc & 0xe0) >> 5
self.guard_bits = (self.sqcc & 0xe0) >> 5
def __str__(self):
msg = Segment.__str__(self)
msg += '\n Associated Component: {0}'.format(self.cqcc)
msg += _print_quantization_style(self.sqcc)
msg += '{0} guard bits'.format(self._guard_bits)
msg += '{0} guard bits'.format(self.guard_bits)
step_size = zip(self._mantissa, self._exponent)
step_size = zip(self.mantissa, self.exponent)
msg += '\n Step size: ' + str(list(step_size))
return msg
@ -1312,6 +1339,10 @@ class QCDsegment(Segment):
Quantization style for all components.
spqcd : iterable bytes
Quantization step size values (uninterpreted).
mantissa, exponent : iterable
Defines quantization factors.
guard_bits : int
Number of guard bits.
References
----------
@ -1328,18 +1359,18 @@ class QCDsegment(Segment):
self.offset = offset
mantissa, exponent = parse_quantization(self.spqcd, self.sqcd)
self._mantissa = mantissa
self._exponent = exponent
self._guard_bits = (self.sqcd & 0xe0) >> 5
self.mantissa = mantissa
self.exponent = exponent
self.guard_bits = (self.sqcd & 0xe0) >> 5
def __str__(self):
msg = Segment.__str__(self)
msg += _print_quantization_style(self.sqcd)
msg += '{0} guard bits'.format(self._guard_bits)
msg += '{0} guard bits'.format(self.guard_bits)
step_size = zip(self._mantissa, self._exponent)
step_size = zip(self.mantissa, self.exponent)
msg += '\n Step size: ' + str(list(step_size))
return msg
@ -1411,7 +1442,11 @@ class SIZsegment(Segment):
xtosiz, ytosiz : int
Horizontal and vertical offsets of tile from origin of reference grid.
ssiz : iterable bytes
Precision (depth) in bits and sign of each component.
Encoded precision (depth) in bits and sign of each component.
bitdepth : iterable bytes
Precision (depth) in bits of each component.
signed : iterable bool
Signedness of each component.
xrsiz, yrsiz : int
Horizontal and vertical sample separations with respect to reference
grid.
@ -1459,8 +1494,8 @@ class SIZsegment(Segment):
self.xrsiz = data[1::3]
self.yrsiz = data[2::3]
self._bitdepth = tuple(((x & 0x7f) + 1) for x in self.ssiz)
self._signed = tuple(((x & 0xb0) > 0) for x in self.ssiz)
self.bitdepth = tuple(((x & 0x7f) + 1) for x in self.ssiz)
self.signed = tuple(((x & 0xb0) > 0) for x in self.ssiz)
self.length = length
self.offset = offset
@ -1483,8 +1518,8 @@ class SIZsegment(Segment):
self.yosiz, self.xosiz,
self.ytsiz, self.xtsiz,
self.ytosiz, self.xtosiz,
self._bitdepth,
self._signed,
self.bitdepth,
self.signed,
tuple(zip(self.yrsiz, self.xrsiz)))
return msg

View file

@ -24,6 +24,7 @@ import uuid
import warnings
import xml.etree.cElementTree as ET
if sys.hexversion < 0x02070000:
# pylint: disable=F0401,E0611
from ordereddict import OrderedDict
from xml.etree.cElementTree import XMLParserError as ParseError
else:
@ -361,7 +362,8 @@ class _ICCProfile(object):
header['Connection Space'] = data
data = struct.unpack('>HHHHHH', self._raw_buffer[24:36])
header['Datetime'] = datetime.datetime(*data)
header['Datetime'] = datetime.datetime(data[0], data[1], data[2],
data[3], data[4], data[5])
header['File Signature'] = read_buffer[36:40].decode('utf-8')
if read_buffer[40:44] == b'\x00\x00\x00\x00':
header['Platform'] = 'unrecognized'
@ -369,10 +371,9 @@ class _ICCProfile(object):
header['Platform'] = read_buffer[40:44].decode('utf-8')
fval, = struct.unpack('>I', read_buffer[44:48])
flags = 'embedded, ' if fval & 0x01 else 'not embedded, '
flags += 'cannot ' if fval & 0x02 else 'can '
flags += 'be used independently'
header['Flags'] = flags
flags = "{0}embedded, {1} be used independently"
header['Flags'] = flags.format('' if fval & 0x01 else 'not ',
'cannot' if fval & 0x02 else 'can')
header['Device Manufacturer'] = read_buffer[48:52].decode('utf-8')
if read_buffer[52:56] == b'\x00\x00\x00\x00':
@ -382,11 +383,11 @@ class _ICCProfile(object):
header['Device Model'] = device_model
val, = struct.unpack('>Q', read_buffer[56:64])
attr = 'transparency, ' if val & 0x01 else 'reflective, '
attr += 'matte, ' if val & 0x02 else 'glossy, '
attr += 'negative ' if val & 0x04 else 'positive '
attr += 'media polarity, '
attr += 'black and white media' if val & 0x08 else 'color media'
attr = "{0}, {1}, {2} media polarity, {3} media"
attr = attr.format('transparency' if val & 0x01 else 'reflective',
'matte' if val & 0x02 else 'glossy',
'negative' if val & 0x04 else 'positive',
'black and white' if val & 0x08 else 'color')
header['Device Attributes'] = attr
rval, = struct.unpack('>I', read_buffer[64:68])
@ -1237,43 +1238,68 @@ class PaletteBox(Jp2kBox):
bps = [((x & 0x07f) + 1) for x in data]
signed = [((x & 0x80) > 1) for x in data]
# Each palette component is padded out to the next largest byte.
# That means a list comprehension does this in one shot.
row_nbytes = sum([int(math.ceil(x/8.0)) for x in bps])
# Form the format string so that we can intelligently unpack the
# colormap. We have to do this because it is possible that the
# colormap columns could have different datatypes.
#
# This means that we store the palette as a list of 1D arrays,
# which reverses the usual indexing scheme.
palette = []
fmt = '>'
row_nbytes = 0
for j in range(num_columns):
if bps[j] <= 8:
fmt += 'B'
row_nbytes += 1
palette.append(np.zeros(num_entries, dtype=np.uint8))
elif bps[j] <= 16:
fmt += 'H'
row_nbytes += 2
palette.append(np.zeros(num_entries, dtype=np.uint16))
elif bps[j] <= 32:
fmt += 'I'
row_nbytes += 4
palette.append(np.zeros(num_entries, dtype=np.uint32))
else:
msg = 'Unsupported palette bitdepth (%d).'.format(bps[j])
raise IOError(msg)
read_buffer = fptr.read(num_entries * row_nbytes)
palette = _buffer2palette(read_buffer, num_entries, num_columns, bps)
for j in range(num_entries):
row_buffer = read_buffer[(row_nbytes * j):(row_nbytes * (j + 1))]
row = struct.unpack(fmt, row_buffer)
for k in range(num_columns):
palette[k][j] = row[k]
box = PaletteBox(palette, bps, signed, length=length,
offset=offset)
box = PaletteBox(palette, bps, signed, length=length, offset=offset)
return box
def _buffer2palette(read_buffer, num_rows, num_cols, bps):
"""Construct the palette from the buffer read from file.
Parameters
----------
read_buffer : iterable
Byte array of palette information read from file.
num_rows, num_cols : int
Size of palette.
bps : iterable
Bits per sample for each channel.
Returns
-------
palette : list of 1D arrays
Each 1D array corresponds to a channel.
"""
row_nbytes = 0
palette = []
fmt = '>'
for j in range(num_cols):
if bps[j] <= 8:
row_nbytes += 1
fmt += 'B'
palette.append(np.zeros(num_rows, dtype=np.uint8))
elif bps[j] <= 16:
row_nbytes += 2
fmt += 'H'
palette.append(np.zeros(num_rows, dtype=np.uint16))
elif bps[j] <= 32:
row_nbytes += 4
fmt += 'I'
palette.append(np.zeros(num_rows, dtype=np.uint32))
else:
msg = 'Unsupported palette bitdepth (%d).'.format(bps[j])
raise IOError(msg)
for j in range(num_rows):
row_buffer = read_buffer[(row_nbytes * j):(row_nbytes * (j + 1))]
row = struct.unpack(fmt, row_buffer)
for k in range(num_cols):
palette[k][j] = row[k]
return palette
# Map rreq codes to display text.
_READER_REQUIREMENTS_DISPLAY = {
0: 'File not completely understood',
@ -1434,52 +1460,18 @@ class ReaderRequirementsBox(Jp2kBox):
"""
read_buffer = fptr.read(1)
mask_length, = struct.unpack('>B', read_buffer)
if mask_length == 1:
mask_format = 'B'
elif mask_length == 2:
mask_format = 'H'
elif mask_length == 4:
mask_format = 'I'
else:
msg = 'Unhandled reader requirements box mask length (%d).'
msg %= mask_length
raise RuntimeError(msg)
# Fully Understands Aspect Mask
# Decodes Completely Mask
read_buffer = fptr.read(2 * mask_length)
data = struct.unpack('>' + mask_format * 2, read_buffer)
fuam = data[0]
dcm = data[1]
read_buffer = fptr.read(2)
num_standard_flags, = struct.unpack('>H', read_buffer)
# The mask length tells us the format string to use when unpacking
# from the buffer read from file.
mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length]
fuam, dcm = struct.unpack('>' + mask_format * 2, read_buffer)
# Read in standard flags and standard masks. Each standard flag should
# be two bytes, but the standard mask flag is as long as specified by
# the mask length.
read_buffer = fptr.read(num_standard_flags * (2 + mask_length))
data = struct.unpack('>' + ('H' + mask_format) * num_standard_flags,
read_buffer)
standard_flag = data[0:num_standard_flags * 2:2]
standard_mask = data[1:num_standard_flags * 2:2]
# Vendor features
read_buffer = fptr.read(2)
num_vendor_features, = struct.unpack('>H', read_buffer)
# Each vendor feature consists of a 16-byte UUID plus a mask whose
# length is specified by, you guessed it, "mask_length".
entry_length = 16 + mask_length
read_buffer = fptr.read(num_vendor_features * entry_length)
vendor_feature = []
vendor_mask = []
for j in range(num_vendor_features):
ubuffer = read_buffer[j * entry_length:(j + 1) * entry_length]
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
vmask = struct.unpack('>' + mask_format, ubuffer[16:])
vendor_mask.append(vmask)
standard_flag, standard_mask = _parse_standard_flag(fptr, mask_length)
vendor_feature, vendor_mask = _parse_vendor_features(fptr, mask_length)
box = ReaderRequirementsBox(fuam, dcm, standard_flag, standard_mask,
vendor_feature, vendor_mask,
@ -1487,6 +1479,74 @@ class ReaderRequirementsBox(Jp2kBox):
return box
def _parse_standard_flag(fptr, mask_length):
"""Construct standard flag, standard mask data from the file.
Specifically working on Reader Requirements box.
Parameters
----------
fptr : file object
File object for JP2K file.
mask_length : int
Length of standard mask flag
"""
# The mask length tells us the format string to use when unpacking
# from the buffer read from file.
mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length]
read_buffer = fptr.read(2)
num_standard_flags, = struct.unpack('>H', read_buffer)
# Read in standard flags and standard masks. Each standard flag should
# be two bytes, but the standard mask flag is as long as specified by
# the mask length.
read_buffer = fptr.read(num_standard_flags * (2 + mask_length))
fmt = '>' + ('H' + mask_format) * num_standard_flags
data = struct.unpack(fmt, read_buffer)
standard_flag = data[0:num_standard_flags * 2:2]
standard_mask = data[1:num_standard_flags * 2:2]
return standard_flag, standard_mask
def _parse_vendor_features(fptr, mask_length):
"""Construct vendor features, vendor mask data from the file.
Specifically working on Reader Requirements box.
Parameters
----------
fptr : file object
File object for JP2K file.
mask_length : int
Length of vendor mask flag
"""
# The mask length tells us the format string to use when unpacking
# from the buffer read from file.
mask_format = {1: 'B', 2: 'H', 4: 'I'}[mask_length]
read_buffer = fptr.read(2)
num_vendor_features, = struct.unpack('>H', read_buffer)
# Each vendor feature consists of a 16-byte UUID plus a mask whose
# length is specified by, you guessed it, "mask_length".
entry_length = 16 + mask_length
read_buffer = fptr.read(num_vendor_features * entry_length)
vendor_feature = []
vendor_mask = []
for j in range(num_vendor_features):
ubuffer = read_buffer[j * entry_length:(j + 1) * entry_length]
vendor_feature.append(uuid.UUID(bytes=ubuffer[0:16]))
vmask = struct.unpack('>' + mask_format, ubuffer[16:])
vendor_mask.append(vmask)
return vendor_feature, vendor_mask
class ResolutionBox(Jp2kBox):
"""Container for Resolution superbox information.

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
"""This package organizes individual libraries employed by glymur."""
from . import openjp2 as _openjp2
from . import openjpeg as _openjpeg
from . import openjp2 as openjp2
from . import openjpeg as openjpeg
from . import c

View file

@ -1,6 +1,9 @@
"""
Configure glymur to use installed libraries if possible.
"""
# configparser is new in python3 (pylint/python-2.7)
# pylint: disable=F0401
import ctypes
from ctypes.util import find_library
import os

View file

@ -2,7 +2,7 @@
Wraps individual functions in openjp2 library.
"""
# pylint: disable=C0302,R0903
# pylint: disable=C0302,R0903,W0201
import ctypes
import sys
@ -1381,7 +1381,6 @@ def write_tile(codec, tile_index, data, data_size, stream):
def set_error_message(msg):
"""The openjpeg error handler has recorded an error message."""
global ERROR_MSG_LST
ERROR_MSG_LST.append(msg)

View file

@ -1 +1,3 @@
#from .test_openjp2 import TestOpenJP2 as openjp2
"""
Test suite for openjp2, openjpeg low-level functionality.
"""

View file

@ -1,9 +1,14 @@
#pylint: disable-all
import doctest
"""
Tests for libopenjp2 wrapping functions.
"""
# R0904: Seems like pylint is fooled in this situation
# W0142: using kwargs is ok in this context
# pylint: disable=R0904,W0142
# unittest2 is python-2.6 only (pylint/python-2.7)
# pylint: disable=F0401
import os
import pkg_resources
import shutil
import struct
import sys
import tempfile
@ -15,28 +20,28 @@ else:
import numpy as np
import glymur
from glymur.lib import openjp2
OPENJP2_IS_V2_OFFICIAL = False
if glymur.lib.openjp2.OPENJP2 is not None:
if not hasattr(glymur.lib.openjp2.OPENJP2,
if openjp2.OPENJP2 is not None:
if not hasattr(openjp2.OPENJP2,
'opj_stream_create_default_file_stream_v3'):
OPENJP2_IS_V2_OFFICIAL = True
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
@unittest.skipIf(openjp2.OPENJP2 is None,
"Missing openjp2 library.")
@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "API followed here specific to V2.0+")
class TestOpenJP2(unittest.TestCase):
"""Test openjp2 library functionality.
def setUp(self):
pass
Some tests correspond to those in the openjpeg test suite.
"""
def tearDown(self):
pass
def test_set_default_encoder_parameters(self):
cparams = glymur.lib._openjp2.set_default_encoder_parameters()
def test_default_encoder_parameters(self):
"""Ensure that the encoder structure is clean upon init."""
cparams = openjp2.set_default_encoder_parameters()
self.assertEqual(cparams.res_spec, 0)
self.assertEqual(cparams.cblockw_init, 64)
@ -52,8 +57,9 @@ class TestOpenJP2(unittest.TestCase):
self.assertEqual(cparams.irreversible, 0)
def test_set_default_decoder_parameters(self):
dparams = glymur.lib._openjp2.set_default_decoder_parameters()
def test_default_decoder_parameters(self):
"""Tests that the structure is clean upon initialization"""
dparams = openjp2.set_default_decoder_parameters()
self.assertEqual(dparams.DA_x0, 0)
self.assertEqual(dparams.DA_y0, 0)
@ -61,35 +67,34 @@ class TestOpenJP2(unittest.TestCase):
self.assertEqual(dparams.DA_y1, 0)
def tile_macro(self, codec, stream, imagep, tidx):
# called only by j2k_random_tile_access
glymur.lib._openjp2.get_decoded_tile(codec, stream, imagep, tidx)
"""called only by j2k_random_tile_access"""
openjp2.get_decoded_tile(codec, stream, imagep, tidx)
for j in range(imagep.contents.numcomps):
self.assertIsNotNone(imagep.contents.comps[j].data)
def j2k_random_tile_access(self, filename, codec_format=None):
# called by the test_rtaX methods
dparam = glymur.lib._openjp2.set_default_decoder_parameters()
"""fixture called by the test_rtaX methods"""
dparam = openjp2.set_default_decoder_parameters()
infile = filename.encode()
nelts = glymur.lib._openjp2.PATH_LEN - len(infile)
nelts = openjp2.PATH_LEN - len(infile)
infile += b'0' * nelts
dparam.infile = infile
dparam.decod_format = codec_format
codec = glymur.lib._openjp2.create_decompress(codec_format)
codec = openjp2.create_decompress(codec_format)
glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib._openjp2.set_error_handler(codec, None)
openjp2.set_info_handler(codec, None)
openjp2.set_warning_handler(codec, None)
openjp2.set_error_handler(codec, None)
x = (filename, True)
stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
stream = openjp2.stream_create_default_file_stream_v3(filename, True)
glymur.lib._openjp2.setup_decoder(codec, dparam)
image = glymur.lib._openjp2.read_header(stream, codec)
openjp2.setup_decoder(codec, dparam)
image = openjp2.read_header(stream, codec)
cstr_info = glymur.lib._openjp2.get_cstr_info(codec)
cstr_info = openjp2.get_cstr_info(codec)
tile_ul = 0
tile_ur = cstr_info.contents.tw - 1
@ -101,159 +106,39 @@ class TestOpenJP2(unittest.TestCase):
self.tile_macro(codec, stream, image, tile_lr)
self.tile_macro(codec, stream, image, tile_ll)
glymur.lib._openjp2.destroy_cstr_info(cstr_info)
openjp2.destroy_cstr_info(cstr_info)
glymur.lib._openjp2.end_decompress(codec, stream)
glymur.lib._openjp2.destroy_codec(codec)
glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib._openjp2.image_destroy(image)
def tile_decoder(self, x0=None, y0=None, x1=None, y1=None, filename=None,
codec_format=None):
x = (filename, True)
stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
dparam = glymur.lib._openjp2.set_default_decoder_parameters()
dparam.decod_format = codec_format
# Do not use layer decoding limitation.
dparam.cp_layer = 0
# do not use resolution reductions.
dparam.cp_reduce = 0
codec = glymur.lib._openjp2.create_decompress(codec_format)
glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib._openjp2.set_error_handler(codec, None)
glymur.lib._openjp2.setup_decoder(codec, dparam)
image = glymur.lib._openjp2.read_header(stream, codec)
glymur.lib._openjp2.set_decode_area(codec, image, x0, y0, x1, y1)
data = np.zeros((1150, 2048, 3), dtype=np.uint8)
while True:
rargs = glymur.lib._openjp2.read_tile_header(codec, stream)
tidx = rargs[0]
sz = rargs[1]
go_on = rargs[-1]
if not go_on:
break
glymur.lib._openjp2.decode_tile_data(codec, tidx, data, sz, stream)
glymur.lib._openjp2.end_decompress(codec, stream)
glymur.lib._openjp2.destroy_codec(codec)
glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib._openjp2.image_destroy(image)
def tile_encoder(self, num_comps=None, tile_width=None, tile_height=None,
filename=None, codec=None, comp_prec=None,
image_width=None, image_height=None,
irreversible=None):
num_tiles = (image_width / tile_width) * (image_height / tile_height)
tile_size = tile_width * tile_height * num_comps * comp_prec / 8
data = np.random.random((tile_height, tile_width, num_comps))
data = (data * 255).astype(np.uint8)
l_param = glymur.lib._openjp2.set_default_encoder_parameters()
l_param.tcp_numlayers = 1
l_param.cp_fixed_quality = 1
l_param.tcp_distoratio[0] = 20
# position of the tile grid aligned with the image
l_param.cp_tx0 = 0
l_param.cp_ty0 = 0
# tile size, we are using tile based encoding
l_param.tile_size_on = 1
l_param.cp_tdx = tile_width
l_param.cp_tdy = tile_height
# use irreversible encoding
l_param.irreversible = irreversible
l_param.numresolution = 6
l_param.prog_order = glymur.core.LRCP
l_params = (glymur.lib._openjp2.ImageComptParmType * num_comps)()
for j in range(num_comps):
l_params[j].dx = 1
l_params[j].dy = 1
l_params[j].h = image_height
l_params[j].w = image_width
l_params[j].sgnd = 0
l_params[j].prec = comp_prec
l_params[j].x0 = 0
l_params[j].y0 = 0
codec = glymur.lib._openjp2.create_compress(codec)
glymur.lib._openjp2.set_info_handler(codec, None)
glymur.lib._openjp2.set_warning_handler(codec, None)
glymur.lib._openjp2.set_error_handler(codec, None)
cspace = glymur.lib._openjp2.CLRSPC_SRGB
l_image = glymur.lib._openjp2.image_tile_create(l_params, cspace)
l_image.contents.x0 = 0
l_image.contents.y0 = 0
l_image.contents.x1 = image_width
l_image.contents.y1 = image_height
l_image.contents.color_space = glymur.lib._openjp2.CLRSPC_SRGB
glymur.lib._openjp2.setup_encoder(codec, l_param, l_image)
x = (filename, False)
stream = glymur.lib._openjp2.stream_create_default_file_stream_v3(*x)
glymur.lib._openjp2.start_compress(codec, l_image, stream)
for j in np.arange(num_tiles):
glymur.lib._openjp2.write_tile(codec, j, data, tile_size, stream)
glymur.lib._openjp2.end_compress(codec, stream)
glymur.lib._openjp2.stream_destroy_v3(stream)
glymur.lib._openjp2.destroy_codec(codec)
glymur.lib._openjp2.image_destroy(l_image)
def tte0_setup(self, filename):
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 3,
'image_height': 200,
'image_width': 200,
'tile_height': 100,
'tile_width': 100}
self.tile_encoder(**kwargs)
openjp2.end_decompress(codec, stream)
openjp2.destroy_codec(codec)
openjp2.stream_destroy_v3(stream)
openjp2.image_destroy(image)
def test_tte0(self):
# Runs test designated tte0 in OpenJPEG test suite.
"""Runs test designated tte0 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte0_setup(tfile.name)
ttx0_setup(tfile.name)
self.assertTrue(True)
def test_ttd0(self):
# Runs test designated ttd0 in OpenJPEG test suite.
"""Runs test designated ttd0 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
# Produce the tte0 output file for ttd0 input.
self.tte0_setup(tfile.name)
ttx0_setup(tfile.name)
kwargs = {'x0': 0,
'y0': 0,
'x1': 1000,
'y1': 1000,
'filename': tfile.name,
'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.tile_decoder(**kwargs)
'codec_format': openjp2.CODEC_J2K}
tile_decoder(**kwargs)
self.assertTrue(True)
def tte1_setup(self, filename):
def xtx1_setup(self, filename):
"""Runs tests tte1, rta1."""
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_J2K,
'codec': openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 3,
@ -261,149 +146,298 @@ class TestOpenJP2(unittest.TestCase):
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
self.tile_encoder(**kwargs)
tile_encoder(**kwargs)
self.assertTrue(True)
def test_tte1(self):
"""Runs test designated tte1 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
# Runs test designated tte1 in OpenJPEG test suite.
self.tte1_setup(tfile.name)
self.xtx1_setup(tfile.name)
def test_ttd1(self):
# Runs test designated ttd1 in OpenJPEG test suite.
"""Runs test designated ttd1 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
# Produce the tte0 output file for ttd0 input.
self.tte1_setup(tfile.name)
self.xtx1_setup(tfile.name)
kwargs = {'x0': 0,
'y0': 0,
'x1': 128,
'y1': 128,
'filename': tfile.name,
'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.tile_decoder(**kwargs)
'codec_format': openjp2.CODEC_J2K}
tile_decoder(**kwargs)
self.assertTrue(True)
def test_rta1(self):
"""Runs test designated rta1 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
# Runs test designated rta1 in OpenJPEG test suite.
self.tte1_setup(tfile.name)
self.xtx1_setup(tfile.name)
kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs)
def tte2_setup(self, filename):
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_JP2,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 3,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
self.tile_encoder(**kwargs)
codec_format = openjp2.CODEC_J2K
self.j2k_random_tile_access(tfile.name, codec_format)
self.assertTrue(True)
def test_tte2(self):
# Runs test designated tte2 in OpenJPEG test suite.
"""Runs test designated tte2 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
self.tte2_setup(tfile.name)
xtx2_setup(tfile.name)
self.assertTrue(True)
def test_ttd2(self):
# Runs test designated ttd2 in OpenJPEG test suite.
"""Runs test designated ttd2 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
# Produce the tte0 output file for ttd0 input.
self.tte2_setup(tfile.name)
xtx2_setup(tfile.name)
kwargs = {'x0': 0,
'y0': 0,
'x1': 128,
'y1': 128,
'filename': tfile.name,
'codec_format': glymur.lib._openjp2.CODEC_JP2}
self.tile_decoder(**kwargs)
'codec_format': openjp2.CODEC_JP2}
tile_decoder(**kwargs)
self.assertTrue(True)
def test_rta2(self):
"""Runs test designated rta2 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
# Runs test designated rta2 in OpenJPEG test suite.
self.tte2_setup(tfile.name)
xtx2_setup(tfile.name)
kwargs = {'codec_format': glymur.lib._openjp2.CODEC_JP2}
self.j2k_random_tile_access(tfile.name, **kwargs)
def tte3_setup(self, filename):
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 1,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
self.tile_encoder(**kwargs)
codec_format = openjp2.CODEC_JP2
self.j2k_random_tile_access(tfile.name, codec_format)
def test_tte3(self):
"""Runs test designated tte3 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
# Runs test designated tte3 in OpenJPEG test suite.
self.tte3_setup(tfile.name)
xtx3_setup(tfile.name)
self.assertTrue(True)
def test_rta3(self):
# Runs test designated rta3 in OpenJPEG test suite.
"""Runs test designated rta3 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte3_setup(tfile.name)
xtx3_setup(tfile.name)
kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs)
def tte4_setup(self, filename):
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 0,
'num_comps': 1,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
self.tile_encoder(**kwargs)
codec_format = openjp2.CODEC_J2K
self.j2k_random_tile_access(tfile.name, codec_format)
self.assertTrue(True)
def test_tte4(self):
# Runs test designated tte4 in OpenJPEG test suite.
"""Runs test designated tte4 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte4_setup(tfile.name)
xtx4_setup(tfile.name)
self.assertTrue(True)
def test_rta4(self):
# Runs test designated rta4 in OpenJPEG test suite.
"""Runs test designated rta4 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte4_setup(tfile.name)
xtx4_setup(tfile.name)
kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs)
def tte5_setup(self, filename):
kwargs = {'filename': filename,
'codec': glymur.lib._openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 0,
'num_comps': 1,
'image_height': 512,
'image_width': 512,
'tile_height': 256,
'tile_width': 256}
self.tile_encoder(**kwargs)
codec_format = openjp2.CODEC_J2K
self.j2k_random_tile_access(tfile.name, codec_format)
def test_tte5(self):
# Runs test designated tte5 in OpenJPEG test suite.
"""Runs test designated tte5 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte5_setup(tfile.name)
xtx5_setup(tfile.name)
self.assertTrue(True)
def test_rta5(self):
# Runs test designated rta5 in OpenJPEG test suite.
"""Runs test designated rta5 in OpenJPEG test suite."""
with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile:
self.tte5_setup(tfile.name)
xtx5_setup(tfile.name)
kwargs = {'codec_format': glymur.lib._openjp2.CODEC_J2K}
self.j2k_random_tile_access(tfile.name, **kwargs)
codec_format = openjp2.CODEC_J2K
self.j2k_random_tile_access(tfile.name, codec_format)
#def tile_encoder(num_comps=None, tile_width=None, tile_height=None,
# filename=None, codec=None, comp_prec=None,
# image_width=None, image_height=None,
# irreversible=None):
def tile_encoder(**kwargs):
"""Fixture used by many tests."""
num_tiles = ((kwargs['image_width'] / kwargs['tile_width']) *
(kwargs['image_height'] / kwargs['tile_height']))
tile_size = ((kwargs['tile_width'] * kwargs['tile_height']) *
(kwargs['num_comps'] * kwargs['comp_prec'] / 8))
data = np.random.random((kwargs['tile_height'],
kwargs['tile_width'],
kwargs['num_comps']))
data = (data * 255).astype(np.uint8)
l_param = openjp2.set_default_encoder_parameters()
l_param.tcp_numlayers = 1
l_param.cp_fixed_quality = 1
l_param.tcp_distoratio[0] = 20
# position of the tile grid aligned with the image
l_param.cp_tx0 = 0
l_param.cp_ty0 = 0
# tile size, we are using tile based encoding
l_param.tile_size_on = 1
l_param.cp_tdx = kwargs['tile_width']
l_param.cp_tdy = kwargs['tile_height']
# use irreversible encoding
l_param.irreversible = kwargs['irreversible']
l_param.numresolution = 6
l_param.prog_order = glymur.core.LRCP
l_params = (openjp2.ImageComptParmType * kwargs['num_comps'])()
for j in range(kwargs['num_comps']):
l_params[j].dx = 1
l_params[j].dy = 1
l_params[j].h = kwargs['image_height']
l_params[j].w = kwargs['image_width']
l_params[j].sgnd = 0
l_params[j].prec = kwargs['comp_prec']
l_params[j].x0 = 0
l_params[j].y0 = 0
codec = openjp2.create_compress(kwargs['codec'])
openjp2.set_info_handler(codec, None)
openjp2.set_warning_handler(codec, None)
openjp2.set_error_handler(codec, None)
cspace = openjp2.CLRSPC_SRGB
l_image = openjp2.image_tile_create(l_params, cspace)
l_image.contents.x0 = 0
l_image.contents.y0 = 0
l_image.contents.x1 = kwargs['image_width']
l_image.contents.y1 = kwargs['image_height']
l_image.contents.color_space = openjp2.CLRSPC_SRGB
openjp2.setup_encoder(codec, l_param, l_image)
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
False)
openjp2.start_compress(codec, l_image, stream)
for j in np.arange(num_tiles):
openjp2.write_tile(codec, j, data, tile_size, stream)
openjp2.end_compress(codec, stream)
openjp2.stream_destroy_v3(stream)
openjp2.destroy_codec(codec)
openjp2.image_destroy(l_image)
def tile_decoder(**kwargs):
"""Fixture called with various configurations by many tests.
Reads a tile. That's all it does.
"""
stream = openjp2.stream_create_default_file_stream_v3(kwargs['filename'],
True)
dparam = openjp2.set_default_decoder_parameters()
dparam.decod_format = kwargs['codec_format']
# Do not use layer decoding limitation.
dparam.cp_layer = 0
# do not use resolution reductions.
dparam.cp_reduce = 0
codec = openjp2.create_decompress(kwargs['codec_format'])
openjp2.set_info_handler(codec, None)
openjp2.set_warning_handler(codec, None)
openjp2.set_error_handler(codec, None)
openjp2.setup_decoder(codec, dparam)
image = openjp2.read_header(stream, codec)
openjp2.set_decode_area(codec, image,
kwargs['x0'], kwargs['y0'],
kwargs['x1'], kwargs['y1'])
data = np.zeros((1150, 2048, 3), dtype=np.uint8)
while True:
rargs = openjp2.read_tile_header(codec, stream)
tidx = rargs[0]
size = rargs[1]
go_on = rargs[-1]
if not go_on:
break
openjp2.decode_tile_data(codec, tidx, data, size, stream)
openjp2.end_decompress(codec, stream)
openjp2.destroy_codec(codec)
openjp2.stream_destroy_v3(stream)
openjp2.image_destroy(image)
def ttx0_setup(filename):
"""Runs tests tte0, tte0."""
kwargs = {'filename': filename,
'codec': openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 3,
'image_height': 200,
'image_width': 200,
'tile_height': 100,
'tile_width': 100}
tile_encoder(**kwargs)
def xtx2_setup(filename):
"""Runs tests rta2, tte2, ttd2."""
kwargs = {'filename': filename,
'codec': openjp2.CODEC_JP2,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 3,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
tile_encoder(**kwargs)
def xtx3_setup(filename):
"""Runs tests tte3, rta3."""
kwargs = {'filename': filename,
'codec': openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 1,
'num_comps': 1,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
tile_encoder(**kwargs)
def xtx4_setup(filename):
"""Runs tests rta4, tte4."""
kwargs = {'filename': filename,
'codec': openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 0,
'num_comps': 1,
'image_height': 256,
'image_width': 256,
'tile_height': 128,
'tile_width': 128}
tile_encoder(**kwargs)
def xtx5_setup(filename):
"""Runs tests rta5, tte5."""
kwargs = {'filename': filename,
'codec': openjp2.CODEC_J2K,
'comp_prec': 8,
'irreversible': 0,
'num_comps': 1,
'image_height': 512,
'image_width': 512,
'tile_height': 256,
'tile_width': 256}
tile_encoder(**kwargs)
if __name__ == "__main__":
unittest.main()

View file

@ -1,4 +1,11 @@
#pylint: disable-all
"""
Tests for OpenJPEG module.
"""
# unittest2 is python2.6 only (pylint/python-2.7)
# pylint: disable=F0401
# pylint: disable=E1101,R0904
import ctypes
import re
import sys
@ -10,43 +17,38 @@ else:
import glymur
@unittest.skipIf(glymur.lib._openjpeg.OPENJPEG is None,
@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
"Missing openjpeg library.")
class TestOpenJPEG(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
"""Test suite for openjpeg functions we choose to expose."""
def test_version(self):
version = glymur.lib._openjpeg.version()
"""Only versions 1.3, 1.4, and 1.5 are supported."""
version = glymur.lib.openjpeg.version()
regex = re.compile('1.[345].[0-9]')
if sys.hexversion <= 0x03020000:
self.assertRegexpMatches(version, regex)
else:
self.assertRegex(version, regex)
def test_set_default_decoder_parameters(self):
# Verify that we properly set the default decode parameters.
version = glymur.lib._openjpeg.version()
def test_default_decoder_parameters(self):
"""Verify that we properly set the default decode parameters."""
version = glymur.lib.openjpeg.version()
minor = int(version.split('.')[1])
dp = glymur.lib._openjpeg.DecompressionParametersType()
glymur.lib._openjpeg.set_default_decoder_parameters(ctypes.byref(dp))
dcp = glymur.lib.openjpeg.DecompressionParametersType()
glymur.lib.openjpeg.set_default_decoder_parameters(ctypes.byref(dcp))
self.assertEqual(dp.cp_reduce, 0)
self.assertEqual(dp.cp_layer, 0)
self.assertEqual(dp.infile, b'')
self.assertEqual(dp.outfile, b'')
self.assertEqual(dp.decod_format, -1)
self.assertEqual(dp.cod_format, -1)
self.assertEqual(dp.jpwl_correct, 0)
self.assertEqual(dp.jpwl_exp_comps, 0)
self.assertEqual(dp.jpwl_max_tiles, 0)
self.assertEqual(dp.cp_limit_decoding, 0)
self.assertEqual(dcp.cp_reduce, 0)
self.assertEqual(dcp.cp_layer, 0)
self.assertEqual(dcp.infile, b'')
self.assertEqual(dcp.outfile, b'')
self.assertEqual(dcp.decod_format, -1)
self.assertEqual(dcp.cod_format, -1)
self.assertEqual(dcp.jpwl_correct, 0)
self.assertEqual(dcp.jpwl_exp_comps, 0)
self.assertEqual(dcp.jpwl_max_tiles, 0)
self.assertEqual(dcp.cp_limit_decoding, 0)
if minor > 4:
# Introduced in 1.5.x
self.assertEqual(dp.flags, 0)
self.assertEqual(dcp.flags, 0)

View file

@ -36,8 +36,8 @@ except ImportError:
def read_image(infile):
"""Read image using matplotlib backend.
Hopefully PIL(low) is installed as matplotlib's backend. It issues
Hopefully PIL(low) is installed as matplotlib's backend. It issues
warnings which we do not care about, so suppress them.
"""
with warnings.catch_warnings():
@ -101,6 +101,7 @@ def read_pgx(pgx_file):
return(data.byteswap(swapbytes))
def determine_pgx_datatype(signed, bitdepth):
"""Determine the datatype of the PGX file.
@ -128,6 +129,7 @@ def determine_pgx_datatype(signed, bitdepth):
return dtype
def read_pgx_header(pgx_file):
"""Open the file in ascii mode (not really) and read the header line.
Will look something like
@ -150,4 +152,3 @@ def read_pgx_header(pgx_file):
header = header.rstrip()
return header, pos

View file

@ -1,6 +1,13 @@
#pylint: disable-all
"""
Test suite for openjpeg's callback functions.
"""
# R0904: Seems like pylint is fooled in this situation
# pylint: disable=R0904
# 'mock' most certainly is in unittest (Python 3.3)
# pylint: disable=E0611,F0401
import os
import pkg_resources
import re
import sys
import tempfile
@ -24,6 +31,7 @@ import glymur
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
class TestCallbacks(unittest.TestCase):
"""Test suite for callbacks."""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -34,7 +42,7 @@ class TestCallbacks(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_info_callback_on_write(self):
# Verify the messages printed when writing an image in verbose mode.
"""Verify messages printed when writing an image in verbose mode."""
j = glymur.Jp2k(self.jp2file)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
@ -47,12 +55,14 @@ class TestCallbacks(unittest.TestCase):
expected = '[INFO] tile number 1 / 1'
self.assertEqual(actual, expected)
def test_info_warning_callbacks_on_read(self):
def test_info_callbacks_on_read(self):
"""stdio output when info callback handler is enabled"""
# Verify that we get the expected stdio output when our internal info
# callback handler is enabled.
j = glymur.Jp2k(self.j2kfile)
with patch('sys.stdout', new=StringIO()) as fake_out:
d = j.read(rlevel=1, verbose=True, area=(0, 0, 200, 150))
j.read(rlevel=1, verbose=True, area=(0, 0, 200, 150))
actual = fake_out.getvalue().strip()
lines = ['[INFO] Start to read j2k main header (0).',
@ -80,13 +90,16 @@ class TestCallbacks15(unittest.TestCase):
pass
def test_info_callbacks_on_read(self):
# Verify that we get the expected stdio output when our internal info
# callback handler is enabled.
"""Verify stdout when reading.
Verify that we get the expected stdio output when our internal info
callback handler is enabled.
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
# Force to use OPENJPEG instead of OPENJP2.
j = glymur.Jp2k(self.j2kfile)
with patch('sys.stdout', new=StringIO()) as fake_out:
d = j.read(rlevel=1, verbose=True)
j.read(rlevel=1, verbose=True)
actual = fake_out.getvalue().strip()
regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+
@ -97,6 +110,9 @@ class TestCallbacks15(unittest.TestCase):
\[INFO\]\s-\stile\sdecoded\sin\s
[0-9]+\.[0-9]+\ss""",
re.VERBOSE)
# assertRegex in Python 3.3 (python2.7/pylint issue)
# pylint: disable=E1101
if sys.hexversion <= 0x03020000:
self.assertRegexpMatches(actual, regex)
else:

View file

@ -1,4 +1,16 @@
#pylint: disable-all
"""
Test suite for codestream parsing.
"""
# unittest doesn't work well with R0904.
# pylint: disable=R0904
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
# pylint: disable=E1101
# unittest2 is python2.6 only (pylint/python-2.7)
# pylint: disable=F0401
import os
import struct
import sys
@ -9,23 +21,21 @@ if sys.hexversion < 0x02070000:
else:
import unittest
import numpy as np
import pkg_resources
from glymur import Jp2k
import glymur
try:
data_root = os.environ['OPJ_DATA_ROOT']
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
DATA_ROOT = None
except:
raise
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestCodestream(unittest.TestCase):
"""Test suite for unusual codestream cases."""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -35,75 +45,76 @@ class TestCodestream(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_reserved_marker_segment(self):
"""Reserved marker segments are ok."""
# Some marker segments were reserved in FCD15444-1. Since that
# standard is old, some of them may have come into use.
#
# Let's inject a reserved marker segment into a file that
# we know something about to make sure we can still parse it.
filename = os.path.join(data_root, 'input/conformance/p0_01.j2k')
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
with open(filename, 'rb') as ifile:
# Everything up until the first QCD marker.
buffer = ifile.read(45)
tfile.write(buffer)
read_buffer = ifile.read(45)
tfile.write(read_buffer)
# Write the new marker segment, 0xff6f = 65391
buffer = struct.pack('>HHB', int(65391), int(3), int(0))
tfile.write(buffer)
read_buffer = struct.pack('>HHB', int(65391), int(3), int(0))
tfile.write(read_buffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
read_buffer = ifile.read()
tfile.write(read_buffer)
tfile.flush()
j = Jp2k(tfile.name)
c = j.get_codestream()
codestream = Jp2k(tfile.name).get_codestream()
self.assertEqual(c.segment[2].marker_id, '0xff6f')
self.assertEqual(c.segment[2].length, 3)
self.assertEqual(c.segment[2]._data, b'\x00')
self.assertEqual(codestream.segment[2].marker_id, '0xff6f')
self.assertEqual(codestream.segment[2].length, 3)
self.assertEqual(codestream.segment[2].data, b'\x00')
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_unknown_marker_segment(self):
"""Should warn for an unknown marker."""
# Let's inject a marker segment whose marker does not appear to
# be valid. We still parse the file, but warn about the offending
# marker.
filename = os.path.join(data_root, 'input/conformance/p0_01.j2k')
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
with open(filename, 'rb') as ifile:
# Everything up until the first QCD marker.
buffer = ifile.read(45)
tfile.write(buffer)
read_buffer = ifile.read(45)
tfile.write(read_buffer)
# Write the new marker segment, 0xff79 = 65401
buffer = struct.pack('>HHB', int(65401), int(3), int(0))
tfile.write(buffer)
read_buffer = struct.pack('>HHB', int(65401), int(3), int(0))
tfile.write(read_buffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
read_buffer = ifile.read()
tfile.write(read_buffer)
tfile.flush()
with self.assertWarns(UserWarning):
j = Jp2k(tfile.name)
c = j.get_codestream()
codestream = Jp2k(tfile.name).get_codestream()
self.assertEqual(c.segment[2].marker_id, '0xff79')
self.assertEqual(c.segment[2].length, 3)
self.assertEqual(c.segment[2]._data, b'\x00')
self.assertEqual(codestream.segment[2].marker_id, '0xff79')
self.assertEqual(codestream.segment[2].length, 3)
self.assertEqual(codestream.segment[2].data, b'\x00')
def test_psot_is_zero(self):
# Psot=0 in SOT is perfectly legal. Issue #78.
filename = os.path.join(data_root,
"""Psot=0 in SOT is perfectly legal. Issue #78."""
filename = os.path.join(DATA_ROOT,
'input/nonregression/123.j2c')
j = Jp2k(filename)
c = j.get_codestream(header_only=False)
codestream = j.get_codestream(header_only=False)
# The codestream is valid, so we should be able to get the entire
# codestream, so the last one is EOC.
self.assertEqual(c.segment[-1].marker_id, 'EOC')
self.assertEqual(codestream.segment[-1].marker_id, 'EOC')
if __name__ == "__main__":
unittest.main()

View file

@ -1,7 +1,15 @@
"""These tests are for edge cases where OPENJPEG does not exist, but
OPENJP2 may be present in some form or other.
"""
#pylint: disable-all
# unittest doesn't work well with R0904.
# pylint: disable=R0904
# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2
# pylint: disable=E1101
# unittest.mock only in Python 3.3 (python2.7/pylint import issue)
# pylint: disable=E0611,F0401
import imp
import os
@ -17,13 +25,9 @@ if sys.hexversion <= 0x03030000:
from mock import patch
else:
from unittest.mock import patch
import warnings
import pkg_resources
import glymur
from glymur import Jp2k
from glymur.lib import openjp2 as opj2
@unittest.skipIf(sys.hexversion < 0x03020000,
@ -31,6 +35,7 @@ from glymur.lib import openjp2 as opj2
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Needs openjp2 library first before these tests make sense.")
class TestSuite(unittest.TestCase):
"""Test suite for configuration file operation."""
@classmethod
def setUpClass(cls):
@ -56,29 +61,33 @@ class TestSuite(unittest.TestCase):
filename = os.path.join(configdir, 'glymurrc')
with open(filename, 'wt') as tfile:
tfile.write('[library]\n')
# Need to reliably recover the location of the openjp2 library,
# so using '_name' appears to be the only way to do it.
# pylint: disable=W0212
libloc = glymur.lib.openjp2.OPENJP2._name
line = 'openjp2: {0}\n'.format(libloc)
tfile.write(line)
tfile.flush()
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
imp.reload(glymur.lib.openjp2)
j = Jp2k(self.jp2file)
Jp2k(self.jp2file)
def test_config_file_via_environ_is_wrong(self):
# A non-existant library location should be rejected.
def test_xdg_env_config_file_is_bad(self):
"""A non-existant library location should be rejected."""
with tempfile.TemporaryDirectory() as tdir:
configdir = os.path.join(tdir, 'glymur')
os.mkdir(configdir)
fname = os.path.join(configdir, 'glymurrc')
with open(fname, 'w') as fp:
with open(fname, 'w') as fptr:
with tempfile.NamedTemporaryFile(suffix='.dylib') as tfile:
fp.write('[library]\n')
fp.write('openjp2: {0}.not.there\n'.format(tfile.name))
fp.flush()
fptr.write('[library]\n')
fptr.write('openjp2: {0}.not.there\n'.format(tfile.name))
fptr.flush()
with patch.dict('os.environ', {'XDG_CONFIG_HOME': tdir}):
# Misconfigured new configuration file should
# be rejected.
with self.assertWarns(UserWarning) as cw:
with self.assertWarns(UserWarning):
imp.reload(glymur.lib.openjp2)
if __name__ == "__main__":

View file

@ -1,9 +1,17 @@
"""
These tests deal with JPX/JP2/J2K images in the format-corpus repository.
"""
#pylint: disable-all
# R0904: Not too many methods in unittest.
# pylint: disable=R0904
# E1101: assertWarns introduced in python 3.2
# pylint: disable=E1101
# unittest2 is python2.6 only (pylint/python-2.7)
# pylint: disable=F0401
import os
from os.path import join
import sys
if sys.hexversion < 0x02070000:
@ -11,106 +19,98 @@ if sys.hexversion < 0x02070000:
else:
import unittest
import warnings
from glymur import Jp2k
import glymur
try:
format_corpus_data_root = os.environ['FORMAT_CORPUS_DATA_ROOT']
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
except KeyError:
format_corpus_data_root = None
FORMAT_CORPUS_DATA_ROOT = None
try:
opj_data_root = os.environ['OPJ_DATA_ROOT']
OPJ_DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
opj_data_root = None
OPJ_DATA_ROOT = None
@unittest.skipIf(format_corpus_data_root is None,
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
@unittest.skipIf(sys.hexversion < 0x03020000,
"Requires features introduced in 3.2 (assertWarns)")
class TestSuiteFormatCorpus(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
"""Test suite for files in format corpus repository."""
def test_balloon_trunc1(self):
# Has one byte shaved off of EOC marker.
jfile = os.path.join(format_corpus_data_root,
"""Has one byte shaved off of EOC marker."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-test/byteCorruption/balloon_trunc1.jp2')
j2k = Jp2k(jfile)
with self.assertWarns(UserWarning):
c = j2k.get_codestream(header_only=False)
codestream = j2k.get_codestream(header_only=False)
# The last segment is truncated, so there should not be an EOC marker.
self.assertNotEqual(c.segment[-1].marker_id, 'EOC')
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
# The codestream is not as long as claimed.
with self.assertRaises(OSError):
j2k.read(rlevel=-1)
def test_balloon_trunc2(self):
# Shortened by 5000 bytes.
jfile = os.path.join(format_corpus_data_root,
"""Shortened by 5000 bytes."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-test/byteCorruption/balloon_trunc2.jp2')
j2k = Jp2k(jfile)
with self.assertWarns(UserWarning):
c = j2k.get_codestream(header_only=False)
codestream = j2k.get_codestream(header_only=False)
# The last segment is truncated, so there should not be an EOC marker.
self.assertNotEqual(c.segment[-1].marker_id, 'EOC')
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
# The codestream is not as long as claimed.
with self.assertRaises(OSError):
j2k.read(rlevel=-1)
def test_balloon_trunc3(self):
# Most of last tile is missing.
jfile = os.path.join(format_corpus_data_root,
"""Most of last tile is missing."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-test/byteCorruption/balloon_trunc3.jp2')
j2k = Jp2k(jfile)
with self.assertWarns(UserWarning):
c = j2k.get_codestream(header_only=False)
codestream = j2k.get_codestream(header_only=False)
# The last segment is truncated, so there should not be an EOC marker.
self.assertNotEqual(c.segment[-1].marker_id, 'EOC')
self.assertNotEqual(codestream.segment[-1].marker_id, 'EOC')
# Should error out, it does not.
#with self.assertRaises(OSError):
# j2k.read(rlevel=-1)
def test_jp2_brand_vs_any_icc_profile(self):
# If 'jp2 ', then the method cannot be any icc profile.
jfile = os.path.join(format_corpus_data_root,
def test_jp2_brand_any_icc_profile(self):
"""If 'jp2 ', then the method cannot be any icc profile."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-test', 'icc',
'balloon_eciRGBv2_ps_adobeplugin.jpf')
with self.assertWarns(UserWarning):
j2k = Jp2k(jfile)
Jp2k(jfile)
def test_jp2_brand_vs_any_icc_profile_multiple_colr(self):
# Has colr box, one that conforms, one that does not.
def test_jp2_brand_iccpr_mult_colr(self):
"""Has colr box, one that conforms, one that does not."""
# Wrong 'brand' field; contains two versions of ICC profile: one
# embedded using "Any ICC" method; other embedded using "Restricted
# ICC" method, with description ("Modified eciRGB v2") and profileClass
# ("Input Device") changed relative to original profile.
lst = [format_corpus_data_root, 'jp2k-test', 'icc',
'balloon_eciRGBv2_ps_adobeplugin_jp2compatible.jpf']
jfile = os.path.join(*lst)
jfile = join(FORMAT_CORPUS_DATA_ROOT, 'jp2k-test', 'icc',
'balloon_eciRGBv2_ps_adobeplugin_jp2compatible.jpf')
with self.assertWarns(UserWarning):
j2k = Jp2k(jfile)
Jp2k(jfile)
@unittest.skipIf(opj_data_root is None,
@unittest.skipIf(OPJ_DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
@unittest.skipIf(sys.hexversion < 0x03020000,
"Requires features introduced in 3.2 (assertWarns)")
class TestSuiteOpj(unittest.TestCase):
"""Test suite for files in openjpeg repository."""
def setUp(self):
pass
@ -118,12 +118,12 @@ class TestSuiteOpj(unittest.TestCase):
def tearDown(self):
pass
def test_jp2_brand_vs_any_icc_profile(self):
# If 'jp2 ', then the method cannot be any icc profile.
filename = os.path.join(opj_data_root,
def test_jp2_brand_any_icc_profile(self):
"""If 'jp2 ', then the method cannot be any icc profile."""
filename = os.path.join(OPJ_DATA_ROOT,
'input/nonregression/text_GBR.jp2')
with self.assertWarns(UserWarning):
j2k = Jp2k(filename)
Jp2k(filename)
if __name__ == "__main__":
unittest.main()

View file

@ -1,35 +1,38 @@
#pylint: disable-all
"""
ICC profile tests.
"""
# unittest doesn't work well with R0904.
# pylint: disable=R0904
# unittest2 is python2.6 only (pylint/python-2.7)
# pylint: disable=F0401
import datetime
import os
import struct
import sys
import tempfile
if sys.hexversion < 0x02070000:
import unittest2 as unittest
else:
import unittest
import warnings
from xml.etree import cElementTree as ET
import numpy as np
import pkg_resources
from glymur import Jp2k
import glymur
try:
data_root = os.environ['OPJ_DATA_ROOT']
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
DATA_ROOT = None
except:
raise
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestICC(unittest.TestCase):
"""ICC profile tests"""
def setUp(self):
pass
@ -38,7 +41,8 @@ class TestICC(unittest.TestCase):
pass
def test_file5(self):
filename = os.path.join(data_root, 'input/conformance/file5.jp2')
"""basic ICC profile"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file5.jp2')
j = Jp2k(filename)
profile = j.box[3].box[1].icc_profile
self.assertEqual(profile['Size'], 546)
@ -70,10 +74,14 @@ class TestICC(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_invalid_profile_header(self):
jfile = os.path.join(data_root,
"""invalid ICC header data should cause UserWarning"""
jfile = os.path.join(DATA_ROOT,
'input/nonregression/orb-blue10-lin-jp2.jp2')
with self.assertWarns(UserWarning) as cw:
j = Jp2k(jfile)
# assertWarns in Python 3.3 (python2.7/pylint issue)
# pylint: disable=E1101
with self.assertWarns(UserWarning):
Jp2k(jfile)
if __name__ == "__main__":
unittest.main()

View file

@ -1,4 +1,21 @@
#pylint: disable-all
"""
Test suite specifically targeting JP2 box layout.
"""
# E1103: return value from read may be list or np array
# pylint: disable=E1103
# F0401: unittest2 is needed on python-2.6 (pylint on 2.7)
# pylint: disable=F0401
# R0902: More than 7 instance attributes are just fine for testing.
# pylint: disable=R0902
# R0904: Seems like pylint is fooled in this situation
# pylint: disable=R0904
# W0613: load_tests doesn't need to use ignore or loader arguments.
# pylint: disable=W0613
import doctest
import os
import sys
@ -11,24 +28,25 @@ else:
import unittest
import numpy as np
import pkg_resources
import glymur
from glymur import Jp2k
from glymur.jp2box import *
from glymur.jp2box import ColourSpecificationBox, ContiguousCodestreamBox
from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
from glymur.jp2box import JPEG2000SignatureBox
from glymur.core import COLOR, OPACITY
from glymur.core import RED, GREEN, BLUE, GREY, WHOLE_IMAGE
from .fixtures import OPENJP2_IS_V2_OFFICIAL
try:
format_corpus_data_root = os.environ['FORMAT_CORPUS_DATA_ROOT']
FORMAT_CORPUS_DATA_ROOT = os.environ['FORMAT_CORPUS_DATA_ROOT']
except KeyError:
format_corpus_data_root = None
FORMAT_CORPUS_DATA_ROOT = None
# Doc tests should be run as well.
def load_tests(loader, tests, ignore):
"""Run doc tests as well."""
if os.name == "nt":
# Can't do it on windows, temporary file issue.
return tests
@ -42,6 +60,7 @@ def load_tests(loader, tests, ignore):
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
class TestChannelDefinition(unittest.TestCase):
"""Test suite for channel definition boxes."""
@classmethod
def setUpClass(cls):
@ -78,12 +97,12 @@ class TestChannelDefinition(unittest.TestCase):
self.j2kfile = glymur.data.goodstuff()
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox()
self.jp2b = JPEG2000SignatureBox()
self.ftyp = FileTypeBox()
self.jp2h = JP2HeaderBox()
self.jp2c = ContiguousCodestreamBox()
@ -110,7 +129,7 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -133,7 +152,7 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -156,7 +175,7 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -177,9 +196,9 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_grey(self):
@ -191,7 +210,7 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -212,7 +231,7 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -236,12 +255,12 @@ class TestChannelDefinition(unittest.TestCase):
association=association)
boxes = [self.ihdr, self.colr_gr, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises((OSError, IOError)) as ce:
with self.assertRaises((OSError, IOError)):
j2k.wrap(tfile.name, boxes=boxes)
def test_only_one_cdef_in_jp2_header(self):
def test_only_one_cdef_in_jp2h(self):
"""There can only be one channel definition box in the jp2 header."""
j2k = Jp2k(self.j2kfile)
@ -253,13 +272,14 @@ class TestChannelDefinition(unittest.TestCase):
boxes = [self.ihdr, cdef, self.colr_rgb, cdef]
self.jp2h.box = boxes
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_not_in_jp2_header(self):
def test_not_in_jp2h(self):
"""need cdef in jp2h"""
j2k = Jp2k(self.j2kfile)
boxes = [self.ihdr, self.colr_rgb]
self.jp2h.box = boxes
@ -269,34 +289,37 @@ class TestChannelDefinition(unittest.TestCase):
cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
boxes = [self.jP, self.ftyp, self.jp2h, cdef, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, cdef, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_bad_type(self):
# Channel types are limited to 0, 1, 2, 65535
# Should reject if not all of index, channel_type, association the
# same length.
"""Channel types are limited to 0, 1, 2, 65535
Should reject if not all of index, channel_type, association the
same length.
"""
channel_type = (COLOR, COLOR, 3)
association = (RED, GREEN, BLUE)
with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
def test_wrong_lengths(self):
# Should reject if not all of index, channel_type, association the
# same length.
"""Should reject if not all of index, channel_type, association the
same length.
"""
channel_type = (COLOR, COLOR)
association = (RED, GREEN, BLUE)
with self.assertRaises(IOError):
box = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type,
association=association)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
class TestXML(unittest.TestCase):
"""Test suite for XML boxes."""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -331,12 +354,12 @@ class TestXML(unittest.TestCase):
self.xmlfile = tfile.name
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox()
self.jp2b = JPEG2000SignatureBox()
self.ftyp = FileTypeBox()
self.jp2h = JP2HeaderBox()
self.jp2c = ContiguousCodestreamBox()
@ -346,19 +369,17 @@ class TestXML(unittest.TestCase):
def tearDown(self):
os.unlink(self.xmlfile)
pass
def test_negative_both_file_and_xml_provided(self):
def test_negative_file_and_xml(self):
"""The XML should come from only one source."""
j2k = Jp2k(self.j2kfile)
xml_object = ET.parse(self.xmlfile)
with self.assertRaises((IOError, OSError)) as ce:
xmlb = glymur.jp2box.XMLBox(filename=self.xmlfile, xml=xml_object)
with self.assertRaises((IOError, OSError)):
glymur.jp2box.XMLBox(filename=self.xmlfile, xml=xml_object)
@unittest.skipIf(os.name == "nt",
"Problems using NamedTemporaryFile on windows.")
def test_basic_xml(self):
# Should be able to write an XMLBox.
"""Should be able to write a basic XMLBox"""
j2k = Jp2k(self.j2kfile)
self.jp2h.box = [self.ihdr, self.colr]
@ -368,7 +389,7 @@ class TestXML(unittest.TestCase):
self.assertEqual(ET.tostring(xmlb.xml),
b'<data>0</data>')
boxes = [self.jP, self.ftyp, self.jp2h, xmlb, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, xmlb, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
@ -380,12 +401,13 @@ class TestXML(unittest.TestCase):
@unittest.skipIf(os.name == "nt",
"Problems using NamedTemporaryFile on windows.")
def test_xml_from_file(self):
"""Must be able to create an XML box from an XML file."""
j2k = Jp2k(self.j2kfile)
self.jp2h.box = [self.ihdr, self.colr]
xmlb = glymur.jp2box.XMLBox(filename=self.xmlfile)
boxes = [self.jP, self.ftyp, self.jp2h, xmlb, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, xmlb, self.jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name, boxes=boxes)
jp2 = Jp2k(tfile.name)
@ -403,17 +425,18 @@ class TestXML(unittest.TestCase):
class TestColourSpecificationBox(unittest.TestCase):
"""Test suite for colr box instantiation."""
def setUp(self):
self.j2kfile = glymur.data.goodstuff()
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
self.jP = JPEG2000SignatureBox()
self.jp2b = JPEG2000SignatureBox()
self.ftyp = FileTypeBox()
self.jp2h = JP2HeaderBox()
self.jp2c = ContiguousCodestreamBox()
@ -425,10 +448,11 @@ class TestColourSpecificationBox(unittest.TestCase):
@unittest.skipIf(os.name == "nt",
"Problems using NamedTemporaryFile on windows.")
def test_color_specification_box_with_out_enumerated_colorspace(self):
def test_colr_with_out_enum_cspace(self):
"""must supply an enumerated colorspace when writing"""
j2k = Jp2k(self.j2kfile)
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
boxes[2].box = [self.ihdr, ColourSpecificationBox(colorspace=None)]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(NotImplementedError):
@ -436,47 +460,52 @@ class TestColourSpecificationBox(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_missing_colr_box(self):
"""jp2h must have a colr box"""
j2k = Jp2k(self.j2kfile)
boxes = [self.jP, self.ftyp, self.jp2h, self.jp2c]
boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c]
boxes[2].box = [self.ihdr]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
def test_default_ColourSpecificationBox(self):
b = glymur.jp2box.ColourSpecificationBox(colorspace=glymur.core.SRGB)
self.assertEqual(b.method, glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(b.precedence, 0)
self.assertEqual(b.approximation, 0)
self.assertEqual(b.colorspace, glymur.core.SRGB)
self.assertIsNone(b.icc_profile)
def test_default_colr(self):
"""basic colr instantiation"""
colr = ColourSpecificationBox(colorspace=glymur.core.SRGB)
self.assertEqual(colr.method, glymur.core.ENUMERATED_COLORSPACE)
self.assertEqual(colr.precedence, 0)
self.assertEqual(colr.approximation, 0)
self.assertEqual(colr.colorspace, glymur.core.SRGB)
self.assertIsNone(colr.icc_profile)
def test_ColourSpecificationBox_with_colorspace_and_icc(self):
# Colour specification boxes can't have both.
def test_colr_with_cspace_and_icc(self):
"""Colour specification boxes can't have both."""
with self.assertRaises((OSError, IOError)):
colorspace = glymur.core.SRGB
icc_profile = b'\x01\x02\x03\x04'
b = glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
icc_profile=icc_profile)
rawb = b'\x01\x02\x03\x04'
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
icc_profile=rawb)
def test_ColourSpecificationBox_with_bad_method(self):
def test_colr_with_bad_method(self):
"""colr must have a valid method field"""
colorspace = glymur.core.SRGB
method = -1
with self.assertRaises(IOError):
b = glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
method=method)
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
method=method)
def test_ColourSpecificationBox_with_bad_approximation(self):
def test_colr_with_bad_approx(self):
"""colr must have a valid approximation field"""
colorspace = glymur.core.SRGB
approx = -1
with self.assertRaises(IOError):
b = glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
approximation=approx)
glymur.jp2box.ColourSpecificationBox(colorspace=colorspace,
approximation=approx)
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
class TestWrap(unittest.TestCase):
"""Tests for wrap method."""
def setUp(self):
self.j2kfile = glymur.data.goodstuff()
@ -486,7 +515,7 @@ class TestWrap(unittest.TestCase):
pass
def verify_wrapped_raw(self, jp2file):
# Shared method by at least two tests.
"""Shared fixture"""
jp2 = Jp2k(jp2file)
self.assertEqual(len(jp2.box), 4)
@ -536,6 +565,7 @@ class TestWrap(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_wrap(self):
"""basic test for rewrapping a j2c file, no specified boxes"""
j2k = Jp2k(self.j2kfile)
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
j2k.wrap(tfile.name)
@ -543,6 +573,7 @@ class TestWrap(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_wrap_jp2(self):
"""basic test for rewrapping a jp2 file, no specified boxes"""
j2k = Jp2k(self.jp2file)
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
jp2 = j2k.wrap(tfile.name)
@ -550,16 +581,17 @@ class TestWrap(unittest.TestCase):
self.assertEqual(boxes, ['jP ', 'ftyp', 'jp2h', 'jp2c'])
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_default_layout_but_with_specified_boxes(self):
def test_default_layout_with_boxes(self):
"""basic test for rewrapping a jp2 file, boxes specified"""
j2k = Jp2k(self.j2kfile)
boxes = [JPEG2000SignatureBox(),
FileTypeBox(),
JP2HeaderBox(),
ContiguousCodestreamBox()]
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
boxes[2].box = [ImageHeaderBox(height=height,
width=width,
num_components=num_components),
@ -569,17 +601,17 @@ class TestWrap(unittest.TestCase):
self.verify_wrapped_raw(tfile.name)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_image_header_box_not_first_in_jp2_header(self):
# The specification says that ihdr must be the first box in jp2h.
def test_ihdr_not_first_in_jp2h(self):
"""The specification says that ihdr must be the first box in jp2h."""
j2k = Jp2k(self.j2kfile)
boxes = [JPEG2000SignatureBox(),
FileTypeBox(),
JP2HeaderBox(),
ContiguousCodestreamBox()]
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
boxes[2].box = [ColourSpecificationBox(colorspace=glymur.core.SRGB),
ImageHeaderBox(height=height,
width=width,
@ -589,14 +621,15 @@ class TestWrap(unittest.TestCase):
j2k.wrap(tfile.name, boxes=boxes)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_first_2_boxes_not_jP_and_ftyp(self):
def test_first_boxes_jp_and_ftyp(self):
"""first two boxes must be jP followed by ftyp"""
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
jP = JPEG2000SignatureBox()
jp2b = JPEG2000SignatureBox()
ftyp = FileTypeBox()
jp2h = JP2HeaderBox()
jp2c = ContiguousCodestreamBox()
@ -604,20 +637,21 @@ class TestWrap(unittest.TestCase):
ihdr = ImageHeaderBox(height=height, width=width,
num_components=num_components)
jp2h.box = [ihdr, colr]
boxes = [ftyp, jP, jp2h, jp2c]
boxes = [ftyp, jp2b, jp2h, jp2c]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_jp2h_not_preceeding_jp2c(self):
"""jp2h must precede jp2c"""
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
jP = JPEG2000SignatureBox()
jp2b = JPEG2000SignatureBox()
ftyp = FileTypeBox()
jp2h = JP2HeaderBox()
jp2c = ContiguousCodestreamBox()
@ -625,68 +659,74 @@ class TestWrap(unittest.TestCase):
ihdr = ImageHeaderBox(height=height, width=width,
num_components=num_components)
jp2h.box = [ihdr, colr]
boxes = [jP, ftyp, jp2c, jp2h]
boxes = [jp2b, ftyp, jp2c, jp2h]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_missing_codestream(self):
"""Need a codestream box in order to call wrap method."""
j2k = Jp2k(self.j2kfile)
c = j2k.get_codestream()
height = c.segment[1].ysiz
width = c.segment[1].xsiz
num_components = len(c.segment[1].xrsiz)
codestream = j2k.get_codestream()
height = codestream.segment[1].ysiz
width = codestream.segment[1].xsiz
num_components = len(codestream.segment[1].xrsiz)
jP = JPEG2000SignatureBox()
jp2k = JPEG2000SignatureBox()
ftyp = FileTypeBox()
jp2h = JP2HeaderBox()
ihdr = ImageHeaderBox(height=height, width=width,
num_components=num_components)
jp2h.box = [ihdr]
boxes = [jP, ftyp, jp2h]
boxes = [jp2k, ftyp, jp2h]
with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile:
with self.assertRaises(IOError):
j2k.wrap(tfile.name, boxes=boxes)
class TestJp2Boxes(unittest.TestCase):
"""Tests for canonical JP2 boxes."""
def test_default_JPEG2000SignatureBox(self):
# Should be able to instantiate a JPEG2000SignatureBox
b = glymur.jp2box.JPEG2000SignatureBox()
self.assertEqual(b.signature, (13, 10, 135, 10))
def test_default_jp2k(self):
"""Should be able to instantiate a JPEG2000SignatureBox"""
jp2k = glymur.jp2box.JPEG2000SignatureBox()
self.assertEqual(jp2k.signature, (13, 10, 135, 10))
def test_default_FileTypeBox(self):
# Should be able to instantiate a FileTypeBox
b = glymur.jp2box.FileTypeBox()
self.assertEqual(b.brand, 'jp2 ')
self.assertEqual(b.minor_version, 0)
self.assertEqual(b.compatibility_list, ['jp2 '])
def test_default_ftyp(self):
"""Should be able to instantiate a FileTypeBox"""
ftyp = glymur.jp2box.FileTypeBox()
self.assertEqual(ftyp.brand, 'jp2 ')
self.assertEqual(ftyp.minor_version, 0)
self.assertEqual(ftyp.compatibility_list, ['jp2 '])
def test_default_ImageHeaderBox(self):
# Should be able to instantiate an image header box.
b = glymur.jp2box.ImageHeaderBox(height=512, width=256,
def test_default_ihdr(self):
"""Should be able to instantiate an image header box."""
ihdr = glymur.jp2box.ImageHeaderBox(height=512, width=256,
num_components=3)
self.assertEqual(b.height, 512)
self.assertEqual(b.width, 256)
self.assertEqual(b.num_components, 3)
self.assertEqual(b.bits_per_component, 8)
self.assertFalse(b.signed)
self.assertFalse(b.colorspace_unknown)
self.assertEqual(ihdr.height, 512)
self.assertEqual(ihdr.width, 256)
self.assertEqual(ihdr.num_components, 3)
self.assertEqual(ihdr.bits_per_component, 8)
self.assertFalse(ihdr.signed)
self.assertFalse(ihdr.colorspace_unknown)
def test_default_JP2HeaderBox(self):
b1 = JP2HeaderBox()
b1.box = [ImageHeaderBox(height=512, width=256),
def test_default_jp2headerbox(self):
"""Should be able to set jp2h boxes."""
box = JP2HeaderBox()
box.box = [ImageHeaderBox(height=512, width=256),
ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)]
self.assertTrue(True)
def test_default_ContiguousCodestreamBox(self):
b = ContiguousCodestreamBox()
self.assertEqual(b.box_id, 'jp2c')
self.assertIsNone(b.main_header)
def test_default_ccodestreambox(self):
"""Raw instantiation should not produce a main_header."""
box = ContiguousCodestreamBox()
self.assertEqual(box.box_id, 'jp2c')
self.assertIsNone(box.main_header)
class TestJpxBoxes(unittest.TestCase):
"""Tests for JPX boxes."""
def setUp(self):
pass
@ -694,11 +734,11 @@ class TestJpxBoxes(unittest.TestCase):
def tearDown(self):
pass
@unittest.skipIf(format_corpus_data_root is None,
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
def test_codestream_header(self):
# Should recognize codestream header box.
jfile = os.path.join(format_corpus_data_root,
"""Should recognize codestream header box."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-formats/balloon.jpf')
jpx = Jp2k(jfile)
@ -706,11 +746,11 @@ class TestJpxBoxes(unittest.TestCase):
self.assertEqual(jpx.box[4].box_id, 'jpch')
self.assertEqual(len(jpx.box[4].box), 0)
@unittest.skipIf(format_corpus_data_root is None,
@unittest.skipIf(FORMAT_CORPUS_DATA_ROOT is None,
"FORMAT_CORPUS_DATA_ROOT environment variable not set")
def test_compositing_layer_header(self):
# Should recognize compositing layer header box.
jfile = os.path.join(format_corpus_data_root,
"""Should recognize compositing layer header box."""
jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT,
'jp2k-formats/balloon.jpf')
jpx = Jp2k(jfile)

View file

@ -1,4 +1,15 @@
# pylint: disable-all
"""
Tests for general glymur functionality.
"""
# E1101: assertWarns introduced in python 3.2
# pylint: disable=E1101
# R0904: Not too many methods in unittest.
# pylint: disable=R0904
# E0611: unittest.mock is unknown to python2.7/pylint
# pylint: disable=E0611,F0401
import doctest
import os
import re
@ -25,20 +36,24 @@ import pkg_resources
import glymur
from glymur import Jp2k
from glymur.lib import openjp2 as opj2
from .fixtures import OPENJP2_IS_V2_OFFICIAL
try:
data_root = os.environ['OPJ_DATA_ROOT']
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
DATA_ROOT = None
except:
raise
# Doc tests should be run as well.
def load_tests(loader, tests, ignore):
# W0613: "loader" and "ignore" are necessary for the protocol
# They are unused here, however.
# pylint: disable=W0613
"""Should run doc tests as well"""
if os.name == "nt":
# Can't do it on windows, temporary file issue.
return tests
@ -54,6 +69,7 @@ def load_tests(loader, tests, ignore):
glymur.lib.openjpeg.OPENJPEG is None,
"Missing openjp2 library.")
class TestConfig(unittest.TestCase):
"""Test suite for reading without proper library in place."""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -62,24 +78,24 @@ class TestConfig(unittest.TestCase):
def tearDown(self):
pass
def test_read_without_library_backing_us_up(self):
def test_read_without_library(self):
"""Don't have either openjp2 or openjpeg libraries? Must error out.
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
d = glymur.Jp2k(self.jp2file).read()
glymur.Jp2k(self.jp2file).read()
def test_read_bands_without_library_backing_us_up(self):
def test_read_bands_without_library(self):
"""Don't have openjp2 library? Must error out.
"""
with patch('glymur.lib.openjp2.OPENJP2', new=None):
with patch('glymur.lib.openjpeg.OPENJPEG', new=None):
with self.assertRaises(glymur.jp2k.LibraryNotFoundError):
d = glymur.Jp2k(self.jp2file).read_bands()
glymur.Jp2k(self.jp2file).read_bands()
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_without_library_backing_us_up(self):
def test_write_without_library(self):
"""Don't have openjp2 library? Must error out.
"""
data = glymur.Jp2k(self.j2kfile).read()
@ -95,32 +111,34 @@ class TestConfig(unittest.TestCase):
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
class TestJp2kBadXmlFile(unittest.TestCase):
"""Test suite for bad XML box situations"""
@classmethod
def setUpClass(cls):
# Setup a JP2 file with a bad XML box. We only need to do this once
# per class rather than once per test.
"""Setup a JP2 file with a bad XML box. We only need to do this once
per class rather than once per test.
"""
jp2file = pkg_resources.resource_filename(glymur.__name__,
"data/nemo.jp2")
with tempfile.NamedTemporaryFile(suffix='.jp2', delete=False) as tfile:
cls._bad_xml_file = tfile.name
with open(jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
tfile.write(buffer)
write_buffer = ifile.read(77)
tfile.write(write_buffer)
# Write the xml box with bad xml
# Length = 28, id is 'xml '.
buffer = struct.pack('>I4s', int(28), b'xml ')
tfile.write(buffer)
write_buffer = struct.pack('>I4s', int(28), b'xml ')
tfile.write(write_buffer)
buffer = '<test>this is a test'
buffer = buffer.encode()
tfile.write(buffer)
write_buffer = '<test>this is a test'
write_buffer = write_buffer.encode()
tfile.write(write_buffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
write_buffer = ifile.read()
tfile.write(write_buffer)
tfile.flush()
@classmethod
@ -137,13 +155,12 @@ class TestJp2kBadXmlFile(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_invalid_xml_box_warning(self):
# Should be able to recover from xml box with bad xml.
# Just verify that a warning is issued on 3.3+
with self.assertWarns(UserWarning) as cw:
jp2k = Jp2k(self._bad_xml_file)
"""Should warn in case of bad XML"""
with self.assertWarns(UserWarning):
Jp2k(self._bad_xml_file)
def test_invalid_xml_box(self):
# Should be able to recover from xml box with bad xml.
"""Should be able to recover info from xml box with bad xml."""
with warnings.catch_warnings():
warnings.simplefilter("ignore")
jp2k = Jp2k(self._bad_xml_file)
@ -157,6 +174,7 @@ class TestJp2kBadXmlFile(unittest.TestCase):
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
class TestJp2k(unittest.TestCase):
"""Test suite for version 2.0/2.0+ of openjpeg"""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -166,7 +184,7 @@ class TestJp2k(unittest.TestCase):
pass
def test_rlevel_max(self):
# Verify that rlevel=-1 gets us the lowest resolution image
"""Verify that rlevel=-1 gets us the lowest resolution image"""
j = Jp2k(self.j2kfile)
thumbnail1 = j.read(rlevel=-1)
thumbnail2 = j.read(rlevel=5)
@ -174,43 +192,52 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(thumbnail1.shape, (25, 15, 3))
def test_bad_area_parameter(self):
# Verify that we error out appropriately if given a bad area parameter.
"""Should error out appropriately if given a bad area parameter."""
j = Jp2k(self.jp2file)
with self.assertRaises(IOError):
# Start corner must be >= 0
d = j.read(area=(-1, -1, 1, 1))
j.read(area=(-1, -1, 1, 1))
with self.assertRaises(IOError):
# End corner must be > 0
d = j.read(area=(10, 10, 0, 0))
j.read(area=(10, 10, 0, 0))
with self.assertRaises(IOError):
# End corner must be >= start corner
d = j.read(area=(10, 10, 8, 8))
j.read(area=(10, 10, 8, 8))
def test_rlevel_too_high(self):
# Verify that we error out appropriately if not given a JPEG 2000 file.
"""Should error out appropriately if reduce level too high"""
j = Jp2k(self.jp2file)
with self.assertRaises(IOError):
d = j.read(rlevel=6)
j.read(rlevel=6)
def test_not_JPEG2000(self):
# Verify that we error out appropriately if not given a JPEG 2000 file.
def test_not_jpeg2000(self):
"""Should error out appropriately if not given a JPEG 2000 file."""
filename = pkg_resources.resource_filename(glymur.__name__, "jp2k.py")
with self.assertRaises(IOError):
jp2k = Jp2k(filename)
Jp2k(filename)
def test_file_not_present(self):
"""Should error out if reading from a file that does not exist"""
# Verify that we error out appropriately if not given an existing file
# at all.
if sys.hexversion < 0x03030000:
error = OSError
else:
error = IOError
with self.assertRaises(error):
with self.assertRaises(OSError):
filename = 'this file does not actually exist on the file system.'
jp2k = Jp2k(filename)
Jp2k(filename)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_with_jp2_in_caps(self):
"""should be able to write with JP2 suffix."""
j2k = Jp2k(self.j2kfile)
expdata = j2k.read()
with tempfile.NamedTemporaryFile(suffix='.JP2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
ofile.write(expdata)
actdata = ofile.read()
np.testing.assert_array_equal(actdata, expdata)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_srgb_without_mct(self):
"""should be able to write RGB without specifying mct"""
j2k = Jp2k(self.j2kfile)
expdata = j2k.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
@ -219,12 +246,12 @@ class TestJp2k(unittest.TestCase):
actdata = ofile.read()
np.testing.assert_array_equal(actdata, expdata)
c = ofile.get_codestream()
self.assertEqual(c.segment[2].spcod[3], 0) # no mct
codestream = ofile.get_codestream()
self.assertEqual(codestream.segment[2].spcod[3], 0) # no mct
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_grayscale_with_mct(self):
# MCT usage makes no sense for grayscale images.
"""MCT usage makes no sense for grayscale images."""
j2k = Jp2k(self.j2kfile)
expdata = j2k.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
@ -234,6 +261,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_write_cprl(self):
"""Must be able to write a CPRL progression order file"""
# Issue 17
j = Jp2k(self.jp2file)
expdata = j.read(rlevel=1)
@ -243,11 +271,11 @@ class TestJp2k(unittest.TestCase):
actdata = ofile.read()
np.testing.assert_array_equal(actdata, expdata)
c = ofile.get_codestream()
self.assertEqual(c.segment[2].spcod[0], glymur.core.CPRL)
codestream = ofile.get_codestream()
self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL)
def test_jp2_boxes(self):
# Verify the boxes of a JP2 file.
"""Verify the boxes of a JP2 file. Basic jp2 test."""
jp2k = Jp2k(self.jp2file)
# top-level boxes
@ -305,39 +333,41 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(jp2k.box[2].box[1].colorspace, glymur.core.SRGB)
self.assertIsNone(jp2k.box[2].box[1].icc_profile)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_j2k_box(self):
"""A J2K/J2C file must not have any boxes."""
# Verify that a J2K file has no boxes.
filename = os.path.join(data_root, 'input/conformance/p0_01.j2k')
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_01.j2k')
jp2k = Jp2k(filename)
self.assertEqual(len(jp2k.box), 0)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_64bit_XL_field(self):
def test_64bit_xl_field(self):
"""XL field should be supported"""
# Verify that boxes with the XL field are properly read.
# Don't have such a file on hand, so we create one. Copy our example
# file, but making the codestream have a 64-bit XL field.
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(3127)
tfile.write(buffer)
write_buffer = ifile.read(3127)
tfile.write(write_buffer)
# The L field must be 1 in order to signal the presence of the
# XL field. The actual length of the jp2c box increased by 8
# (8 bytes for the XL field).
L = 1
T = b'jp2c'
XL = 1133427 + 8
buffer = struct.pack('>I4sQ', int(L), T, XL)
tfile.write(buffer)
length = 1
typ = b'jp2c'
xlen = 1133427 + 8
write_buffer = struct.pack('>I4sQ', int(length), typ, xlen)
tfile.write(write_buffer)
# Get the rest of the input file (minus the 8 bytes for L and
# T.
ifile.seek(8, 1)
buffer = ifile.read()
tfile.write(buffer)
write_buffer = ifile.read()
tfile.write(write_buffer)
tfile.flush()
jp2k = Jp2k(tfile.name)
@ -347,7 +377,8 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(jp2k.box[5].length, 1133427 + 8)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_L_is_zero(self):
def test_length_field_is_zero(self):
"""L=0 (length field in box header) is allowed"""
# Verify that boxes with the L field as zero are correctly read.
# This should only happen in the last box of a JPEG 2000 file.
# Our example image has its last box at byte 588458.
@ -355,19 +386,19 @@ class TestJp2k(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(588458)
tfile.write(buffer)
write_buffer = ifile.read(588458)
tfile.write(write_buffer)
L = 0
T = b'uuid'
buffer = struct.pack('>I4s', int(L), T)
tfile.write(buffer)
length = 0
typ = b'uuid'
write_buffer = struct.pack('>I4s', int(length), typ)
tfile.write(write_buffer)
# Get the rest of the input file (minus the 8 bytes for L and
# T.
ifile.seek(8, 1)
buffer = ifile.read()
tfile.write(buffer)
write_buffer = ifile.read()
tfile.write(write_buffer)
tfile.flush()
new_jp2 = Jp2k(tfile.name)
@ -381,31 +412,34 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(new_jp2.box[j].length,
baseline_jp2.box[j].length)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_read_differing_subsamples(self):
"""should error out with read used on differently subsampled images"""
# Verify that we error out appropriately if we use the read method
# on an image with differing subsamples
#
# Issue 86.
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k')
j = Jp2k(filename)
with self.assertRaises(RuntimeError):
j.read()
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_empty_box_with_j2k(self):
# Verify that the list of boxes in a J2C/J2K file is present, but
# empty.
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
"""Verify that the list of boxes in a J2C/J2K file is present, but
empty.
"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k')
j = Jp2k(filename)
self.assertEqual(j.box, [])
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_code_block_height_different_than_width(self):
# Verify that we can set a code block size where height does not equal
# width.
def test_cblkh_different_than_width(self):
"""Verify that we can set a code block size where height does not equal
width.
"""
data = np.zeros((128, 128), dtype=np.uint8)
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
@ -413,49 +447,50 @@ class TestJp2k(unittest.TestCase):
# The code block dimensions are given as rows x columns.
j.write(data, cbsize=(16, 32))
c = j.get_codestream()
codestream = j.get_codestream()
# Code block size is reported as XY in the codestream.
self.assertEqual(tuple(c.segment[2].spcod[5:7]), (3, 2))
self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2))
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_negative_too_many_dimensions(self):
# OpenJP2 only allows 2D or 3D images.
def test_too_many_dimensions(self):
"""OpenJP2 only allows 2D or 3D images."""
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
data = np.zeros((128, 128, 2, 2), dtype=np.uint8)
j.write(data)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_unrecognized_jp2_colorspace(self):
# We only allow RGB and GRAYSCALE.
def test_unrecognized_jp2_clrspace(self):
"""We only allow RGB and GRAYSCALE. Should error out with others"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
data = np.zeros((128, 128, 3), dtype=np.uint8)
j.write(data, colorspace='cmyk')
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_2D_rgb(self):
# RGB must have at least 3 components.
def test_2d_rgb(self):
"""RGB must have at least 3 components."""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
data = np.zeros((128, 128, 2), dtype=np.uint8)
j.write(data, colorspace='rgb')
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_colorspace_with_j2k(self):
# Specifying a colorspace with J2K does not make sense.
"""Specifying a colorspace with J2K does not make sense"""
with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
data = np.zeros((128, 128, 3), dtype=np.uint8)
j.write(data, colorspace='rgb')
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_specify_rgb(self):
"""specify RGB explicitly"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128, 3), dtype=np.uint8)
@ -464,6 +499,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_specify_gray(self):
"""test gray explicitly specified (that's GRAY, not GREY)"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128), dtype=np.uint8)
@ -473,6 +509,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_specify_grey(self):
"""test grey explicitly specified"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128), dtype=np.uint8)
@ -484,6 +521,7 @@ class TestJp2k(unittest.TestCase):
"Does not seem to work on official v2.0.0 release.")
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_grey_with_extra_component(self):
"""version 2.0 cannot write gray + extra"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128, 2), dtype=np.uint8)
@ -495,7 +533,8 @@ class TestJp2k(unittest.TestCase):
glymur.core.GREYSCALE)
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_grey_with_two_extra_components(self):
def test_grey_with_two_extra_comps(self):
"""should be able to write gray + two extra components"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128, 3), dtype=np.uint8)
@ -510,6 +549,7 @@ class TestJp2k(unittest.TestCase):
"Does not seem to work on official v2.0.0 release.")
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_rgb_with_extra_component(self):
"""v2.0+ should be able to write extra components"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
data = np.zeros((128, 128, 4), dtype=np.uint8)
@ -522,7 +562,8 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL is False,
"Test is specific for v2.0.0 release")
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_extra_components_on_v2_official(self):
def test_extra_components_on_v2(self):
"""must error out in 1.x with extra components."""
# Extra components seems to require 2.0+. Verify that we error out.
with self.assertRaises(IOError):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
@ -531,48 +572,50 @@ class TestJp2k(unittest.TestCase):
j.write(data)
def test_specify_ycc(self):
# We don't support writing YCC at the moment.
"""Should reject YCC"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
j = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
data = np.zeros((128, 128, 3), dtype=np.uint8)
j.write(data, colorspace='ycc')
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_uinf_ulst_url_boxes(self):
"""Verify that we can read UINF, ULST, and URL boxes"""
# Verify that we can read UINF, ULST, and URL boxes. I don't have
# easy access to such a file, and there's no such file in the
# openjpeg repository, so I'll fake one.
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
tfile.write(buffer)
write_buffer = ifile.read(77)
tfile.write(write_buffer)
# Write the UINF superbox
# Length = 50, id is uinf.
buffer = struct.pack('>I4s', int(50), b'uinf')
tfile.write(buffer)
write_buffer = struct.pack('>I4s', int(50), b'uinf')
tfile.write(write_buffer)
# Write the ULST box.
# Length is 26, 1 UUID, hard code that UUID as zeros.
buffer = struct.pack('>I4sHIIII', int(26), b'ulst', int(1),
int(0), int(0), int(0), int(0))
tfile.write(buffer)
write_buffer = struct.pack('>I4sHIIII', int(26), b'ulst',
int(1), int(0), int(0), int(0),
int(0))
tfile.write(write_buffer)
# Write the URL box.
# Length is 16, version is one byte, flag is 3 bytes, url
# is the rest.
buffer = struct.pack('>I4sBBBB',
int(16), b'url ',
int(0), int(0), int(0), int(0))
tfile.write(buffer)
buffer = struct.pack('>ssss', b'a', b'b', b'c', b'd')
tfile.write(buffer)
write_buffer = struct.pack('>I4sBBBB',
int(16), b'url ',
int(0), int(0), int(0), int(0))
tfile.write(write_buffer)
write_buffer = struct.pack('>ssss', b'a', b'b', b'c', b'd')
tfile.write(write_buffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
write_buffer = ifile.read()
tfile.write(write_buffer)
tfile.flush()
jp2k = Jp2k(tfile.name)
@ -596,27 +639,26 @@ class TestJp2k(unittest.TestCase):
self.assertEqual(jp2k.box[3].box[1].url, 'abcd')
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_xml_box_with_trailing_nulls(self):
# ElementTree does not like trailing null chars after valid XML
# text.
def test_xml_with_trailing_nulls(self):
"""ElementTree doesn't like trailing null chars after valid XML text"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
tfile.write(buffer)
write_buffer = ifile.read(77)
tfile.write(write_buffer)
# Write the xml box
# Length = 36, id is 'xml '.
buffer = struct.pack('>I4s', int(36), b'xml ')
tfile.write(buffer)
write_buffer = struct.pack('>I4s', int(36), b'xml ')
tfile.write(write_buffer)
buffer = '<test>this is a test</test>' + chr(0)
buffer = buffer.encode()
tfile.write(buffer)
write_buffer = '<test>this is a test</test>' + chr(0)
write_buffer = write_buffer.encode()
tfile.write(write_buffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
write_buffer = ifile.read()
tfile.write(write_buffer)
tfile.flush()
jp2k = Jp2k(tfile.name)
@ -629,6 +671,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_asoc_label_box(self):
"""Test asoc and label box"""
# Construct a fake file with an asoc and a label box, as
# OpenJPEG doesn't have such a file.
data = Jp2k(self.jp2file).read(rlevel=1)
@ -639,30 +682,30 @@ class TestJp2k(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
# Offset of the codestream is where we start.
buffer = tfile.read(77)
tfile2.write(buffer)
read_buffer = tfile.read(77)
tfile2.write(read_buffer)
# read the rest of the file, it's the codestream.
codestream = tfile.read()
# Write the asoc superbox.
# Length = 36, id is 'asoc'.
buffer = struct.pack('>I4s', int(56), b'asoc')
tfile2.write(buffer)
write_buffer = struct.pack('>I4s', int(56), b'asoc')
tfile2.write(write_buffer)
# Write the contained label box
buffer = struct.pack('>I4s', int(13), b'lbl ')
tfile2.write(buffer)
write_buffer = struct.pack('>I4s', int(13), b'lbl ')
tfile2.write(write_buffer)
tfile2.write('label'.encode())
# Write the xml box
# Length = 36, id is 'xml '.
buffer = struct.pack('>I4s', int(35), b'xml ')
tfile2.write(buffer)
write_buffer = struct.pack('>I4s', int(35), b'xml ')
tfile2.write(write_buffer)
buffer = '<test>this is a test</test>'
buffer = buffer.encode()
tfile2.write(buffer)
write_buffer = '<test>this is a test</test>'
write_buffer = write_buffer.encode()
tfile2.write(write_buffer)
# Now append the codestream.
tfile2.write(codestream)
@ -678,10 +721,10 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL,
"Segfault on official v2.0.0 release.")
def test_openjpeg_library_message(self):
# Verify the error message produced by the openjpeg library.
"""Verify the error message produced by the openjpeg library"""
# This will confirm that the error callback mechanism is working.
with open(self.jp2file, 'rb') as fp:
data = fp.read()
with open(self.jp2file, 'rb') as fptr:
data = fptr.read()
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
# Codestream starts at byte 3127. SIZ marker at 3137.
# COD marker at 3186. Subsampling at 3180.
@ -705,13 +748,13 @@ class TestJp2k(unittest.TestCase):
:\sdx=1\sdy=0''', re.VERBOSE)
if sys.hexversion < 0x03020000:
with self.assertRaisesRegexp((IOError, OSError), regexp):
d = j.read(rlevel=1)
j.read(rlevel=1)
else:
with self.assertRaisesRegex((IOError, OSError), regexp):
d = j.read(rlevel=1)
j.read(rlevel=1)
def test_xmp_attribute(self):
# Verify that we can read the XMP packet in our shipping example file.
"""Verify the XMP packet in the shipping example file can be read."""
j = Jp2k(self.jp2file)
xmp = j.box[4].data
ns0 = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
@ -723,7 +766,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
def test_unrecognized_exif_tag(self):
# An unrecognized exif tag should be handled gracefully.
"""An unrecognized exif tag should be handled gracefully."""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
shutil.copyfile(self.jp2file, tfile.name)
@ -733,10 +776,10 @@ class TestJp2k(unittest.TestCase):
# the the Image IFD number of tags, where we finally find the first
# tag, "Make" (271). We'll corrupt it by changing it into 171,
# which does not correspond to any known Exif Image tag.
with open(tfile.name, 'r+b') as fp:
fp.seek(117)
buffer = struct.pack('<H', int(171))
fp.write(buffer)
with open(tfile.name, 'r+b') as fptr:
fptr.seek(117)
write_buffer = struct.pack('<H', int(171))
fptr.write(write_buffer)
# Verify that a warning is issued, but only on python3.
# On python2, just suppress the warning.
@ -745,7 +788,7 @@ class TestJp2k(unittest.TestCase):
warnings.simplefilter("ignore")
j = Jp2k(tfile.name)
else:
with self.assertWarns(UserWarning) as cw:
with self.assertWarns(UserWarning):
j = Jp2k(tfile.name)
exif = j.box[3].data
@ -757,6 +800,7 @@ class TestJp2k(unittest.TestCase):
@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None,
"Missing openjpeg library.")
class TestJp2k15(unittest.TestCase):
"""Test suite for openjpeg 1.5"""
@classmethod
def setUpClass(cls):

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,15 @@
The tests here do not correspond directly to the OpenJPEG test suite, but
seem like logical negative tests to add.
"""
#pylint: disable-all
# E1101: assertWarns introduced in python 3.2
# pylint: disable=E1101
# R0904: Not too many methods in unittest.
# pylint: disable=R0904
# unittest2 is python2.6 only (pylint/python-2.7)
# pylint: disable=F0401
import os
import sys
import tempfile
@ -13,9 +21,6 @@ else:
import unittest
import numpy as np
import pkg_resources
from glymur.lib import openjp2 as opj2
from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG
@ -23,9 +28,9 @@ from glymur import Jp2k
import glymur
try:
data_root = os.environ['OPJ_DATA_ROOT']
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
DATA_ROOT = None
except:
raise
@ -33,9 +38,10 @@ except:
@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None,
"Missing openjp2 library.")
@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
class TestSuiteNegative(unittest.TestCase):
"""Test suite for certain negative tests from openjpeg suite."""
def setUp(self):
self.jp2file = glymur.data.nemo()
@ -45,45 +51,50 @@ class TestSuiteNegative(unittest.TestCase):
pass
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_negative_psnr_with_cratios(self):
# Using psnr with cratios options is not allowed.
def test_psnr_with_cratios(self):
"""Using psnr with cratios options is not allowed."""
# Not an OpenJPEG test, but close.
infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm')
infile = os.path.join(DATA_ROOT, '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])
def test_NR_MarkerIsNotCompliant_j2k_dump(self):
def test_nr_marker_not_compliant(self):
"""non-compliant marker, should still be able to read"""
relpath = 'input/nonregression/MarkerIsNotCompliant.j2k'
jfile = os.path.join(data_root, relpath)
jfile = os.path.join(DATA_ROOT, relpath)
jp2k = Jp2k(jfile)
c = jp2k.get_codestream(header_only=False)
jp2k.get_codestream(header_only=False)
self.assertTrue(True)
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_NR_illegalcolortransform_dump(self):
# EOC marker is bad
def test_nr_illegalclrtransform(self):
"""EOC marker is bad"""
relpath = 'input/nonregression/illegalcolortransform.j2k'
jfile = os.path.join(data_root, relpath)
jfile = os.path.join(DATA_ROOT, relpath)
jp2k = Jp2k(jfile)
with self.assertWarns(UserWarning) as cw:
c = jp2k.get_codestream(header_only=False)
with self.assertWarns(UserWarning):
codestream = jp2k.get_codestream(header_only=False)
# Verify that the last segment returned in the codestream is SOD,
# not EOC. Codestream parsing should stop when we try to jump to
# the end of SOT.
self.assertEqual(c.segment[-1].marker_id, 'SOD')
self.assertEqual(codestream.segment[-1].marker_id, 'SOD')
def test_NR_Cannotreaddatawithnosizeknown_j2k(self):
def test_nr_cannotreadwnosizeknown(self):
"""not sure exactly what is wrong with this file"""
relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k'
jfile = os.path.join(data_root, relpath)
jfile = os.path.join(DATA_ROOT, relpath)
jp2k = Jp2k(jfile)
c = jp2k.get_codestream(header_only=False)
jp2k.get_codestream(header_only=False)
self.assertTrue(True)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_code_block_dimensions(self):
"""don't allow extreme codeblock sizes"""
# opj_compress doesn't allow the dimensions of a codeblock
# to be too small or too big, so neither will we.
data = np.zeros((256, 256), dtype=np.uint8)
@ -91,55 +102,55 @@ class TestSuiteNegative(unittest.TestCase):
j = Jp2k(tfile.name, 'wb')
# opj_compress doesn't allow code block area to exceed 4096.
with self.assertRaises(IOError) as cr:
with self.assertRaises(IOError):
j.write(data, cbsize=(256, 256))
# opj_compress doesn't allow either dimension to be less than 4.
with self.assertRaises(IOError) as cr:
with self.assertRaises(IOError):
j.write(data, cbsize=(2048, 2))
with self.assertRaises(IOError) as cr:
with self.assertRaises(IOError):
j.write(data, cbsize=(2, 2048))
@unittest.skipIf(sys.hexversion < 0x03020000,
"Uses features introduced in 3.2.")
def test_exceeded_box(self):
"""should warn if reading past end of a box"""
# Verify that a warning is issued if we read past the end of a box
# This file has a palette (pclr) box whose length is impossibly
# short.
infile = os.path.join(data_root,
infile = os.path.join(DATA_ROOT,
'input/nonregression/mem-b2ace68c-1381.jp2')
with self.assertWarns(UserWarning) as cw:
j = Jp2k(infile)
with self.assertWarns(UserWarning):
Jp2k(infile)
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_precinct_size_not_multiple_of_two(self):
# Seems like precinct sizes should be powers of two.
def test_precinct_size_not_p2(self):
"""precinct sizes should be powers of two."""
ifile = Jp2k(self.j2kfile)
data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
ofile.write(data, psizes=[(13, 13)])
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_codeblock_size_not_multiple_of_two(self):
# Seems like code block sizes should be powers of two.
def test_cblk_size_not_power_of_two(self):
"""code block sizes should be powers of two."""
ifile = Jp2k(self.j2kfile)
data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
ofile.write(data, cbsize=(13, 12))
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_codeblock_size_with_precinct_size(self):
# Seems like code block sizes should never exceed half that of
# precinct size.
def test_cblk_size_precinct_size(self):
"""code block sizes should never exceed half that of precinct size."""
ifile = Jp2k(self.j2kfile)
data = ifile.read(rlevel=2)
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
ofile = Jp2k(tfile.name, 'wb')
with self.assertRaises(IOError) as ce:
with self.assertRaises(IOError):
ofile.write(data,
cbsize=(64, 64),
psizes=[(64, 64)])

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,15 @@
#pylint: disable-all
"""Test suite for printing.
"""
# C0302: don't care too much about having too many lines in a test module
# pylint: disable=C0302
# E061: unittest.mock introduced in 3.3 (python-2.7/pylint issue)
# pylint: disable=E0611,F0401
# R0904: Not too many methods in unittest.
# pylint: disable=R0904
import os
import pkg_resources
import re
import struct
import sys
import tempfile
@ -26,9 +34,9 @@ import glymur
from glymur import Jp2k
try:
data_root = os.environ['OPJ_DATA_ROOT']
DATA_ROOT = os.environ['OPJ_DATA_ROOT']
except KeyError:
data_root = None
DATA_ROOT = None
except:
raise
@ -122,12 +130,13 @@ class TestPrintingNeedsLib(unittest.TestCase):
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
+ '(0, 10), (0, 9), (0, 9), (0, 10), (0, 9), (0, 9), '
+ '(0, 10)]']
self.expectedPlain = '\n'.join(lines)
self.expected_plain = '\n'.join(lines)
def tearDown(self):
pass
def test_asoc_label_box(self):
"""verify printing of asoc, label boxes"""
# Construct a fake file with an asoc and a label box, as
# OpenJPEG doesn't have such a file.
data = glymur.Jp2k(self.jp2file).read(rlevel=1)
@ -138,30 +147,30 @@ class TestPrintingNeedsLib(unittest.TestCase):
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2:
# Offset of the codestream is where we start.
buffer = tfile.read(77)
tfile2.write(buffer)
wbuffer = tfile.read(77)
tfile2.write(wbuffer)
# read the rest of the file, it's the codestream.
codestream = tfile.read()
# Write the asoc superbox.
# Length = 36, id is 'asoc'.
buffer = struct.pack('>I4s', int(56), b'asoc')
tfile2.write(buffer)
wbuffer = struct.pack('>I4s', int(56), b'asoc')
tfile2.write(wbuffer)
# Write the contained label box
buffer = struct.pack('>I4s', int(13), b'lbl ')
tfile2.write(buffer)
wbuffer = struct.pack('>I4s', int(13), b'lbl ')
tfile2.write(wbuffer)
tfile2.write('label'.encode())
# Write the xml box
# Length = 36, id is 'xml '.
buffer = struct.pack('>I4s', int(35), b'xml ')
tfile2.write(buffer)
wbuffer = struct.pack('>I4s', int(35), b'xml ')
tfile2.write(wbuffer)
buffer = '<test>this is a test</test>'
buffer = buffer.encode()
tfile2.write(buffer)
wbuffer = '<test>this is a test</test>'
wbuffer = wbuffer.encode()
tfile2.write(wbuffer)
# Now append the codestream.
tfile2.write(codestream)
@ -180,6 +189,7 @@ class TestPrintingNeedsLib(unittest.TestCase):
self.assertEqual(actual, expected)
def test_jp2dump(self):
"""basic jp2dump test"""
with patch('sys.stdout', new=StringIO()) as fake_out:
glymur.jp2dump(self._plain_nemo_file)
actual = fake_out.getvalue().strip()
@ -188,9 +198,10 @@ class TestPrintingNeedsLib(unittest.TestCase):
lst = actual.split('\n')
lst = lst[1:]
actual = '\n'.join(lst)
self.assertEqual(actual, self.expectedPlain)
self.assertEqual(actual, self.expected_plain)
def test_entire_file(self):
"""verify output from printing entire file"""
j = glymur.Jp2k(self._plain_nemo_file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j)
@ -201,10 +212,11 @@ class TestPrintingNeedsLib(unittest.TestCase):
lst = lst[1:]
actual = '\n'.join(lst)
self.assertEqual(actual, self.expectedPlain)
self.assertEqual(actual, self.expected_plain)
class TestPrinting(unittest.TestCase):
"""Test suite for printing where the libraries are not needed"""
def setUp(self):
# Save sys.stdout.
@ -213,7 +225,8 @@ class TestPrinting(unittest.TestCase):
def tearDown(self):
pass
def test_COC_segment(self):
def test_coc_segment(self):
"""verify printing of COC segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -240,7 +253,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_COD_segment(self):
def test_cod_segment(self):
"""verify printing of COD segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -271,14 +285,13 @@ class TestPrinting(unittest.TestCase):
' Segmentation symbols: False']
expected = '\n'.join(lines)
self.actual = actual
self.expected = expected
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_icc_profile(self):
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
"""verify printing of colr box with ICC profile"""
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2')
with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
@ -343,24 +356,26 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_CRG(self):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
def test_crg(self):
"""verify printing of CRG segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[-5])
actual = fake_out.getvalue().strip()
lines = ['CRG marker segment at (87, 6)',
lines = ['CRG marker segment @ (87, 6)',
' Vertical, Horizontal offset: (0.50, 1.00)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_RGN(self):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
def test_rgn(self):
"""verify printing of RGN segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -373,10 +388,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_SOP(self):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
def test_sop(self):
"""verify printing of SOP segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -387,11 +403,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_CME(self):
# Test printing a CME or comment marker segment.
filename = os.path.join(data_root, 'input/conformance/p0_02.j2k')
def test_cme(self):
"""Test printing a CME or comment marker segment."""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_02.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
# 2nd to last segment in the main header
@ -403,7 +419,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_EOC_segment(self):
def test_eoc_segment(self):
"""verify printing of eoc segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -414,10 +431,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_PLT_segment(self):
filename = os.path.join(data_root, 'input/conformance/p0_07.j2k')
def test_plt_segment(self):
"""verify printing of PLT segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_07.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -432,10 +450,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_POD_segment(self):
filename = os.path.join(data_root, 'input/conformance/p0_13.j2k')
def test_pod_segment(self):
"""verify printing of POD segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_13.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -461,10 +480,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_PPM_segment(self):
filename = os.path.join(data_root, 'input/conformance/p1_03.j2k')
def test_ppm_segment(self):
"""verify printing of PPM segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p1_03.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -478,10 +498,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_PPT_segment(self):
filename = os.path.join(data_root, 'input/conformance/p1_06.j2k')
def test_ppt_segment(self):
"""verify printing of ppt segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p1_06.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -495,7 +516,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_QCC_segment(self):
def test_qcc_segment(self):
"""verify printing of qcc segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -510,7 +532,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_QCD_segment_5x3_transform(self):
def test_qcd_segment_5x3_transform(self):
"""verify printing of qcd segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -524,7 +547,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_SIZ_segment(self):
def test_siz_segment(self):
"""verify printing of SIZ segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -545,7 +569,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_SOC_segment(self):
def test_soc_segment(self):
"""verify printing of SOC segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -556,7 +581,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_SOD_segment(self):
def test_sod_segment(self):
"""verify printing of SOD segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -567,7 +593,8 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
def test_SOT_segment(self):
def test_sot_segment(self):
"""verify printing of SOT segment"""
j = glymur.Jp2k(self.jp2file)
codestream = j.get_codestream(header_only=False)
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -581,13 +608,13 @@ class TestPrinting(unittest.TestCase):
' Number of tile parts: 1']
expected = '\n'.join(lines)
self.maxDiff = None
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_TLM_segment(self):
filename = os.path.join(data_root, 'input/conformance/p0_15.j2k')
def test_tlm_segment(self):
"""verify printing of TLM segment"""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_15.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -605,7 +632,7 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x02070000,
"Differences in XML printing between 2.6 and 2.7")
def test_xmp(self):
# Verify the printing of a UUID/XMP box.
"""Verify the printing of a UUID/XMP box."""
j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[4])
@ -627,6 +654,7 @@ class TestPrinting(unittest.TestCase):
self.assertEqual(actual, expected)
def test_codestream(self):
"""verify printing of entire codestream"""
j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.get_codestream())
@ -672,15 +700,15 @@ class TestPrinting(unittest.TestCase):
' CME marker segment @ (3209, 37)',
' "Created by OpenJPEG version 2.0.0"']
expected = '\n'.join(lst)
self.maxDiff = None
self.assertEqual(actual, expected)
@unittest.skipIf(sys.hexversion < 0x02070000,
"Differences in XML printing between 2.6 and 2.7")
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_xml(self):
filename = os.path.join(data_root, 'input/conformance/file1.jp2')
"""verify printing of XML box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file1.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2])
@ -707,10 +735,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_channel_definition(self):
filename = os.path.join(data_root, 'input/conformance/file2.jp2')
"""verify printing of cdef box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file2.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2])
@ -722,10 +751,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_component_mapping(self):
filename = os.path.join(data_root, 'input/conformance/file9.jp2')
"""verify printing of cmap box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[2])
@ -737,10 +767,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_palette(self):
filename = os.path.join(data_root, 'input/conformance/file9.jp2')
def test_palette7(self):
"""verify printing of pclr box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1])
@ -750,10 +781,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_palette(self):
filename = os.path.join(data_root, 'input/conformance/file7.jp2')
def test_rreq(self):
"""verify printing of reader requirements box"""
filename = os.path.join(DATA_ROOT, 'input/conformance/file7.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2])
@ -773,25 +805,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
"OPJ_DATA_ROOT environment variable not set")
def test_CRG(self):
filename = os.path.join(data_root, 'input/conformance/p0_03.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
print(codestream.segment[6])
actual = fake_out.getvalue().strip()
lines = ['CRG marker segment @ (87, 6)',
' Vertical, Horizontal offset: (0.50, 1.00)']
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_differing_subsamples(self):
# Issue 86.
filename = os.path.join(data_root, 'input/conformance/p0_05.j2k')
"""verify printing of SIZ with different subsampling... Issue 86."""
filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k')
j = glymur.Jp2k(filename)
codestream = j.get_codestream()
with patch('sys.stdout', new=StringIO()) as fake_out:
@ -810,11 +828,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_palette_box(self):
# Verify that palette (pclr) boxes are printed without error.
filename = os.path.join(data_root, 'input/conformance/file9.jp2')
"""Verify that palette (pclr) boxes are printed without error."""
filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2')
j = glymur.Jp2k(filename)
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2].box[1])
@ -826,54 +844,56 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
def test_less_common_boxes(self):
"""verify uinf, ulst, url, res, resd, resc box printing"""
with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile:
with open(self.jp2file, 'rb') as ifile:
# Everything up until the jp2c box.
buffer = ifile.read(77)
tfile.write(buffer)
wbuffer = ifile.read(77)
tfile.write(wbuffer)
# Write the UINF superbox
# Length = 50, id is uinf.
buffer = struct.pack('>I4s', int(50), b'uinf')
tfile.write(buffer)
wbuffer = struct.pack('>I4s', int(50), b'uinf')
tfile.write(wbuffer)
# Write the ULST box.
# Length is 26, 1 UUID, hard code that UUID as zeros.
buffer = struct.pack('>I4sHIIII', int(26), b'ulst', int(1),
int(0), int(0), int(0), int(0))
tfile.write(buffer)
wbuffer = struct.pack('>I4sHIIII', int(26), b'ulst', int(1),
int(0), int(0), int(0), int(0))
tfile.write(wbuffer)
# Write the URL box.
# Length is 16, version is one byte, flag is 3 bytes, url
# is the rest.
buffer = struct.pack('>I4sBBBB',
int(16), b'url ',
int(0), int(0), int(0), int(0))
tfile.write(buffer)
buffer = struct.pack('>ssss', b'a', b'b', b'c', b'd')
tfile.write(buffer)
wbuffer = struct.pack('>I4sBBBB',
int(16), b'url ',
int(0), int(0), int(0), int(0))
tfile.write(wbuffer)
wbuffer = struct.pack('>ssss', b'a', b'b', b'c', b'd')
tfile.write(wbuffer)
# Start the resolution superbox.
buffer = struct.pack('>I4s', int(44), b'res ')
tfile.write(buffer)
wbuffer = struct.pack('>I4s', int(44), b'res ')
tfile.write(wbuffer)
# Write the capture resolution box.
buffer = struct.pack('>I4sHHHHBB',
int(18), b'resc',
int(1), int(1), int(1), int(1),
int(0), int(1))
tfile.write(buffer)
wbuffer = struct.pack('>I4sHHHHBB',
int(18), b'resc',
int(1), int(1), int(1), int(1),
int(0), int(1))
tfile.write(wbuffer)
# Write the display resolution box.
buffer = struct.pack('>I4sHHHHBB',
int(18), b'resd',
int(1), int(1), int(1), int(1),
int(1), int(0))
tfile.write(buffer)
wbuffer = struct.pack('>I4sHHHHBB',
int(18), b'resd',
int(1), int(1), int(1), int(1),
int(1), int(0))
tfile.write(wbuffer)
# Get the rest of the input file.
buffer = ifile.read()
tfile.write(buffer)
wbuffer = ifile.read()
tfile.write(wbuffer)
tfile.flush()
jp2k = glymur.Jp2k(tfile.name)
@ -901,12 +921,13 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03000000,
"Ordered dicts not printing well in 2.7")
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_jpx_approximation_with_icc_profile(self):
def test_jpx_approx_icc_profile(self):
"""verify jpx with approx field equal to zero"""
# ICC profiles may be used in JP2, but the approximation field should
# be zero unless we have jpx. This file does both.
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2')
with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
@ -945,11 +966,11 @@ class TestPrinting(unittest.TestCase):
expected = '\n'.join(lines)
self.assertEqual(actual, expected)
@unittest.skipIf(data_root is None,
@unittest.skipIf(DATA_ROOT is None,
"OPJ_DATA_ROOT environment variable not set")
def test_uuid(self):
# UUID box
filename = os.path.join(data_root, 'input/nonregression/text_GBR.jp2')
"""verify printing of UUID box"""
filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2')
with warnings.catch_warnings():
# brand is 'jp2 ', but has any icc profile.
warnings.simplefilter("ignore")
@ -968,6 +989,7 @@ class TestPrinting(unittest.TestCase):
@unittest.skipIf(sys.hexversion < 0x03000000,
"Ordered dicts not printing well in 2.7")
def test_exif_uuid(self):
"""Verify printing of exif information"""
j = glymur.Jp2k(self.jp2file)
with patch('sys.stdout', new=StringIO()) as fake_out: