From e53a9a915778f6c426f396c03ae88c341a584f21 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Aug 2013 08:03:03 -0400 Subject: [PATCH 001/122] Moved the SIZ, COD, TLM, and PLT segment parsing back to being object methods. #94 --- glymur/codestream.py | 323 ++++++++++++++++++++++--------------------- 1 file changed, 164 insertions(+), 159 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 637f40e..f39b27f 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -150,30 +150,19 @@ class Codestream(object): segment = Segment(marker_id=the_id, offset=offset, length=0) elif marker_id == 0xff51: - # Need to keep track of the number of components from SIZ for - # other markers - segment = _parse_siz_segment(fptr) - self._csiz = len(segment.ssiz) + segment = self._parse_siz_segment(fptr) elif marker_id == 0xff52: - segment = _parse_cod_segment(fptr) - - sop = (segment.scod & 2) > 0 - eph = (segment.scod & 4) > 0 - - if sop or eph: - self._parse_tpart_flag = True - else: - self._parse_tpart_flag = False + segment = self._parse_cod_segment(fptr) elif marker_id == 0xff53: segment = self._parse_coc_segment(fptr) elif marker_id == 0xff55: - segment = _parse_tlm_segment(fptr) + segment = self._parse_tlm_segment(fptr) elif marker_id == 0xff58: - segment = _parse_plt_segment(fptr) + segment = self._parse_plt_segment(fptr) elif marker_id == 0xff5c: segment = _parse_qcd_segment(fptr) @@ -326,6 +315,81 @@ class Codestream(object): return COCsegment(ccoc, scoc, spcoc, length, offset) + + def _parse_cod_segment(self, fptr): + """Parse the COD segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + COD segment instance. + """ + offset = fptr.tell() - 2 + offset = fptr.tell() - 2 + + read_buffer = fptr.read(3) + length, scod = struct.unpack('>HB', read_buffer) + + numbytes = offset + 2 + length - fptr.tell() + spcod = fptr.read(numbytes) + spcod = np.frombuffer(spcod, dtype=np.uint8) + + sop = (scod & 2) > 0 + eph = (scod & 4) > 0 + + if sop or eph: + self._parse_tpart_flag = True + else: + self._parse_tpart_flag = False + + + return CODsegment(scod, spcod, length, offset) + + + def _parse_plt_segment(self, fptr): + """Parse the PLT segment. + + The packet headers are not parsed, i.e. they remain "uninterpreted" + raw data beffers. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + PLT segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(3) + length, zplt = struct.unpack('>HB', read_buffer) + + numbytes = length - 3 + read_buffer = fptr.read(numbytes) + iplt = np.frombuffer(read_buffer, dtype=np.uint8) + + packet_len = [] + plen = 0 + for byte in iplt: + plen |= (byte & 0x7f) + if byte & 0x80: + # Continue by or-ing in the next byte. + plen <<= 7 + else: + packet_len.append(plen) + plen = 0 + + iplt = packet_len + + return PLTsegment(zplt, iplt, length, offset) + + def _parse_pod_segment(self, fptr): """Parse the POD segment. @@ -423,6 +487,91 @@ class Codestream(object): return RGNsegment(length, offset, crgn, srgn, sprgn) + def _parse_siz_segment(self, fptr): + """Parse the SIZ segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + SIZsegment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(2) + length, = struct.unpack('>H', read_buffer) + + xy_buffer = fptr.read(36) + + num_components, = struct.unpack('>H', xy_buffer[-2:]) + + component_buffer = fptr.read(num_components * 3) + + segment = SIZsegment(xy_buffer, component_buffer, length, offset) + + # Need to keep track of the number of components from SIZ for + # other markers + self._csiz = len(segment.ssiz) + + return segment + + + def _parse_tlm_segment(self, fptr): + """Parse the TLM segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + TLM segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(2) + length, = struct.unpack('>H', read_buffer) + + read_buffer = fptr.read(2) + ztlm, stlm = struct.unpack('>BB', read_buffer) + ttlm_st = (stlm >> 4) & 0x3 + ptlm_sp = (stlm >> 6) & 0x1 + + nbytes = length - 4 + if ttlm_st == 0: + ntiles = nbytes / ((ptlm_sp + 1) * 2) + else: + ntiles = nbytes / (ttlm_st + (ptlm_sp + 1) * 2) + + read_buffer = fptr.read(nbytes) + if ttlm_st == 0: + ttlm = None + fmt = '' + elif ttlm_st == 1: + fmt = 'B' + elif ttlm_st == 2: + fmt = 'H' + + if ptlm_sp == 0: + fmt += 'H' + else: + fmt += 'I' + + data = struct.unpack('>' + fmt * int(ntiles), read_buffer) + if ttlm_st == 0: + ttlm = None + ptlm = data + else: + ttlm = data[0::2] + ptlm = data[1::2] + + return TLMsegment(length, offset, ztlm, ttlm, ptlm) + + class Segment(object): """Segment information. @@ -1435,59 +1584,6 @@ def _print_quantization_style(sqcc): return msg -def _parse_tlm_segment(fptr): - """Parse the TLM segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - TLM segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(2) - length, = struct.unpack('>H', read_buffer) - - read_buffer = fptr.read(2) - ztlm, stlm = struct.unpack('>BB', read_buffer) - ttlm_st = (stlm >> 4) & 0x3 - ptlm_sp = (stlm >> 6) & 0x1 - - nbytes = length - 4 - if ttlm_st == 0: - ntiles = nbytes / ((ptlm_sp + 1) * 2) - else: - ntiles = nbytes / (ttlm_st + (ptlm_sp + 1) * 2) - - read_buffer = fptr.read(nbytes) - if ttlm_st == 0: - ttlm = None - fmt = '' - elif ttlm_st == 1: - fmt = 'B' - elif ttlm_st == 2: - fmt = 'H' - - if ptlm_sp == 0: - fmt += 'H' - else: - fmt += 'I' - - data = struct.unpack('>' + fmt * int(ntiles), read_buffer) - if ttlm_st == 0: - ttlm = None - ptlm = data - else: - ttlm = data[0::2] - ptlm = data[1::2] - - return TLMsegment(length, offset, ztlm, ttlm, ptlm) - - def _parse_sot_segment(fptr): """Parse the SOT segment. @@ -1581,46 +1677,6 @@ def _parse_ppt_segment(fptr): return PPTsegment(zppt, ippt, length, offset) -def _parse_plt_segment(fptr): - """Parse the PLT segment. - - The packet headers are not parsed, i.e. they remain "uninterpreted" - raw data beffers. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - PLT segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(3) - length, zplt = struct.unpack('>HB', read_buffer) - - numbytes = length - 3 - read_buffer = fptr.read(numbytes) - iplt = np.frombuffer(read_buffer, dtype=np.uint8) - - packet_len = [] - plen = 0 - for byte in iplt: - plen |= (byte & 0x7f) - if byte & 0x80: - # Continue by or-ing in the next byte. - plen <<= 7 - else: - packet_len.append(plen) - plen = 0 - - iplt = packet_len - - return PLTsegment(zplt, iplt, length, offset) - - def _parse_ppm_segment(fptr): """Parse the PPM segment. @@ -1710,57 +1766,6 @@ def _parse_cme_segment(fptr): return CMEsegment(rcme, ccme, length, offset) -def _parse_siz_segment(fptr): - """Parse the SIZ segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - SIZsegment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(2) - length, = struct.unpack('>H', read_buffer) - - xy_buffer = fptr.read(36) - - num_components, = struct.unpack('>H', xy_buffer[-2:]) - - component_buffer = fptr.read(num_components * 3) - - return SIZsegment(xy_buffer, component_buffer, length, offset) - - -def _parse_cod_segment(fptr): - """Parse the COD segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - COD segment instance. - """ - offset = fptr.tell() - 2 - offset = fptr.tell() - 2 - - read_buffer = fptr.read(3) - length, scod = struct.unpack('>HB', read_buffer) - - numbytes = offset + 2 + length - fptr.tell() - spcod = fptr.read(numbytes) - spcod = np.frombuffer(spcod, dtype=np.uint8) - - return CODsegment(scod, spcod, length, offset) - - def _parse_generic_segment(fptr, marker_id): """Parse a generic marker segment. From 40e91dae7f1bd458a33dcc797e045bbe4258f3c7 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Aug 2013 09:30:13 -0400 Subject: [PATCH 002/122] All the known marker segments parsers are now methods. #94 --- glymur/codestream.py | 405 +++++++++++++++++++++---------------------- 1 file changed, 202 insertions(+), 203 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index f39b27f..e5acc1c 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -165,7 +165,7 @@ class Codestream(object): segment = self._parse_plt_segment(fptr) elif marker_id == 0xff5c: - segment = _parse_qcd_segment(fptr) + segment = self._parse_qcd_segment(fptr) elif marker_id == 0xff5d: segment = self._parse_qcc_segment(fptr) @@ -177,38 +177,25 @@ class Codestream(object): segment = self._parse_pod_segment(fptr) elif marker_id == 0xff60: - segment = _parse_ppm_segment(fptr) + segment = self._parse_ppm_segment(fptr) elif marker_id == 0xff61: - segment = _parse_ppt_segment(fptr) + segment = self._parse_ppt_segment(fptr) elif marker_id == 0xff63: - segment = _parse_crg_segment(fptr, self._csiz) + segment = self._parse_crg_segment(fptr) elif marker_id == 0xff64: - segment = _parse_cme_segment(fptr) + segment = self._parse_cme_segment(fptr) elif marker_id == 0xff90: - # Need to keep easy access to tile offsets and lengths for when - # we encounter start-of-data marker segments. - - segment = _parse_sot_segment(fptr) - self._tile_offset.append(segment.offset) - if segment.psot == 0: - tile_part_length = (self.offset + self.length - - segment.offset - 2) - else: - tile_part_length = segment.psot - self._tile_length.append(tile_part_length) + segment = self._parse_sot_segment(fptr) elif marker_id == 0xff93: - # start of data. Need to seek past the current tile part. - # The last SOT marker segment has the info that we need. - segment = _parse_sod_segment(fptr) + segment = self._parse_sod_segment(fptr) elif marker_id == 0xffd9: - # end of codestream - segment = _parse_eoc_segment(fptr) + segment = self._parse_eoc_segment(fptr) elif marker_id in _VALID_MARKERS: # It's a reserved marker that I don't know anything about. @@ -277,6 +264,29 @@ class Codestream(object): msg += ''.join(strs) return msg + def _parse_cme_segment(self, fptr): + """Parse the CME marker segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + CME segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(4) + data = struct.unpack('>HH', read_buffer) + length = data[0] + rcme = data[1] + ccme = fptr.read(length - 4) + + return CMEsegment(rcme, ccme, length, offset) + + def _parse_coc_segment(self, fptr): """Parse the COC marker segment. @@ -350,6 +360,49 @@ class Codestream(object): return CODsegment(scod, spcod, length, offset) + def _parse_crg_segment(self, fptr): + """Parse the CRG marker segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + CRG segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(2) + length, = struct.unpack('>H', read_buffer) + + read_buffer = fptr.read(4 * self._csiz) + data = struct.unpack('>' + 'HH' * self._csiz, read_buffer) + xcrg = data[0::2] + ycrg = data[1::2] + + return CRGsegment(xcrg, ycrg, length, offset) + + + def _parse_eoc_segment(self, fptr): + """Parse the EOC (end-of-codestream) marker segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + EOC Segment instance. + """ + offset = fptr.tell() - 2 + length = 0 + + return EOCsegment(length, offset) + + def _parse_plt_segment(self, fptr): """Parse the PLT segment. @@ -420,6 +473,57 @@ class Codestream(object): return PODsegment(pod_params, length, offset) + def _parse_ppm_segment(self, fptr): + """Parse the PPM segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + PPM segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(3) + length, zppm = struct.unpack('>HB', read_buffer) + + numbytes = length - 3 + read_buffer = fptr.read(numbytes) + + return PPMsegment(zppm, read_buffer, length, offset) + + + def _parse_ppt_segment(self, fptr): + """Parse the PPT segment. + + The packet headers are not parsed, i.e. they remain "uninterpreted" + raw data beffers. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + PPT segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(3) + length, zppt = struct.unpack('>HB', read_buffer) + length = length + zppt = zppt + + numbytes = length - 3 + ippt = fptr.read(numbytes) + + return PPTsegment(zppt, ippt, length, offset) + + def _parse_qcc_segment(self, fptr): """Parse the QCC segment. @@ -456,6 +560,26 @@ class Codestream(object): return QCCsegment(cqcc, sqcc, spqcc, length, offset) + def _parse_qcd_segment(self, fptr): + """Parse the QCD segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + QCD Segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(3) + length, sqcd = struct.unpack('>HB', read_buffer) + spqcd = fptr.read(length - 3) + + return QCDsegment(sqcd, spqcd, length, offset) + def _parse_rgn_segment(self, fptr): """Parse the RGN segment. @@ -519,6 +643,63 @@ class Codestream(object): return segment + def _parse_sod_segment(self, fptr): + """Parse the SOD (start-of-data) segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + SOD segment instance. + """ + offset = fptr.tell() - 2 + length = 0 + + return SODsegment(length, offset) + + + def _parse_sot_segment(self, fptr): + """Parse the SOT segment. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + SOT segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(10) + data = struct.unpack('>HHIBB', read_buffer) + + length = data[0] + isot = data[1] + psot = data[2] + tpsot = data[3] + tnsot = data[4] + + segment = SOTsegment(isot, psot, tpsot, tnsot, length, offset) + + # Need to keep easy access to tile offsets and lengths for when + # we encounter start-of-data marker segments. + + self._tile_offset.append(segment.offset) + if segment.psot == 0: + tile_part_length = (self.offset + self.length - + segment.offset - 2) + else: + tile_part_length = segment.psot + self._tile_length.append(tile_part_length) + + return segment + + def _parse_tlm_segment(self, fptr): """Parse the TLM segment. @@ -1584,188 +1765,6 @@ def _print_quantization_style(sqcc): return msg -def _parse_sot_segment(fptr): - """Parse the SOT segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - SOT segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(10) - data = struct.unpack('>HHIBB', read_buffer) - - length = data[0] - isot = data[1] - psot = data[2] - tpsot = data[3] - tnsot = data[4] - - return SOTsegment(isot, psot, tpsot, tnsot, length, offset) - - -def _parse_sod_segment(fptr): - """Parse the SOD segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - SOD segment instance. - """ - offset = fptr.tell() - 2 - length = 0 - - return SODsegment(length, offset) - - -def _parse_qcd_segment(fptr): - """Parse the QCD segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - QCD Segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(3) - length, sqcd = struct.unpack('>HB', read_buffer) - spqcd = fptr.read(length - 3) - - return QCDsegment(sqcd, spqcd, length, offset) - - -def _parse_ppt_segment(fptr): - """Parse the PPT segment. - - The packet headers are not parsed, i.e. they remain "uninterpreted" - raw data beffers. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - PPT segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(3) - length, zppt = struct.unpack('>HB', read_buffer) - length = length - zppt = zppt - - numbytes = length - 3 - ippt = fptr.read(numbytes) - - return PPTsegment(zppt, ippt, length, offset) - - -def _parse_ppm_segment(fptr): - """Parse the PPM segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - PPM segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(3) - length, zppm = struct.unpack('>HB', read_buffer) - - numbytes = length - 3 - read_buffer = fptr.read(numbytes) - - return PPMsegment(zppm, read_buffer, length, offset) - - -def _parse_crg_segment(fptr, csiz): - """Parse the CRG marker segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - CRG segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(2) - length, = struct.unpack('>H', read_buffer) - - read_buffer = fptr.read(4 * csiz) - data = struct.unpack('>' + 'HH' * csiz, read_buffer) - xcrg = data[0::2] - ycrg = data[1::2] - - return CRGsegment(xcrg, ycrg, length, offset) - - -def _parse_eoc_segment(fptr): - """Parse the EOC marker segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - EOC Segment instance. - """ - offset = fptr.tell() - 2 - length = 0 - - return EOCsegment(length, offset) - - -def _parse_cme_segment(fptr): - """Parse the CME marker segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - CME segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(4) - data = struct.unpack('>HH', read_buffer) - length = data[0] - rcme = data[1] - ccme = fptr.read(length - 4) - - return CMEsegment(rcme, ccme, length, offset) - - def _parse_generic_segment(fptr, marker_id): """Parse a generic marker segment. From 2b5b1d081d85110d38425144db3832153e6d22ba Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Aug 2013 11:13:57 -0400 Subject: [PATCH 003/122] All parsing routines have the same signature now. #94 --- glymur/codestream.py | 150 +++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 69 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index e5acc1c..65b6130 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -103,7 +103,7 @@ class Codestream(object): read_buffer = fptr.read(2) try: - marker_id, = struct.unpack('>H', read_buffer) + self._marker_id, = struct.unpack('>H', read_buffer) except struct.error: # Treat this as a warning. msg = "Marker had length {0} instead of expected length of 2 " @@ -111,13 +111,15 @@ class Codestream(object): warnings.warn(msg.format(len(read_buffer))) break - if marker_id == 0xff90 and header_only: + self._offset = fptr.tell() - 2 + + if self._marker_id == 0xff90 and header_only: # Start-of-tile (SOT) means that we are out of the main header # and there is no need to go further. break try: - segment = self._process_marker_segment(fptr, marker_id) + segment = self._process_marker_segment(fptr) except Exception as error: # Treat this as a warning. msg = str(error) @@ -126,11 +128,11 @@ class Codestream(object): self.segment.append(segment) - if marker_id == 0xffd9: + if self._marker_id == 0xffd9: # end of codestream, should break. break - if marker_id == 0xff93: + if self._marker_id == 0xff93: # If SOD, then we need to seek past the tile part bit stream. if self._parse_tpart_flag and not header_only: # But first parse the tile part bit stream for SOP and @@ -140,93 +142,126 @@ class Codestream(object): fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) - def _process_marker_segment(self, fptr, marker_id): + def _process_marker_segment(self, fptr): """Process and return a segment from the codestream. """ - offset = fptr.tell() - 2 + if self._marker_id >= 0xff30 and self._marker_id <= 0xff3f: + segment = self._parse_reserved_marker(fptr) - if marker_id >= 0xff30 and marker_id <= 0xff3f: - the_id = '0x{0:x}'.format(marker_id) - segment = Segment(marker_id=the_id, offset=offset, length=0) - - elif marker_id == 0xff51: + elif self._marker_id == 0xff51: segment = self._parse_siz_segment(fptr) - elif marker_id == 0xff52: + elif self._marker_id == 0xff52: segment = self._parse_cod_segment(fptr) - elif marker_id == 0xff53: + elif self._marker_id == 0xff53: segment = self._parse_coc_segment(fptr) - elif marker_id == 0xff55: + elif self._marker_id == 0xff55: segment = self._parse_tlm_segment(fptr) - elif marker_id == 0xff58: + elif self._marker_id == 0xff58: segment = self._parse_plt_segment(fptr) - elif marker_id == 0xff5c: + elif self._marker_id == 0xff5c: segment = self._parse_qcd_segment(fptr) - elif marker_id == 0xff5d: + elif self._marker_id == 0xff5d: segment = self._parse_qcc_segment(fptr) - elif marker_id == 0xff5e: + elif self._marker_id == 0xff5e: segment = self._parse_rgn_segment(fptr) - elif marker_id == 0xff5f: + elif self._marker_id == 0xff5f: segment = self._parse_pod_segment(fptr) - elif marker_id == 0xff60: + elif self._marker_id == 0xff60: segment = self._parse_ppm_segment(fptr) - elif marker_id == 0xff61: + elif self._marker_id == 0xff61: segment = self._parse_ppt_segment(fptr) - elif marker_id == 0xff63: + elif self._marker_id == 0xff63: segment = self._parse_crg_segment(fptr) - elif marker_id == 0xff64: + elif self._marker_id == 0xff64: segment = self._parse_cme_segment(fptr) - elif marker_id == 0xff90: + elif self._marker_id == 0xff90: segment = self._parse_sot_segment(fptr) - elif marker_id == 0xff93: + elif self._marker_id == 0xff93: segment = self._parse_sod_segment(fptr) - elif marker_id == 0xffd9: + elif self._marker_id == 0xffd9: segment = self._parse_eoc_segment(fptr) - elif marker_id in _VALID_MARKERS: + elif self._marker_id in _VALID_MARKERS: # It's a reserved marker that I don't know anything about. # See table A-1 in ISO/IEC FCD15444-1. - segment = _parse_generic_segment(fptr, marker_id) + segment = self._parse_reserved_segment(fptr) - elif ((marker_id & 0xff00) >> 8) == 255: - # Peek ahead to see if the next two bytes are a marker or not. - # Then seek back. - msg = "Unrecognized marker id: 0x{0:x}".format(marker_id) - warnings.warn(msg) - cpos = fptr.tell() - read_buffer = fptr.read(2) - next_item, = struct.unpack('>H', read_buffer) - fptr.seek(cpos) - if ((next_item & 0xff00) >> 8) == 255: - # No segment associated with this marker, so reset - # to two bytes after it. - segment = Segment(id='0x{0:x}'.format(marker_id), - offset=offset, length=0) - else: - segment = _parse_generic_segment(fptr, marker_id) + elif self._marker_id == 0xff79: + segment = self._parse_unrecognized_segment(fptr) else: msg = 'Invalid marker id encountered at byte {0:d} ' msg += 'in codestream: "0x{1:x}"' - msg = msg.format(offset, marker_id) + msg = msg.format(self._offset, self._marker_id) raise IOError(msg) return segment + def _parse_unrecognized_segment(self, fptr): + """Looks like a marker, but not sure what it is. + """ + msg = "Unrecognized marker id: 0x{0:x}".format(self._marker_id) + warnings.warn(msg) + cpos = fptr.tell() + read_buffer = fptr.read(2) + next_item, = struct.unpack('>H', read_buffer) + fptr.seek(cpos) + if ((next_item & 0xff00) >> 8) == 255: + # No segment associated with this marker, so reset + # to two bytes after it. + segment = Segment(id='0x{0:x}'.format(self._marker_id), + offset=self._offset, length=0) + else: + segment = self._parse_reserved_segment(fptr) + return segment + + + def _parse_reserved_marker(self, fptr): + """Marker range between 0xff30 and 0xff39. + """ + the_id = '0x{0:x}'.format(self._marker_id) + segment = Segment(marker_id=the_id, offset=self._offset, length=0) + return segment + + + def _parse_reserved_segment(self, fptr): + """Parse a marker segment for which we know nothing of the segment itself. + + Parameters + ---------- + fptr : file + Open file object. + + Returns + ------- + Segment instance. + """ + offset = fptr.tell() - 2 + + read_buffer = fptr.read(2) + length, = struct.unpack('>H', read_buffer) + data = fptr.read(length-2) + + segment = Segment(marker_id='0x{0:x}'.format(self._marker_id), + offset=offset, length=length, data=data) + return segment + + def _parse_tile_part_bit_stream(self, fptr, sod_marker, tile_length): """Parse the tile part bit stream for SOP, EPH marker segments.""" read_buffer = fptr.read(tile_length) @@ -1763,26 +1798,3 @@ def _print_quantization_style(sqcc): elif sqcc & 0x1f == 2: msg += 'scalar explicit, ' return msg - - -def _parse_generic_segment(fptr, marker_id): - """Parse a generic marker segment. - - Parameters - ---------- - fptr : file - Open file object. - - Returns - ------- - Segment instance. - """ - offset = fptr.tell() - 2 - - read_buffer = fptr.read(2) - length, = struct.unpack('>H', read_buffer) - data = fptr.read(length-2) - - segment = Segment(marker_id='0x{0:x}'.format(marker_id), offset=offset, - length=length, data=data) - return segment From ebb15b0fba4f5c72107e2b6a8e5928a5e1221b63 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 1 Aug 2013 13:51:23 -0400 Subject: [PATCH 004/122] Finished refactoring marker segment parsing, #94. --- glymur/codestream.py | 141 ++++++++++++++++----------------- glymur/test/test_codestream.py | 14 ++-- 2 files changed, 76 insertions(+), 79 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 65b6130..d41d8f1 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -77,6 +77,66 @@ class Codestream(object): If True, only marker segments in the main header are parsed. Supplying False may impose a large performance penalty. """ + # Map each of the known markers to a method that processes them. + process_marker_segment = { + 0xff00: self._parse_reserved_segment, + 0xff01: self._parse_reserved_segment, + 0xff30: self._parse_reserved_marker, + 0xff31: self._parse_reserved_marker, + 0xff32: self._parse_reserved_marker, + 0xff33: self._parse_reserved_marker, + 0xff34: self._parse_reserved_marker, + 0xff35: self._parse_reserved_marker, + 0xff36: self._parse_reserved_marker, + 0xff37: self._parse_reserved_marker, + 0xff38: self._parse_reserved_marker, + 0xff39: self._parse_reserved_marker, + 0xff3a: self._parse_reserved_marker, + 0xff3b: self._parse_reserved_marker, + 0xff3c: self._parse_reserved_marker, + 0xff3d: self._parse_reserved_marker, + 0xff3e: self._parse_reserved_marker, + 0xff3f: self._parse_reserved_marker, + 0xff4f: self._parse_reserved_segment, + 0xff50: self._parse_reserved_segment, + 0xff51: self._parse_siz_segment, + 0xff52: self._parse_cod_segment, + 0xff53: self._parse_coc_segment, + 0xff54: self._parse_reserved_segment, + 0xff55: self._parse_tlm_segment, + 0xff56: self._parse_reserved_segment, + 0xff57: self._parse_reserved_segment, + 0xff58: self._parse_plt_segment, + 0xff59: self._parse_reserved_segment, + 0xff5a: self._parse_reserved_segment, + 0xff5b: self._parse_reserved_segment, + 0xff5c: self._parse_qcd_segment, + 0xff5d: self._parse_qcc_segment, + 0xff5e: self._parse_rgn_segment, + 0xff5f: self._parse_pod_segment, + 0xff60: self._parse_ppm_segment, + 0xff61: self._parse_ppt_segment, + 0xff62: self._parse_reserved_segment, + 0xff63: self._parse_crg_segment, + 0xff64: self._parse_cme_segment, + 0xff65: self._parse_reserved_segment, + 0xff66: self._parse_reserved_segment, + 0xff67: self._parse_reserved_segment, + 0xff68: self._parse_reserved_segment, + 0xff69: self._parse_reserved_segment, + 0xff6a: self._parse_reserved_segment, + 0xff6b: self._parse_reserved_segment, + 0xff6c: self._parse_reserved_segment, + 0xff6d: self._parse_reserved_segment, + 0xff6e: self._parse_reserved_segment, + 0xff6f: self._parse_reserved_segment, + 0xff79: self._parse_unrecognized_segment, + 0xff90: self._parse_sot_segment, + 0xff91: self._parse_unrecognized_segment, + 0xff92: self._parse_unrecognized_segment, + 0xff93: self._parse_sod_segment, + 0xffd9: self._parse_eoc_segment, + } self.offset = fptr.tell() self.length = length @@ -119,7 +179,13 @@ class Codestream(object): break try: - segment = self._process_marker_segment(fptr) + segment = process_marker_segment[self._marker_id](fptr) + except KeyError: + msg = 'Invalid marker id encountered at byte {0:d} ' + msg += 'in codestream: "0x{1:x}"' + msg = msg.format(self._offset, self._marker_id) + warnings.warn(msg) + break except Exception as error: # Treat this as a warning. msg = str(error) @@ -142,78 +208,9 @@ class Codestream(object): fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) - def _process_marker_segment(self, fptr): - """Process and return a segment from the codestream. - """ - if self._marker_id >= 0xff30 and self._marker_id <= 0xff3f: - segment = self._parse_reserved_marker(fptr) - - elif self._marker_id == 0xff51: - segment = self._parse_siz_segment(fptr) - - elif self._marker_id == 0xff52: - segment = self._parse_cod_segment(fptr) - - elif self._marker_id == 0xff53: - segment = self._parse_coc_segment(fptr) - - elif self._marker_id == 0xff55: - segment = self._parse_tlm_segment(fptr) - - elif self._marker_id == 0xff58: - segment = self._parse_plt_segment(fptr) - - elif self._marker_id == 0xff5c: - segment = self._parse_qcd_segment(fptr) - - elif self._marker_id == 0xff5d: - segment = self._parse_qcc_segment(fptr) - - elif self._marker_id == 0xff5e: - segment = self._parse_rgn_segment(fptr) - - elif self._marker_id == 0xff5f: - segment = self._parse_pod_segment(fptr) - - elif self._marker_id == 0xff60: - segment = self._parse_ppm_segment(fptr) - - elif self._marker_id == 0xff61: - segment = self._parse_ppt_segment(fptr) - - elif self._marker_id == 0xff63: - segment = self._parse_crg_segment(fptr) - - elif self._marker_id == 0xff64: - segment = self._parse_cme_segment(fptr) - - elif self._marker_id == 0xff90: - segment = self._parse_sot_segment(fptr) - - elif self._marker_id == 0xff93: - segment = self._parse_sod_segment(fptr) - - elif self._marker_id == 0xffd9: - segment = self._parse_eoc_segment(fptr) - - elif self._marker_id in _VALID_MARKERS: - # It's a reserved marker that I don't know anything about. - # See table A-1 in ISO/IEC FCD15444-1. - segment = self._parse_reserved_segment(fptr) - - elif self._marker_id == 0xff79: - segment = self._parse_unrecognized_segment(fptr) - - else: - msg = 'Invalid marker id encountered at byte {0:d} ' - msg += 'in codestream: "0x{1:x}"' - msg = msg.format(self._offset, self._marker_id) - raise IOError(msg) - - return segment def _parse_unrecognized_segment(self, fptr): - """Looks like a marker, but not sure what it is. + """Looks like a valid marker, but not sure from reading the specs. """ msg = "Unrecognized marker id: 0x{0:x}".format(self._marker_id) warnings.warn(msg) @@ -240,7 +237,7 @@ class Codestream(object): def _parse_reserved_segment(self, fptr): - """Parse a marker segment for which we know nothing of the segment itself. + """Parse valid marker segment, segment description is unknown. Parameters ---------- diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py index 31c674c..f0d3e8a 100644 --- a/glymur/test/test_codestream.py +++ b/glymur/test/test_codestream.py @@ -63,9 +63,9 @@ class TestCodestream(unittest.TestCase): self.assertEqual(c.segment[2].length, 3) self.assertEqual(c.segment[2]._data, b'\x00') - @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @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): # Let's inject a marker segment whose marker does not appear to # be valid. We still parse the file, but warn about the offending @@ -86,13 +86,13 @@ class TestCodestream(unittest.TestCase): tfile.write(buffer) tfile.flush() - with self.assertWarns(UserWarning) as cw: - j = Jp2k(tfile.name) - c = j.get_codestream() + with self.assertWarns(UserWarning): + j = Jp2k(tfile.name) + c = j.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(c.segment[2].marker_id, '0xff79') + self.assertEqual(c.segment[2].length, 3) + self.assertEqual(c.segment[2]._data, b'\x00') def test_psot_is_zero(self): # Psot=0 in SOT is perfectly legal. Issue #78. From 586e810a7fd3ea2014ce7f1f0afdcbda661cbfbd Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 1 Aug 2013 18:08:42 -0400 Subject: [PATCH 005/122] pep8, pylint work. closes #94. --- glymur/codestream.py | 287 ++++++++++++++++++++----------------------- 1 file changed, 134 insertions(+), 153 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index d41d8f1..47cde28 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -78,65 +78,63 @@ class Codestream(object): Supplying False may impose a large performance penalty. """ # Map each of the known markers to a method that processes them. - process_marker_segment = { - 0xff00: self._parse_reserved_segment, - 0xff01: self._parse_reserved_segment, - 0xff30: self._parse_reserved_marker, - 0xff31: self._parse_reserved_marker, - 0xff32: self._parse_reserved_marker, - 0xff33: self._parse_reserved_marker, - 0xff34: self._parse_reserved_marker, - 0xff35: self._parse_reserved_marker, - 0xff36: self._parse_reserved_marker, - 0xff37: self._parse_reserved_marker, - 0xff38: self._parse_reserved_marker, - 0xff39: self._parse_reserved_marker, - 0xff3a: self._parse_reserved_marker, - 0xff3b: self._parse_reserved_marker, - 0xff3c: self._parse_reserved_marker, - 0xff3d: self._parse_reserved_marker, - 0xff3e: self._parse_reserved_marker, - 0xff3f: self._parse_reserved_marker, - 0xff4f: self._parse_reserved_segment, - 0xff50: self._parse_reserved_segment, - 0xff51: self._parse_siz_segment, - 0xff52: self._parse_cod_segment, - 0xff53: self._parse_coc_segment, - 0xff54: self._parse_reserved_segment, - 0xff55: self._parse_tlm_segment, - 0xff56: self._parse_reserved_segment, - 0xff57: self._parse_reserved_segment, - 0xff58: self._parse_plt_segment, - 0xff59: self._parse_reserved_segment, - 0xff5a: self._parse_reserved_segment, - 0xff5b: self._parse_reserved_segment, - 0xff5c: self._parse_qcd_segment, - 0xff5d: self._parse_qcc_segment, - 0xff5e: self._parse_rgn_segment, - 0xff5f: self._parse_pod_segment, - 0xff60: self._parse_ppm_segment, - 0xff61: self._parse_ppt_segment, - 0xff62: self._parse_reserved_segment, - 0xff63: self._parse_crg_segment, - 0xff64: self._parse_cme_segment, - 0xff65: self._parse_reserved_segment, - 0xff66: self._parse_reserved_segment, - 0xff67: self._parse_reserved_segment, - 0xff68: self._parse_reserved_segment, - 0xff69: self._parse_reserved_segment, - 0xff6a: self._parse_reserved_segment, - 0xff6b: self._parse_reserved_segment, - 0xff6c: self._parse_reserved_segment, - 0xff6d: self._parse_reserved_segment, - 0xff6e: self._parse_reserved_segment, - 0xff6f: self._parse_reserved_segment, - 0xff79: self._parse_unrecognized_segment, - 0xff90: self._parse_sot_segment, - 0xff91: self._parse_unrecognized_segment, - 0xff92: self._parse_unrecognized_segment, - 0xff93: self._parse_sod_segment, - 0xffd9: self._parse_eoc_segment, - } + process_marker_segment = {0xff00: self._parse_reserved_segment, + 0xff01: self._parse_reserved_segment, + 0xff30: self._parse_reserved_marker, + 0xff31: self._parse_reserved_marker, + 0xff32: self._parse_reserved_marker, + 0xff33: self._parse_reserved_marker, + 0xff34: self._parse_reserved_marker, + 0xff35: self._parse_reserved_marker, + 0xff36: self._parse_reserved_marker, + 0xff37: self._parse_reserved_marker, + 0xff38: self._parse_reserved_marker, + 0xff39: self._parse_reserved_marker, + 0xff3a: self._parse_reserved_marker, + 0xff3b: self._parse_reserved_marker, + 0xff3c: self._parse_reserved_marker, + 0xff3d: self._parse_reserved_marker, + 0xff3e: self._parse_reserved_marker, + 0xff3f: self._parse_reserved_marker, + 0xff4f: self._parse_reserved_segment, + 0xff50: self._parse_reserved_segment, + 0xff51: self._parse_siz_segment, + 0xff52: self._parse_cod_segment, + 0xff53: self._parse_coc_segment, + 0xff54: self._parse_reserved_segment, + 0xff55: self._parse_tlm_segment, + 0xff56: self._parse_reserved_segment, + 0xff57: self._parse_reserved_segment, + 0xff58: self._parse_plt_segment, + 0xff59: self._parse_reserved_segment, + 0xff5a: self._parse_reserved_segment, + 0xff5b: self._parse_reserved_segment, + 0xff5c: self._parse_qcd_segment, + 0xff5d: self._parse_qcc_segment, + 0xff5e: self._parse_rgn_segment, + 0xff5f: self._parse_pod_segment, + 0xff60: self._parse_ppm_segment, + 0xff61: self._parse_ppt_segment, + 0xff62: self._parse_reserved_segment, + 0xff63: self._parse_crg_segment, + 0xff64: self._parse_cme_segment, + 0xff65: self._parse_reserved_segment, + 0xff66: self._parse_reserved_segment, + 0xff67: self._parse_reserved_segment, + 0xff68: self._parse_reserved_segment, + 0xff69: self._parse_reserved_segment, + 0xff6a: self._parse_reserved_segment, + 0xff6b: self._parse_reserved_segment, + 0xff6c: self._parse_reserved_segment, + 0xff6d: self._parse_reserved_segment, + 0xff6e: self._parse_reserved_segment, + 0xff6f: self._parse_reserved_segment, + 0xff79: self._parse_unrecognized_segment, + 0xff90: self._parse_sot_segment, + 0xff91: self._parse_unrecognized_segment, + 0xff92: self._parse_unrecognized_segment, + 0xff93: self._parse_sod_segment, + 0xffd9: self._parse_eoc_segment} self.offset = fptr.tell() self.length = length @@ -150,9 +148,8 @@ class Codestream(object): self.segment = [] - # First two bytes are the SOC marker + # First two bytes are the SOC marker. We already know that. read_buffer = fptr.read(2) - marker_id, = struct.unpack('>H', read_buffer) segment = SOCsegment(offset=fptr.tell() - 2, length=0) self.segment.append(segment) @@ -208,7 +205,6 @@ class Codestream(object): fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) - def _parse_unrecognized_segment(self, fptr): """Looks like a valid marker, but not sure from reading the specs. """ @@ -225,40 +221,37 @@ class Codestream(object): offset=self._offset, length=0) else: segment = self._parse_reserved_segment(fptr) - return segment - + return segment def _parse_reserved_marker(self, fptr): """Marker range between 0xff30 and 0xff39. """ the_id = '0x{0:x}'.format(self._marker_id) segment = Segment(marker_id=the_id, offset=self._offset, length=0) - return segment - + return segment def _parse_reserved_segment(self, fptr): """Parse valid marker segment, segment description is unknown. - + Parameters ---------- fptr : file Open file object. - + Returns ------- Segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(2) length, = struct.unpack('>H', read_buffer) data = fptr.read(length-2) - + segment = Segment(marker_id='0x{0:x}'.format(self._marker_id), offset=offset, length=length, data=data) return segment - def _parse_tile_part_bit_stream(self, fptr, sod_marker, tile_length): """Parse the tile part bit stream for SOP, EPH marker segments.""" read_buffer = fptr.read(tile_length) @@ -296,29 +289,29 @@ class Codestream(object): msg += ''.join(strs) return msg + # pylint: disable=R0201 def _parse_cme_segment(self, fptr): """Parse the CME marker segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- CME segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(4) data = struct.unpack('>HH', read_buffer) length = data[0] rcme = data[1] ccme = fptr.read(length - 4) - + return CMEsegment(rcme, ccme, length, offset) - - + def _parse_coc_segment(self, fptr): """Parse the COC marker segment. @@ -357,25 +350,24 @@ class Codestream(object): return COCsegment(ccoc, scoc, spcoc, length, offset) - def _parse_cod_segment(self, fptr): """Parse the COD segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- COD segment instance. """ offset = fptr.tell() - 2 offset = fptr.tell() - 2 - + read_buffer = fptr.read(3) length, scod = struct.unpack('>HB', read_buffer) - + numbytes = offset + 2 + length - fptr.tell() spcod = fptr.read(numbytes) spcod = np.frombuffer(spcod, dtype=np.uint8) @@ -388,77 +380,73 @@ class Codestream(object): else: self._parse_tpart_flag = False - return CODsegment(scod, spcod, length, offset) - - + def _parse_crg_segment(self, fptr): """Parse the CRG marker segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- CRG segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(2) length, = struct.unpack('>H', read_buffer) - + read_buffer = fptr.read(4 * self._csiz) data = struct.unpack('>' + 'HH' * self._csiz, read_buffer) xcrg = data[0::2] ycrg = data[1::2] - - return CRGsegment(xcrg, ycrg, length, offset) + return CRGsegment(xcrg, ycrg, length, offset) def _parse_eoc_segment(self, fptr): """Parse the EOC (end-of-codestream) marker segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- EOC Segment instance. """ offset = fptr.tell() - 2 length = 0 - + return EOCsegment(length, offset) - - + def _parse_plt_segment(self, fptr): """Parse the PLT segment. - + The packet headers are not parsed, i.e. they remain "uninterpreted" raw data beffers. - + Parameters ---------- fptr : file Open file object. - + Returns ------- PLT segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(3) length, zplt = struct.unpack('>HB', read_buffer) - + numbytes = length - 3 read_buffer = fptr.read(numbytes) iplt = np.frombuffer(read_buffer, dtype=np.uint8) - + packet_len = [] plen = 0 for byte in iplt: @@ -469,12 +457,11 @@ class Codestream(object): else: packet_len.append(plen) plen = 0 - + iplt = packet_len - + return PLTsegment(zplt, iplt, length, offset) - - + def _parse_pod_segment(self, fptr): """Parse the POD segment. @@ -507,54 +494,52 @@ class Codestream(object): def _parse_ppm_segment(self, fptr): """Parse the PPM segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- PPM segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(3) length, zppm = struct.unpack('>HB', read_buffer) - + numbytes = length - 3 read_buffer = fptr.read(numbytes) - + return PPMsegment(zppm, read_buffer, length, offset) - - + def _parse_ppt_segment(self, fptr): """Parse the PPT segment. - + The packet headers are not parsed, i.e. they remain "uninterpreted" raw data beffers. - + Parameters ---------- fptr : file Open file object. - + Returns ------- PPT segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(3) length, zppt = struct.unpack('>HB', read_buffer) length = length zppt = zppt - + numbytes = length - 3 ippt = fptr.read(numbytes) - - return PPTsegment(zppt, ippt, length, offset) + return PPTsegment(zppt, ippt, length, offset) def _parse_qcc_segment(self, fptr): """Parse the QCC segment. @@ -594,22 +579,22 @@ class Codestream(object): def _parse_qcd_segment(self, fptr): """Parse the QCD segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- QCD Segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(3) length, sqcd = struct.unpack('>HB', read_buffer) spqcd = fptr.read(length - 3) - + return QCDsegment(sqcd, spqcd, length, offset) def _parse_rgn_segment(self, fptr): @@ -645,44 +630,43 @@ class Codestream(object): def _parse_siz_segment(self, fptr): """Parse the SIZ segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- SIZsegment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(2) length, = struct.unpack('>H', read_buffer) - + xy_buffer = fptr.read(36) - + num_components, = struct.unpack('>H', xy_buffer[-2:]) - + component_buffer = fptr.read(num_components * 3) segment = SIZsegment(xy_buffer, component_buffer, length, offset) - + # Need to keep track of the number of components from SIZ for # other markers self._csiz = len(segment.ssiz) return segment - - + def _parse_sod_segment(self, fptr): """Parse the SOD (start-of-data) segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- SOD segment instance. @@ -692,30 +676,29 @@ class Codestream(object): return SODsegment(length, offset) - def _parse_sot_segment(self, fptr): """Parse the SOT segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- SOT segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(10) data = struct.unpack('>HHIBB', read_buffer) - + length = data[0] isot = data[1] psot = data[2] tpsot = data[3] tnsot = data[4] - + segment = SOTsegment(isot, psot, tpsot, tnsot, length, offset) # Need to keep easy access to tile offsets and lengths for when @@ -730,36 +713,35 @@ class Codestream(object): self._tile_length.append(tile_part_length) return segment - - + def _parse_tlm_segment(self, fptr): """Parse the TLM segment. - + Parameters ---------- fptr : file Open file object. - + Returns ------- TLM segment instance. """ offset = fptr.tell() - 2 - + read_buffer = fptr.read(2) length, = struct.unpack('>H', read_buffer) - + read_buffer = fptr.read(2) ztlm, stlm = struct.unpack('>BB', read_buffer) ttlm_st = (stlm >> 4) & 0x3 ptlm_sp = (stlm >> 6) & 0x1 - + nbytes = length - 4 if ttlm_st == 0: ntiles = nbytes / ((ptlm_sp + 1) * 2) else: ntiles = nbytes / (ttlm_st + (ptlm_sp + 1) * 2) - + read_buffer = fptr.read(nbytes) if ttlm_st == 0: ttlm = None @@ -768,12 +750,12 @@ class Codestream(object): fmt = 'B' elif ttlm_st == 2: fmt = 'H' - + if ptlm_sp == 0: fmt += 'H' else: fmt += 'I' - + data = struct.unpack('>' + fmt * int(ntiles), read_buffer) if ttlm_st == 0: ttlm = None @@ -781,9 +763,8 @@ class Codestream(object): else: ttlm = data[0::2] ptlm = data[1::2] - + return TLMsegment(length, offset, ztlm, ttlm, ptlm) - class Segment(object): From 915e0322809ea979a6709e43bd8f46dba48894d9 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 1 Aug 2013 20:38:32 -0400 Subject: [PATCH 006/122] Changed license line to 'MIT'. The license itself didn't change, just the way that it is listed in the trove classifier. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f725631..ae875c0 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ kwargs = {'name': 'Glymur', 'glymur.lib.test'], 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'scripts': ['bin/jp2dump'], - 'license': 'LICENSE.txt', + 'license': 'MIT', 'test_suite': 'glymur.test', 'platforms': ['darwin']} From f46cdfb75951144a037b810cdebc30b8dc20c014 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 3 Aug 2013 07:58:00 -0400 Subject: [PATCH 007/122] "except Exception" was totally unnecessary, Closes #95 --- glymur/codestream.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 47cde28..4a5a5d2 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -183,11 +183,6 @@ class Codestream(object): msg = msg.format(self._offset, self._marker_id) warnings.warn(msg) break - except Exception as error: - # Treat this as a warning. - msg = str(error) - warnings.warn(msg) - break self.segment.append(segment) @@ -223,13 +218,6 @@ class Codestream(object): segment = self._parse_reserved_segment(fptr) return segment - def _parse_reserved_marker(self, fptr): - """Marker range between 0xff30 and 0xff39. - """ - the_id = '0x{0:x}'.format(self._marker_id) - segment = Segment(marker_id=the_id, offset=self._offset, length=0) - return segment - def _parse_reserved_segment(self, fptr): """Parse valid marker segment, segment description is unknown. @@ -766,6 +754,14 @@ class Codestream(object): return TLMsegment(length, offset, ztlm, ttlm, ptlm) + # pylint: disable=W0613 + def _parse_reserved_marker(self, fptr): + """Marker range between 0xff30 and 0xff39. + """ + the_id = '0x{0:x}'.format(self._marker_id) + segment = Segment(marker_id=the_id, offset=self._offset, length=0) + return segment + class Segment(object): """Segment information. From 20825f960af30b44380d62eec856e3e2d71ac1b0 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 3 Aug 2013 16:11:10 -0400 Subject: [PATCH 008/122] Modified the warning a bit to make it clearer. Closes #87. --- glymur/jp2box.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index c264b7b..149af0a 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1791,14 +1791,15 @@ class XMLBox(Jp2kBox): read_buffer = fptr.read(num_bytes) text = read_buffer.decode('utf-8') - # Strip out any trailing nulls. + # Strip out any trailing nulls, as they can foul up XML parsing. text = text.rstrip('\0') try: elt = ET.fromstring(text) xml = ET.ElementTree(elt) except ParseError as parse_error: - msg = 'A problem was encountered while parsing an XML box: "{0}"' + msg = 'A problem was encountered while parsing an XML box:' + msg += '\n\n\t"{0}"\n\nNo XML was retrieved.' msg = msg.format(str(parse_error)) warnings.warn(msg, UserWarning) xml = None From 10da885ff516d63ccdedd4c65691c86d1dec6979 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 4 Aug 2013 11:36:38 -0400 Subject: [PATCH 009/122] No longer needed, better suited for a wiki page. Closes #95. --- release.txt | 59 ----------------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 release.txt diff --git a/release.txt b/release.txt deleted file mode 100644 index 17d55e0..0000000 --- a/release.txt +++ /dev/null @@ -1,59 +0,0 @@ -| OS | Python | Python | Python | Notes | -| | 2.6 | 2.7 | 3.3 | | -+-----------+--------+--------+--------+--------------------------------------+ -| Windows | | X | | WinPython with OpenJPEG 1.5.1 and | -| | | | | OpenJPEG 2.0.0. 267 of 455 tests | -| | | | | pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Windows | | | X | WinPython with OpenJPEG 1.5.1 and | -| | | | | OpenJPEG svn. 307 of 455 tests | -| | | | | pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | X | | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 354 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | X | | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 315 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | X | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 379 of 461 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | X | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 340 of 461 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | | X | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 407 of 461 | -| | | | | tests should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | | X | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 355 of 461 | -| | | | | tests should pass. | -+-----------+--------+--------+-----------------------------------------------+ -| Fedora 19 | | | X | Ships with 1.5.1, openjp2 svn built, | -| | | | | too. 407 of 461 tests should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Fedora 18 | | X | | Ships with 1.5.1. 173 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Fedora 17 | | X | | Ships with 1.4.0. 171 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| CentOS | X | | | Ships with 1.3.0. 169 of 456 tests | -| 6.3 | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Raspberry | | X | | Ships with 1.3.0. 171 of 456 tests | -| Pi | | | | should pass. | -| Debian 7 | | | | | -+-----------+--------+--------+--------+--------------------------------------+ - -Make release branch, qualify on all platforms. -Pylint on entire package should exceed 0.95. -pep8 should be pass cleanly. -Coverage should exceed 95%. -Make release candidate, push to Pypi, qualify in virtual environment. -Merge release branch to master, tag, push to master, push to Pypi. - From d077da26f241b3a6b011816eed538292b074d27e Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 4 Aug 2013 11:36:38 -0400 Subject: [PATCH 010/122] No longer needed, better suited for a wiki page. Closes #97. --- release.txt | 59 ----------------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 release.txt diff --git a/release.txt b/release.txt deleted file mode 100644 index 17d55e0..0000000 --- a/release.txt +++ /dev/null @@ -1,59 +0,0 @@ -| OS | Python | Python | Python | Notes | -| | 2.6 | 2.7 | 3.3 | | -+-----------+--------+--------+--------+--------------------------------------+ -| Windows | | X | | WinPython with OpenJPEG 1.5.1 and | -| | | | | OpenJPEG 2.0.0. 267 of 455 tests | -| | | | | pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Windows | | | X | WinPython with OpenJPEG 1.5.1 and | -| | | | | OpenJPEG svn. 307 of 455 tests | -| | | | | pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | X | | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 354 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | X | | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 315 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | X | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 379 of 461 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | X | | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 340 of 461 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | | X | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG svn. 407 of 461 | -| | | | | tests should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Mac | | | X | MacPorts with both OpenJPEG 1.5.1 | -| 10.6.8 | | | | and OpenJPEG 2.0. 355 of 461 | -| | | | | tests should pass. | -+-----------+--------+--------+-----------------------------------------------+ -| Fedora 19 | | | X | Ships with 1.5.1, openjp2 svn built, | -| | | | | too. 407 of 461 tests should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Fedora 18 | | X | | Ships with 1.5.1. 173 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Fedora 17 | | X | | Ships with 1.4.0. 171 of 456 tests | -| | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| CentOS | X | | | Ships with 1.3.0. 169 of 456 tests | -| 6.3 | | | | should pass. | -+-----------+--------+--------+--------+--------------------------------------+ -| Raspberry | | X | | Ships with 1.3.0. 171 of 456 tests | -| Pi | | | | should pass. | -| Debian 7 | | | | | -+-----------+--------+--------+--------+--------------------------------------+ - -Make release branch, qualify on all platforms. -Pylint on entire package should exceed 0.95. -pep8 should be pass cleanly. -Coverage should exceed 95%. -Make release candidate, push to Pypi, qualify in virtual environment. -Merge release branch to master, tag, push to master, push to Pypi. - From c6686e212a0584f516ebe06e09ffd9c10d839047 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 5 Aug 2013 20:39:12 -0400 Subject: [PATCH 011/122] pep8 work #98 --- glymur/test/test_callbacks.py | 2 +- glymur/test/test_opj_suite.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index 47ec100..712dd5f 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -88,7 +88,7 @@ class TestCallbacks15(unittest.TestCase): with patch('sys.stdout', new=StringIO()) as fake_out: d = j.read(rlevel=1, verbose=True) actual = fake_out.getvalue().strip() - + regex = re.compile(r"""\[INFO\]\stile\s1\sof\s1\s+ \[INFO\]\s-\stiers-1\stook\s [0-9]+\.[0-9]+\ss\s+ diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index b6de353..c2b5f15 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -3809,7 +3809,7 @@ class TestSuiteDump(unittest.TestCase): 32, 32, 131, 2002, 2002, 1888]) self.assertEqual(c.segment[3]._exponent, [17, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, - 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) + 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) # COM: comment # Registration @@ -4596,10 +4596,10 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[7].sqcc & 0x1f, 2) # none self.assertEqual(c.segment[7]._mantissa, [1824, 1776, 1776, 1728, 1792, 1792, 1760, 1872, - 1872, 1896, 5, 5, 71, 2003, 2003, 1890]) + 1872, 1896, 5, 5, 71, 2003, 2003, 1890]) self.assertEqual(c.segment[7]._exponent, [18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 14, 14, - 14, 14, 14, 14]) + 14, 14, 14, 14]) # COM: comment # Registration @@ -5634,7 +5634,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3]._mantissa, [0] * 16) self.assertEqual(c.segment[3]._exponent, [18, 19, 19, 20, 19, 19, 20, 19, 19, 20, 19, 19, 20, - 19, 19, 20]) + 19, 19, 20]) # COM: comment # Registration From 19f5ae6a46b0d0ba50da70b8cfdd1377161bcb5a Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 5 Aug 2013 20:39:39 -0400 Subject: [PATCH 012/122] pylint work regarding rstrip arguments. closes #98 --- glymur/jp2box.py | 4 ++-- glymur/test/fixtures.py | 2 +- glymur/test/test_jp2k.py | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 149af0a..5bbe733 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1792,14 +1792,14 @@ class XMLBox(Jp2kBox): text = read_buffer.decode('utf-8') # Strip out any trailing nulls, as they can foul up XML parsing. - text = text.rstrip('\0') + text = text.rstrip(chr(0)) try: elt = ET.fromstring(text) xml = ET.ElementTree(elt) except ParseError as parse_error: msg = 'A problem was encountered while parsing an XML box:' - msg += '\n\n\t"{0}"\n\nNo XML was retrieved.' + msg += '\n\n\t"{0}"\n\nNo XML was retrieved.' msg = msg.format(str(parse_error)) warnings.warn(msg, UserWarning) xml = None diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 39b4ac5..cbfbc3b 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -57,7 +57,7 @@ def read_pgx(pgx_file): header += chr(char[0]) header = header.rstrip() - tokens = re.split('\s', header) + tokens = re.split(r'\s', header) if (tokens[1][0] == 'M') and (sys.byteorder == 'little'): swapbytes = True diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index f0db4b7..6e1e7a0 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -7,6 +7,7 @@ import struct import sys import tempfile import uuid +from xml.etree import cElementTree as ET if sys.hexversion < 0x02070000: import unittest2 as unittest @@ -623,6 +624,8 @@ class TestJp2k(unittest.TestCase): self.assertEqual(jp2k.box[3].box_id, 'xml ') self.assertEqual(jp2k.box[3].offset, 77) self.assertEqual(jp2k.box[3].length, 36) + self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), + b'this is a test') @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") def test_asoc_label_box(self): From c98737a72cb149d70dc830405fc9bad05c6333f4 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 7 Aug 2013 13:45:56 -0400 Subject: [PATCH 013/122] Suppressing warnings until metadata printing is done. Closes #96 --- glymur/jp2dump.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/glymur/jp2dump.py b/glymur/jp2dump.py index 0e751e2..82c710b 100644 --- a/glymur/jp2dump.py +++ b/glymur/jp2dump.py @@ -1,6 +1,7 @@ """ Entry point for jp2dump script. """ +import warnings from .jp2k import Jp2k @@ -15,8 +16,22 @@ def jp2dump(filename, codestream=False): codestream : optional, logical scalar Whether or not to dump codestream contents. """ - j = Jp2k(filename) - if codestream: - print(j.get_codestream(header_only=False)) - else: - print(j) + with warnings.catch_warnings(record=True) as wctx: + + # JP2 metadata can be extensive, so don't print any warnings until we + # are done with the metadata. + j = Jp2k(filename) + if codestream: + print(j.get_codestream(header_only=False)) + else: + print(j) + + # Re-emit any warnings that may have been suppressed. + if len(wctx) > 0: + print("\n") + for warning in wctx: + print("{0}:{1}: {2}: {3}".format(warning.filename, + warning.lineno, + warning.category.__name__, + warning.message)) + From cd06a3404b5dafbe098613d4b402d7e0c80cae40 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 7 Aug 2013 13:47:58 -0400 Subject: [PATCH 014/122] Was not interpolating an error message arguments properly. --- glymur/codestream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 4a5a5d2..2c24bef 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -556,8 +556,8 @@ class Codestream(object): mantissa_exponent_buffer_length = length - 4 cqcc, sqcc = struct.unpack(fmt, read_buffer) if cqcc >= self._csiz: - msg = "Invalid component number (%d), " - msg += "number of components is only %d." + msg = "Invalid component number ({0}), " + msg += "number of components is only {1}." msg = msg.format(cqcc, self._csiz) warnings.warn(msg) From 775cd6f80cccdaf538e50cbe6daf9ad2f525ebd0 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 7 Aug 2013 13:48:33 -0400 Subject: [PATCH 015/122] Some refactoring. Reviewed comments and usage of "catch_warnings" --- glymur/test/fixtures.py | 19 +++++++++++++ glymur/test/test_opj_suite.py | 43 ++++++++++------------------- glymur/test/test_opj_suite_neg.py | 12 ++------ glymur/test/test_opj_suite_write.py | 20 +------------- glymur/test/test_printing.py | 2 ++ 5 files changed, 39 insertions(+), 57 deletions(-) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index cbfbc3b..6309c3e 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -1,5 +1,6 @@ import re import sys +import warnings import numpy as np @@ -20,6 +21,24 @@ if glymur.lib.openjp2.OPENJP2 is not None: OPENJP2_IS_V2_OFFICIAL = True +msg = "Matplotlib with the PIL backend must be available in order to run the " +msg += "tests in this suite." +no_read_backend_msg = msg +try: + from PIL import Image + from matplotlib.pyplot import imread + no_read_backend = False +except: + no_read_backend = True + +def read_image(infile): + # PIL issues warnings which we do not care about, so suppress them. + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + data = imread(infile) + return data + + def mse(amat, bmat): """Mean Square Error""" diff = amat.astype(np.double) - bmat.astype(np.double) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index c2b5f15..102b145 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -66,11 +66,10 @@ class TestSuite(unittest.TestCase): def test_ETS_C0P0_p0_02_j2k(self): jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jp2k = Jp2k(jfile) with warnings.catch_warnings(): - # There's a 0xff30 marker segment. Not illegal, but we don't - # really know what to do with it. Just ignore. + # Invalid marker ID. warnings.simplefilter("ignore") - jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_02.pgx') @@ -385,11 +384,7 @@ class TestSuite(unittest.TestCase): def test_ETS_C1P0_p0_02_j2k(self): jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') - with warnings.catch_warnings(): - # There's a 0xff30 marker segment. Not illegal, but we don't - # really know what to do with it. Just ignore. - warnings.simplefilter("ignore") - jp2k = Jp2k(jfile) + jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_02_0.pgx') @@ -830,7 +825,7 @@ class TestSuite(unittest.TestCase): jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2') with self.assertRaises(IOError): with warnings.catch_warnings(): - # Library warning, invalid number of subbands. + # Invalid marker ID. warnings.simplefilter("ignore") data = Jp2k(jfile).read() self.assertTrue(True) @@ -852,7 +847,7 @@ class TestSuite(unittest.TestCase): 'input/nonregression/broken4.jp2') with self.assertRaises(IOError): with warnings.catch_warnings(): - # Library warning, invalid number of subbands. + # invalid number of subbands, bad marker ID warnings.simplefilter("ignore") data = Jp2k(jfile).read() self.assertTrue(True) @@ -1053,6 +1048,7 @@ class TestSuite(unittest.TestCase): f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' jfile = os.path.join(data_root, f) with warnings.catch_warnings(): + # Invalid number of resolutions. warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): @@ -1066,6 +1062,7 @@ class TestSuite(unittest.TestCase): 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') jfile = os.path.join(data_root, '/'.join(lst)) with warnings.catch_warnings(): + # Invalid component number. warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): @@ -1077,6 +1074,7 @@ class TestSuite(unittest.TestCase): relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' jfile = os.path.join(data_root, relpath) with warnings.catch_warnings(): + # Invalid number of tiles. warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): @@ -1088,6 +1086,7 @@ class TestSuite(unittest.TestCase): relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' jfile = os.path.join(data_root, relpath) with warnings.catch_warnings(): + # Invalid subsampling value warnings.simplefilter("ignore") with self.assertRaises(IOError): j = Jp2k(jfile).read() @@ -1220,36 +1219,28 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_p1_04_j2k_57_decode(self): jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=63) # last tile + tdata = jp2k.read(tile=63) # last tile odata = jp2k.read() np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) def test_NR_DEC_p1_04_j2k_58_decode(self): jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=63, rlevel=2) # last tile + tdata = jp2k.read(tile=63, rlevel=2) # last tile odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) def test_NR_DEC_p1_04_j2k_59_decode(self): jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=12) # 2nd row, 5th column + tdata = jp2k.read(tile=12) # 2nd row, 5th column odata = jp2k.read() np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) def test_NR_DEC_p1_04_j2k_60_decode(self): jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column + tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column odata = jp2k.read(rlevel=1) np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) @@ -1366,9 +1357,7 @@ class TestSuite(unittest.TestCase): jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=0) + tiledata = jp2k.read(tile=0) np.testing.assert_array_equal(tiledata, fulldata[0:3, 0:3]) @unittest.skip("fprintf stderr output in r2343.") @@ -1376,9 +1365,7 @@ class TestSuite(unittest.TestCase): jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=5) + tiledata = jp2k.read(tile=5) np.testing.assert_array_equal(tiledata, fulldata[3:6, 3:6]) @unittest.skip("fprintf stderr output in r2343.") diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 3dfda15..41a0b5e 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -12,13 +12,13 @@ if sys.hexversion < 0x02070000: else: import unittest -import warnings - import numpy as np import pkg_resources from glymur.lib import openjp2 as opj2 +from .fixtures import read_image + msg = "Matplotlib with the PIL backend must be available in order to run the " msg += "tests in this suite." no_read_backend_msg = msg @@ -40,14 +40,6 @@ except: raise -def read_image(infile): - # PIL issues warnings which we do not care about, so suppress them. - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - data = imread(infile) - return data - - @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") @unittest.skipIf(no_read_backend, no_read_backend_msg) diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index e5be51a..41737fd 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -13,21 +13,11 @@ if sys.hexversion < 0x02070000: else: import unittest -import warnings - import numpy as np from glymur.lib import openjp2 as opj2 -msg = "Matplotlib with the PIL backend must be available in order to run the " -msg += "tests in this suite." -no_read_backend_msg = msg -try: - from PIL import Image - from matplotlib.pyplot import imread - no_read_backend = False -except: - no_read_backend = True +from .fixtures import read_image, no_read_backend, no_read_backend_msg from glymur import Jp2k import glymur @@ -40,14 +30,6 @@ except: raise -def read_image(infile): - # PIL issues warnings which we do not care about, so suppress them. - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - data = imread(infile) - return data - - @unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 79a12e1..50babe2 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1,6 +1,7 @@ #pylint: disable-all import os import pkg_resources +import re import struct import sys import tempfile @@ -1026,5 +1027,6 @@ class TestPrinting(unittest.TestCase): self.assertEqual(actual, expected) + if __name__ == "__main__": unittest.main() From e95cc30ef45c4bd025f1cfedc8a860a5d96b903f Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 7 Aug 2013 16:45:52 -0400 Subject: [PATCH 016/122] pep8, pylint work, closes #96 --- glymur/jp2dump.py | 1 - glymur/jp2k.py | 6 +- glymur/test/__init__.py | 3 + glymur/test/fixtures.py | 93 +++++++++++++++++++---------- glymur/test/test_jp2k.py | 6 +- glymur/test/test_opj_suite_neg.py | 14 +---- glymur/test/test_opj_suite_write.py | 4 +- 7 files changed, 74 insertions(+), 53 deletions(-) diff --git a/glymur/jp2dump.py b/glymur/jp2dump.py index 82c710b..c0f0f7f 100644 --- a/glymur/jp2dump.py +++ b/glymur/jp2dump.py @@ -34,4 +34,3 @@ def jp2dump(filename, codestream=False): warning.lineno, warning.category.__name__, warning.message)) - diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 8dba499..ff3b92a 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -966,8 +966,10 @@ class Jp2k(Jp2kBox): dparam.nb_tile_to_decode = 1 with ExitStack() as stack: - if hasattr(_opj2.OPENJP2, 'opj_stream_create_default_file_stream_v3'): - stream = _opj2.stream_create_default_file_stream_v3(self.filename, + if hasattr(_opj2.OPENJP2, + 'opj_stream_create_default_file_stream_v3'): + filename = self.filename + stream = _opj2.stream_create_default_file_stream_v3(filename, True) stack.callback(_opj2.stream_destroy_v3, stream) else: diff --git a/glymur/test/__init__.py b/glymur/test/__init__.py index e69de29..b61a5e1 100644 --- a/glymur/test/__init__.py +++ b/glymur/test/__init__.py @@ -0,0 +1,3 @@ +""" +Test suite for glymur high-level functionality. +""" diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 6309c3e..b6ba85d 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -1,3 +1,6 @@ +""" +Test fixtures common to more than one test point. +""" import re import sys import warnings @@ -21,18 +24,22 @@ if glymur.lib.openjp2.OPENJP2 is not None: OPENJP2_IS_V2_OFFICIAL = True -msg = "Matplotlib with the PIL backend must be available in order to run the " -msg += "tests in this suite." -no_read_backend_msg = msg +NO_READ_BACKEND_MSG = "Matplotlib with the PIL backend must be available in " +NO_READ_BACKEND_MSG += "order to run the tests in this suite." + try: - from PIL import Image from matplotlib.pyplot import imread - no_read_backend = False -except: - no_read_backend = True + NO_READ_BACKEND = False +except ImportError: + NO_READ_BACKEND = True + def read_image(infile): - # PIL issues warnings which we do not care about, so suppress them. + """Read image using matplotlib backend. + + 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(): warnings.simplefilter("ignore") data = imread(infile) @@ -55,27 +62,9 @@ def peak_tolerance(amat, bmat): def read_pgx(pgx_file): """Helper function for reading the PGX comparison files. - - Open the file in ascii mode and read the header line. - Will look something like - - PG ML + 8 128 128 - PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d" """ - header = '' - with open(pgx_file, 'rb') as fptr: - while True: - char = fptr.read(1) - if char[0] == 10 or char == '\n': - pos = fptr.tell() - break - else: - if sys.hexversion < 0x03000000: - header += char - else: - header += chr(char[0]) + header, pos = read_pgx_header(pgx_file) - header = header.rstrip() tokens = re.split(r'\s', header) if (tokens[1][0] == 'M') and (sys.byteorder == 'little'): @@ -100,6 +89,28 @@ def read_pgx(pgx_file): nrows = int(tokens[4]) ncols = int(tokens[3]) + dtype = determine_pgx_datatype(signed, bitdepth) + + shape = [nrows, ncols] + + # Reopen the file in binary mode and seek to the start of the binary + # data + with open(pgx_file, 'rb') as fptr: + fptr.seek(pos) + data = np.fromfile(file=fptr, dtype=dtype).reshape(shape) + + return(data.byteswap(swapbytes)) + +def determine_pgx_datatype(signed, bitdepth): + """Determine the datatype of the PGX file. + + Parameters + ---------- + signed : bool + True if the datatype is signed, false otherwise + bitdepth : int + How many bits are used to make up an image plane. Should be 8 or 16. + """ if signed: if bitdepth <= 8: dtype = np.int8 @@ -115,12 +126,28 @@ def read_pgx(pgx_file): else: raise RuntimeError("unhandled bitdepth") - shape = [nrows, ncols] + return dtype - # Reopen the file in binary mode and seek to the start of the binary - # data +def read_pgx_header(pgx_file): + """Open the file in ascii mode (not really) and read the header line. + Will look something like + + PG ML + 8 128 128 + PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d" + """ + header = '' with open(pgx_file, 'rb') as fptr: - fptr.seek(pos) - data = np.fromfile(file=fptr, dtype=dtype).reshape(shape) + while True: + char = fptr.read(1) + if char[0] == 10 or char == '\n': + pos = fptr.tell() + break + else: + if sys.hexversion < 0x03000000: + header += char + else: + header += chr(char[0]) + + header = header.rstrip() + return header, pos - return(data.byteswap(swapbytes)) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 6e1e7a0..1371a05 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -66,7 +66,7 @@ class TestConfig(unittest.TestCase): """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 patch('glymur.lib.openjpeg.OPENJPEG', new=None): with self.assertRaises(glymur.jp2k.LibraryNotFoundError): d = glymur.Jp2k(self.jp2file).read() @@ -74,7 +74,7 @@ class TestConfig(unittest.TestCase): """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 patch('glymur.lib.openjpeg.OPENJPEG', new=None): with self.assertRaises(glymur.jp2k.LibraryNotFoundError): d = glymur.Jp2k(self.jp2file).read_bands() @@ -84,7 +84,7 @@ class TestConfig(unittest.TestCase): """ data = glymur.Jp2k(self.j2kfile).read() with patch('glymur.lib.openjp2.OPENJP2', new=None): - with patch('glymur.lib.openjpeg.OPENJPEG', new=None): + with patch('glymur.lib.openjpeg.OPENJPEG', new=None): with self.assertRaises(glymur.jp2k.LibraryNotFoundError): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: ofile = Jp2k(tfile.name, 'wb') diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 41a0b5e..f851926 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -17,17 +17,7 @@ import pkg_resources from glymur.lib import openjp2 as opj2 -from .fixtures import read_image - -msg = "Matplotlib with the PIL backend must be available in order to run the " -msg += "tests in this suite." -no_read_backend_msg = msg -try: - from PIL import Image - from matplotlib.pyplot import imread - no_read_backend = False -except: - no_read_backend = True +from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from glymur import Jp2k import glymur @@ -42,7 +32,7 @@ except: @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") -@unittest.skipIf(no_read_backend, no_read_backend_msg) +@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") class TestSuiteNegative(unittest.TestCase): diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 41737fd..766297b 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -17,7 +17,7 @@ import numpy as np from glymur.lib import openjp2 as opj2 -from .fixtures import read_image, no_read_backend, no_read_backend_msg +from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from glymur import Jp2k import glymur @@ -33,7 +33,7 @@ except: @unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") -@unittest.skipIf(no_read_backend, no_read_backend_msg) +@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") class TestSuiteWrite(unittest.TestCase): From 658b61672ccfc52be93162ee2a628686d81c9905 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 8 Aug 2013 17:37:02 -0400 Subject: [PATCH 017/122] pylint work --- glymur/jp2box.py | 202 +++++++++++++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 78 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 5bbe733..e6e811c 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -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]) @@ -1233,9 +1234,13 @@ class PaletteBox(Jp2kBox): # Need to determine bps and signed or not read_buffer = fptr.read(num_columns) - data = struct.unpack('>' + 'B' * num_columns, read_buffer) - bps = [((x & 0x07f) + 1) for x in data] - signed = [((x & 0x80) > 1) for x in data] + #data = struct.unpack('>' + 'B' * num_columns, read_buffer) + bps = [((x & 0x07f) + 1) for x in read_buffer] + signed = [((x & 0x80) > 1) for x in read_buffer] + + # Each palette component is padded out to the next largest byte. + # That means a list comprehension does this in one shot. + row_nbytes = sum([math.ceil(x/8) 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 @@ -1243,37 +1248,45 @@ class PaletteBox(Jp2kBox): # # 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) - - 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] + palette = buffer2palette(read_buffer, num_entries, num_columns, bps) 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. + """ + 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 +1447,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 +1466,73 @@ 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. From 77a601b4deb520a37eaaebeb78cd804c3e3bde15 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 8 Aug 2013 18:23:31 -0400 Subject: [PATCH 018/122] pylint work, #99 --- glymur/jp2k.py | 265 +++++++++++++++++++++++++------------------------ 1 file changed, 135 insertions(+), 130 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index ff3b92a..0d61ae1 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -582,72 +582,7 @@ class Jp2k(Jp2kBox): num_components=num_components), ColourSpecificationBox(colorspace=SRGB)] - # Check for a bad sequence of boxes. - # 1st two boxes must be 'jP ' and 'ftyp' - if boxes[0].box_id != 'jP ' or boxes[1].box_id != 'ftyp': - msg = "The first box must be the signature box and the second " - msg += "must be the file type box." - raise IOError(msg) - - # jp2c must be preceeded by jp2h - jp2h_lst = [idx for (idx, box) in enumerate(boxes) - if box.box_id == 'jp2h'] - jp2h_idx = jp2h_lst[0] - jp2c_lst = [idx for (idx, box) in enumerate(boxes) - if box.box_id == 'jp2c'] - if len(jp2c_lst) == 0: - msg = "A codestream box must be defined in the outermost " - msg += "list of boxes." - raise IOError(msg) - - jp2c_idx = jp2c_lst[0] - if jp2h_idx >= jp2c_idx: - msg = "The codestream box must be preceeded by a jp2 header box." - raise IOError(msg) - - # 1st jp2 header box must be ihdr - jp2h = boxes[jp2h_idx] - if jp2h.box[0].box_id != 'ihdr': - msg = "The first box in the jp2 header box must be the image " - msg += "header box." - raise IOError(msg) - - # colr must be present in jp2 header box. - colr_lst = [j for (j, box) in enumerate(jp2h.box) - if box.box_id == 'colr'] - if len(colr_lst) == 0: - msg = "The jp2 header box must contain a color definition box." - raise IOError(msg) - colr = jp2h.box[colr_lst[0]] - - # Any cdef box must be in the jp2 header following the image header. - cdef_lst = [j for (j, box) in enumerate(boxes) if box.box_id == 'cdef'] - if len(cdef_lst) != 0: - msg = "Any channel defintion box must be in the JP2 header " - msg += "following the image header." - raise IOError(msg) - - cdef_lst = [j for (j, box) in enumerate(jp2h.box) - if box.box_id == 'cdef'] - if len(cdef_lst) > 1: - msg = "Only one channel definition box is allowed in the " - msg += "JP2 header." - raise IOError(msg) - elif len(cdef_lst) == 1: - cdef = jp2h.box[cdef_lst[0]] - assn = cdef.association - typ = cdef.channel_type - if colr.colorspace == SRGB: - if any([chan + 1 not in assn or typ[chan] != 0 - for chan in [0, 1, 2]]): - msg = "All color channels must be defined in the " - msg += "channel definition box." - raise IOError(msg) - elif colr.colorspace == GREYSCALE: - if 0 not in typ: - msg = "All color channels must be defined in the " - msg += "channel definition box." - raise IOError(msg) + _validate_jp2_box_sequence(boxes) with open(filename, 'wb') as ofile: for box in boxes: @@ -740,6 +675,18 @@ class Jp2k(Jp2kBox): "using this functionality.") return img + def _subsampling_sanity_check(self): + """Check for differing subsample factors. + """ + codestream = self.get_codestream(header_only=True) + dxs = np.array(codestream.segment[1].xrsiz) + dys = np.array(codestream.segment[1].yrsiz) + if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): + msg = "Components must all have the same subsampling factors " + msg += "to use this method. Please consider using OPENJP2 and " + msg += "the read_bands method instead." + raise RuntimeError(msg) + def _read_openjpeg(self, rlevel=0, verbose=False): """Read a JPEG 2000 image using libopenjpeg. @@ -761,15 +708,7 @@ class Jp2k(Jp2kBox): RuntimeError If the image has differing subsample factors. """ - # Check for differing subsample factors. - codestream = self.get_codestream(header_only=True) - dxs = np.array(codestream.segment[1].xrsiz) - dys = np.array(codestream.segment[1].yrsiz) - if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): - msg = "Components must all have the same subsampling factors " - msg += "to use this method with OpenJPEG 1.5.1. Please consider " - msg += "using OPENJP2 instead." - raise RuntimeError(msg) + self._subsampling_sanity_check() with ExitStack() as stack: # Set decoding parameters. @@ -808,20 +747,7 @@ class Jp2k(Jp2kBox): ncomps = image.contents.numcomps component = image.contents.comps[0] - if component.sgnd: - if component.prec <= 8: - dtype = np.int8 - elif component.prec <= 16: - dtype = np.int16 - else: - raise RuntimeError("Unhandled precision, datatype") - else: - if component.prec <= 8: - dtype = np.uint8 - elif component.prec <= 16: - dtype = np.uint16 - else: - raise RuntimeError("Unhandled precision, datatype") + dtype = component2dtype(component) nrows = image.contents.comps[0].h ncols = image.contents.comps[0].w @@ -833,12 +759,7 @@ class Jp2k(Jp2kBox): nrows = component.h ncols = component.w - if nrows == 0 or ncols == 0: - # Letting this situation continue would segfault - # Python. - msg = "Component {0} has dimensions {1} x {2}" - msg = msg.format(k, nrows, ncols) - raise IOError(msg) + _validate_nonzero_image_size(nrows, ncols, k) addr = ctypes.addressof(component.data.contents) with warnings.catch_warnings(): @@ -884,13 +805,7 @@ class Jp2k(Jp2kBox): RuntimeError If the image has differing subsample factors. """ - # Check for differing subsample factors. - codestream = self.get_codestream(header_only=True) - dxs = np.array(codestream.segment[1].xrsiz) - dys = np.array(codestream.segment[1].yrsiz) - if np.any(dxs - dxs[0]) or np.any(dys - dys[0]): - msg = "Components must all have the same subsampling factors." - raise RuntimeError(msg) + self._subsampling_sanity_check() img_array = self._read_common(rlevel=rlevel, layer=layer, @@ -948,14 +863,10 @@ class Jp2k(Jp2kBox): dparam.cp_reduce = rlevel if area is not None: - if area[0] < 0 or area[1] < 0: - msg = "Upper left corner coordinates must be nonnegative: {0}" - msg = msg.format(area) - raise IOError(msg) - if area[2] <= 0 or area[3] <= 0: - msg = "Lower right corner coordinates must be positive: {0}" - msg = msg.format(area) - raise IOError(msg) + if area[0] < 0 or area[1] < 0 or area[2] <= 0 or area[3] <= 0: + msg = "Upper left corner coordinates must be nonnegative and " + msg += "lower right corner coordinates must be positive: {0}" + raise IOError(msg.format(area)) dparam.DA_y0 = area[0] dparam.DA_x0 = area[1] dparam.DA_y1 = area[2] @@ -1001,20 +912,7 @@ class Jp2k(Jp2kBox): _opj2.end_decompress(codec, stream) component = image.contents.comps[0] - if component.sgnd: - if component.prec <= 8: - dtype = np.int8 - elif component.prec <= 16: - dtype = np.int16 - else: - raise RuntimeError("Unhandled precision, datatype") - else: - if component.prec <= 8: - dtype = np.uint8 - elif component.prec <= 16: - dtype = np.uint16 - else: - raise RuntimeError("Unhandled precision, datatype") + dtype = component2dtype(component) if as_bands: data = [] @@ -1029,12 +927,7 @@ class Jp2k(Jp2kBox): nrows = component.h ncols = component.w - if nrows == 0 or ncols == 0: - # Letting this situation continue would segfault - # Python. - msg = "Component {0} has dimensions {1} x {2}" - msg = msg.format(k, nrows, ncols) - raise IOError(msg) + _validate_nonzero_image_size(nrows, ncols, k) addr = ctypes.addressof(component.data.contents) with warnings.catch_warnings(): @@ -1165,3 +1058,115 @@ class Jp2k(Jp2kBox): header_only=header_only) return codestream + +def component2dtype(component): + """Take an OpenJPEG component structure and determine the numpy datatype. + + Parameters + ---------- + component : ctypes pointer to ImageCompType (image_comp_t) + single image component structure. + + Returns + ------- + dtype : builtins.type + numpy datatype to be used to construct an image array. + """ + if component.sgnd: + if component.prec <= 8: + dtype = np.int8 + elif component.prec <= 16: + dtype = np.int16 + else: + raise RuntimeError("Unhandled precision, datatype") + else: + if component.prec <= 8: + dtype = np.uint8 + elif component.prec <= 16: + dtype = np.uint16 + else: + raise RuntimeError("Unhandled precision, datatype") + + return dtype + + +def _validate_nonzero_image_size(nrows, ncols, component_index): + """The image cannot have area of zero. + """ + if nrows == 0 or ncols == 0: + # Letting this situation continue would segfault Python. + msg = "Component {0} has dimensions {1} x {2}" + msg = msg.format(component_index, nrows, ncols) + raise IOError(msg) + +def _validate_jp2_box_sequence(boxes): + """Run through series of tests for JP2 box legality. + + This is non-exhaustive. + """ + # Check for a bad sequence of boxes. + # 1st two boxes must be 'jP ' and 'ftyp' + if boxes[0].box_id != 'jP ' or boxes[1].box_id != 'ftyp': + msg = "The first box must be the signature box and the second " + msg += "must be the file type box." + raise IOError(msg) + + # jp2c must be preceeded by jp2h + jp2h_lst = [idx for (idx, box) in enumerate(boxes) + if box.box_id == 'jp2h'] + jp2h_idx = jp2h_lst[0] + jp2c_lst = [idx for (idx, box) in enumerate(boxes) + if box.box_id == 'jp2c'] + if len(jp2c_lst) == 0: + msg = "A codestream box must be defined in the outermost " + msg += "list of boxes." + raise IOError(msg) + + jp2c_idx = jp2c_lst[0] + if jp2h_idx >= jp2c_idx: + msg = "The codestream box must be preceeded by a jp2 header box." + raise IOError(msg) + + # 1st jp2 header box must be ihdr + jp2h = boxes[jp2h_idx] + if jp2h.box[0].box_id != 'ihdr': + msg = "The first box in the jp2 header box must be the image " + msg += "header box." + raise IOError(msg) + + # colr must be present in jp2 header box. + colr_lst = [j for (j, box) in enumerate(jp2h.box) + if box.box_id == 'colr'] + if len(colr_lst) == 0: + msg = "The jp2 header box must contain a color definition box." + raise IOError(msg) + colr = jp2h.box[colr_lst[0]] + + # Any cdef box must be in the jp2 header following the image header. + cdef_lst = [j for (j, box) in enumerate(boxes) if box.box_id == 'cdef'] + if len(cdef_lst) != 0: + msg = "Any channel defintion box must be in the JP2 header " + msg += "following the image header." + raise IOError(msg) + + cdef_lst = [j for (j, box) in enumerate(jp2h.box) + if box.box_id == 'cdef'] + if len(cdef_lst) > 1: + msg = "Only one channel definition box is allowed in the " + msg += "JP2 header." + raise IOError(msg) + elif len(cdef_lst) == 1: + cdef = jp2h.box[cdef_lst[0]] + if colr.colorspace == SRGB: + if any([chan + 1 not in cdef.association + or cdef.channel_type[chan] != 0 + for chan in [0, 1, 2]]): + msg = "All color channels must be defined in the " + msg += "channel definition box." + raise IOError(msg) + elif colr.colorspace == GREYSCALE: + if 0 not in cdef.channel_type: + msg = "All color channels must be defined in the " + msg += "channel definition box." + raise IOError(msg) + From bf24e9b280b3b962ed845dd1e1b9439cdd7266fd Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 9 Aug 2013 23:11:03 -0400 Subject: [PATCH 019/122] pylint work, #99 --- glymur/jp2box.py | 8 +- glymur/jp2k.py | 689 ++++++++++++++++++++++++++++------------------- 2 files changed, 417 insertions(+), 280 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index e6e811c..56021b9 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1234,13 +1234,13 @@ class PaletteBox(Jp2kBox): # Need to determine bps and signed or not read_buffer = fptr.read(num_columns) - #data = struct.unpack('>' + 'B' * num_columns, read_buffer) - bps = [((x & 0x07f) + 1) for x in read_buffer] - signed = [((x & 0x80) > 1) for x in read_buffer] + data = struct.unpack('>' + 'B' * num_columns, read_buffer) + 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([math.ceil(x/8) for x in bps]) + 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 diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 0d61ae1..0785178 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -187,36 +187,147 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) - def _validate_write_parameters(self, img_array, code_block_size, - precinct_sizes, cratios, psnr, colorspace, - codec_fmt): - """Check that the input parameters to the write function are valid. + #def _populate_cparams(self, cbsize, cratios, eph, grid_offset, modesw, + # numres, prog, psnr, psizes, sop, subsam, tilesize): + def _populate_cparams(self, **kwargs): + """Populate compression parameters structure from input arguments. + Parameters + ---------- + cbsize : tuple, optional + Code block size (DY, DX). + cratios : iterable + Compression ratios for successive layers. + eph : bool, optional + If true, write SOP marker after each header packet. + grid_offset : tuple, optional + Offset (DY, DX) of the origin of the image in the reference grid. + mct : bool, optional + Specifies usage of the multi component transform. If not + specified, defaults to True if the colorspace is RGB. + modesw : int, optional + Mode switch. + 1 = BYPASS(LAZY) + 2 = RESET + 4 = RESTART(TERMALL) + 8 = VSC + 16 = ERTERM(SEGTERM) + 32 = SEGMARK(SEGSYM) + numres : int, optional + Number of resolutions. + prog : str, optional + Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". + psnr : iterable, optional + Different PSNR for successive layers. + psizes : list, optional + List of precinct sizes. Each precinct size tuple is defined in + (height x width). + sop : bool, optional + If true, write SOP marker before each packet. + subsam : tuple, optional + Subsampling factors (dy, dx). + tilesize : tuple, optional + Numeric tuple specifying tile size in terms of (numrows, numcols), + not (X, Y). + + Returns + ------- + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + """ + + cparams = _opj2.set_default_encoder_parameters() + + outfile = self.filename.encode() + num_pad_bytes = _opj2.PATH_LEN - len(outfile) + outfile += b'0' * num_pad_bytes + cparams.outfile = outfile + + if self.filename[-4:].lower() == '.jp2': + cparams.codec_fmt = _opj2.CODEC_JP2 + else: + cparams.codec_fmt = _opj2.CODEC_J2K + + # Set defaults to lossless to begin. + cparams.tcp_rates[0] = 0 + cparams.tcp_numlayers = 1 + cparams.cp_disto_alloc = 1 + + if 'cbsize' in kwargs: + cparams.cblockw_init = kwargs['cbsize'][1] + cparams.cblockh_init = kwargs['cbsize'][0] + + if 'cratios' in kwargs: + cparams.tcp_numlayers = len(kwargs['cratios']) + for j, cratio in enumerate(kwargs['cratios']): + cparams.tcp_rates[j] = cratio + cparams.cp_disto_alloc = 1 + + if 'eph' in kwargs: + cparams.csty |= 0x04 + + if 'grid_offset' in kwargs: + cparams.image_offset_x0 = kwargs['grid_offset'][1] + cparams.image_offset_y0 = kwargs['grid_offset'][0] + + if 'modesw' in kwargs: + for shift in range(6): + power_of_two = 1 << shift + if kwargs['modesw'] & power_of_two: + cparams.mode |= power_of_two + + if 'numres' in kwargs: + cparams.numresolution = kwargs['numres'] + + if 'prog' in kwargs: + prog = kwargs['prog'].upper() + cparams.prog_order = PROGRESSION_ORDER[prog] + + if 'psnr' in kwargs: + cparams.tcp_numlayers = len(kwargs['psnr']) + for j, snr_layer in enumerate(kwargs['psnr']): + cparams.tcp_distoratio[j] = snr_layer + cparams.cp_fixed_quality = 1 + + if 'psizes' in kwargs: + for j, (prch, prcw) in enumerate(kwargs['psizes']): + cparams.prcw_init[j] = prcw + cparams.prch_init[j] = prch + cparams.csty |= 0x01 + cparams.res_spec = len(kwargs['psizes']) + + if 'sop' in kwargs: + cparams.csty |= 0x02 + + if 'subsam' in kwargs: + cparams.subsampling_dy = kwargs['subsam'][0] + cparams.subsampling_dx = kwargs['subsam'][1] + + if 'tilesize' in kwargs: + cparams.cp_tdx = kwargs['tilesize'][1] + cparams.cp_tdy = kwargs['tilesize'][0] + cparams.tile_size_on = _opj2.TRUE + + return cparams + + def _validate_compression_params(self, img_array, cparams): + """Check that the compression parameters are valid. + Parameters ---------- img_array : ndarray Image data to be written to file. - code_block_size : tuple - Code block size (DY, DX). - precinct_sizes : list - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - cratios : iterable - Compression ratios for successive layers. - psnr : iterable - Different PSNR for successive layers. - mct : bool - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - colorspace : str, optional - Either 'rgb' or 'gray'. - codec_fmt : int - Are we writing a JP2 file or a J2K file? + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. """ - # Validate code block size and precinct sizes. - if code_block_size is not None: - width = code_block_size[1] - height = code_block_size[0] + + # Code block size + code_block_specified = False + if cparams.cblockw_init != 0 and cparams.cblockh_init != 0: + # These fields ARE zero if uninitialized. + width = cparams.cblockw_init + height = cparams.cblockh_init + code_block_specified = True if height * width > 4096 or height < 4 or width < 4: msg = "Code block area cannot exceed 4096. " msg += "Code block height and width must be larger than 4." @@ -226,12 +337,16 @@ class Jp2k(Jp2kBox): msg = "Bad code block size ({0}, {1}), " msg += "must be powers of 2." raise IOError(msg.format(height, width)) - - if precinct_sizes is not None: - for j, (prch, prcw) in enumerate(precinct_sizes): - if j == 0 and code_block_size is not None: - cblkh, cblkw = code_block_size - if cblkh * 2 > prch or cblkw * 2 > prcw: + + # Precinct size + if cparams.res_spec != 0: + # precinct size was not specified if this field is zero. + for j in range(cparams.res_spec): + prch = cparams.prch_init[j] + prcw = cparams.prcw_init[j] + if j == 0 and code_block_specified: + height, width = cparams.cblockh_init, cparams.cblockw_init + if height * 2 > prch or width * 2 > prcw: msg = "Highest Resolution precinct size must be at " msg += "least twice that of the code block dimensions." raise IOError(msg) @@ -240,16 +355,12 @@ class Jp2k(Jp2kBox): msg = "Bad precinct sizes ({0}, {1}), " msg += "must be powers of 2." raise IOError(msg.format(prch, prcw)) - - if cratios is not None and psnr is not None: - msg = "Cannot specify cratios and psnr together." - raise IOError(msg) - + # What would the point of 1D images be? if img_array.ndim == 1 or img_array.ndim > 3: msg = "{0}D imagery is not allowed.".format(img_array.ndim) raise IOError(msg) - + if _OPENJP2_IS_OFFICIAL_V2: if (((img_array.ndim != 2) and (img_array.shape[2] != 1 and img_array.shape[2] != 3))): @@ -258,28 +369,110 @@ class Jp2k(Jp2kBox): msg += "the OpenJPEG library version is the official 2.0.0 " msg += "release." raise IOError(msg) - - if colorspace is not None: - if codec_fmt == _opj2.CODEC_J2K: - msg = 'Do not specify a colorspace when writing a raw ' - msg += 'codestream.' - raise IOError(msg) - if colorspace.lower() not in ('rgb', 'grey', 'gray'): - msg = 'Invalid colorspace "{0}"'.format(colorspace) - raise IOError(msg) - elif colorspace.lower() == 'rgb' and img_array.shape[2] < 3: - msg = 'RGB colorspace requires at least 3 components.' - raise IOError(msg) - + if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: msg = "Only uint8 and uint16 images are currently supported." raise RuntimeError(msg) + + def _set_multi_component_transform(self, colorspace, cparams, mct=None): + """Set multi component transform usage. - # pylint: disable-msg=W0221 - def write(self, img_array, cratios=None, eph=False, psnr=None, numres=None, - cbsize=None, psizes=None, grid_offset=None, sop=False, - subsam=None, tilesize=None, prog=None, modesw=None, - colorspace=None, verbose=False, mct=None): + Parameters + ---------- + colorspace : int + Either CLRSPC_SRGB or CLRSPC_GRAY + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + mct : bool, optional + Specifies usage of the multi component transform. If not + specified, defaults to True if the colorspace is RGB. + """ + if mct is None: + # If the multi component transform was not specified, we infer + # that it should be used if the color space is RGB. + if colorspace == _opj2.CLRSPC_SRGB: + cparams.tcp_mct = 1 + else: + cparams.tcp_mct = 0 + else: + # MCT was specified. Does it make sense? + if mct and colorspace == _opj2.CLRSPC_GRAY: + # Cannot check for this in the validate routine, as we need + # to know what the target colorspace has been determined to be. + msg = "Cannot specify usage of the multi component transform " + msg += "if the colorspace is gray." + raise IOError(msg) + cparams.tcp_mct = 1 if mct else 0 + + def _process_write_inputs(self, img_array, colorspace=None, **kwargs): + """Directs processing of write method arguments. + + It's somewhat awkward to process all the kwargs arguments at once. + The "colorspace" is not a parameter that gets processed into the + compression parameters structure, and it unfortunately must be handled + in the middle of the compression parameter processing. + + Parameters + ---------- + + Returns + ------- + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + colorspace : int + Either CLRSPC_SRGB or CLRSPC_GRAY + """ + + if 'cratios' in kwargs and 'psnr' in kwargs: + msg = "Cannot specify cratios and psnr together." + raise IOError(msg) + + cparams = self._populate_cparams(**kwargs) + self._validate_compression_params(img_array, cparams) + + colorspace = _unpack_colorspace(colorspace, img_array, cparams) + + try: + mct = kwargs['mct'] + except KeyError: + mct = None + self._set_multi_component_transform(colorspace, cparams, mct) + + return cparams, colorspace + + def _populate_image_struct(self, cparams, image, imgdata): + """Populates image struct needed for compression. + + Parameters + ---------- + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + image : ImageType(ctypes.Structure) + Corresponds to image_t type in openjp2 headers. + imgarray : ndarray + Image data to be written to file. + """ + + numrows, numcols, num_comps = imgdata.shape + + # set image offset and reference grid + image.contents.x0 = cparams.image_offset_x0 + image.contents.y0 = cparams.image_offset_y0 + image.contents.x1 = (image.contents.x0 + + (numcols - 1) * cparams.subsampling_dx + 1) + image.contents.y1 = (image.contents.y0 + + (numrows - 1) * cparams.subsampling_dy + 1) + + # Stage the image data to the openjpeg data structure. + for k in range(0, num_comps): + layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) + dest = image.contents.comps[k].data + src = layer.ctypes.data + ctypes.memmove(dest, src, layer.nbytes) + + return image + + def write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the various parameters follows that of OpenJPEG's opj_compress utility. @@ -290,11 +483,6 @@ class Jp2k(Jp2kBox): ---------- img_array : ndarray Image data to be written to file. - callbacks : bool, optional - If true, enable default info handler such that INFO messages - produced by the OpenJPEG library are output to the console. By - default, OpenJPEG warning and error messages are captured by - Python's own warning and error mechanisms. cbsize : tuple, optional Code block size (DY, DX). colorspace : str, optional @@ -356,128 +544,17 @@ class Jp2k(Jp2kBox): "installed before using this " "functionality.") - if self.filename[-4:].lower() == '.jp2': - codec_fmt = _opj2.CODEC_JP2 - else: - codec_fmt = _opj2.CODEC_J2K - - self._validate_write_parameters(img_array, cbsize, psizes, cratios, - psnr, colorspace, codec_fmt) - - cparams = _opj2.set_default_encoder_parameters() - - outfile = self.filename.encode() - num_pad_bytes = _opj2.PATH_LEN - len(outfile) - outfile += b'0' * num_pad_bytes - cparams.outfile = outfile - - cparams.cod_format = codec_fmt - - # Set defaults to lossless to begin. - cparams.tcp_rates[0] = 0 - cparams.tcp_numlayers = 1 - cparams.cp_disto_alloc = 1 - - if cbsize is not None: - width = cbsize[1] - height = cbsize[0] - cparams.cblockw_init = width - cparams.cblockh_init = height - - if cratios is not None: - cparams.tcp_numlayers = len(cratios) - for j, cratio in enumerate(cratios): - cparams.tcp_rates[j] = cratio - cparams.cp_disto_alloc = 1 - - if eph: - cparams.csty |= 0x04 - - if grid_offset is not None: - cparams.image_offset_x0 = grid_offset[1] - cparams.image_offset_y0 = grid_offset[0] - - if modesw is not None: - for shift in range(6): - power_of_two = 1 << shift - if modesw & power_of_two: - cparams.mode |= power_of_two - - if numres is not None: - cparams.numresolution = numres - - if prog is not None: - prog = prog.upper() - cparams.prog_order = PROGRESSION_ORDER[prog] - - if psnr is not None: - cparams.tcp_numlayers = len(psnr) - for j, snr_layer in enumerate(psnr): - cparams.tcp_distoratio[j] = snr_layer - cparams.cp_fixed_quality = 1 - - if psizes is not None: - for j, (prch, prcw) in enumerate(psizes): - cparams.prcw_init[j] = prcw - cparams.prch_init[j] = prch - cparams.csty |= 0x01 - cparams.res_spec = len(psizes) - - if sop: - cparams.csty |= 0x02 - - if subsam is not None: - cparams.subsampling_dy = subsam[0] - cparams.subsampling_dx = subsam[1] - - if tilesize is not None: - cparams.cp_tdx = tilesize[1] - cparams.cp_tdy = tilesize[0] - cparams.tile_size_on = _opj2.TRUE + cparams, colorspace = self._process_write_inputs(img_array, **kwargs) if img_array.ndim == 2: - # Force it to be 3D. Just makes things easier later on. + # Force the image to be 3D. Just makes things easier later on. numrows, numcols = img_array.shape img_array = img_array.reshape(numrows, numcols, 1) + # Only two precisions are possible. + comp_prec = 8 if img_array.dtype == np.uint8 else 16 + numrows, numcols, num_comps = img_array.shape - - if colorspace is None: - # Must infer the colorspace from the image dimensions. - if img_array.shape[2] == 1 or img_array.shape[2] == 2: - # A single channel image or an image with two channels is going - # to be greyscale. - colorspace = _opj2.CLRSPC_GRAY - else: - # Anything else must be RGB, right? - colorspace = _opj2.CLRSPC_SRGB - else: - # Turn the colorspace from a string to the enumerated value that - # the library expects. - colorspace = _COLORSPACE_MAP[colorspace.lower()] - - if mct is None: - # If the multi component transform was not specified, we infer - # that it should be used if the color space is RGB. - if colorspace == _opj2.CLRSPC_SRGB: - cparams.tcp_mct = 1 - else: - cparams.tcp_mct = 0 - else: - if mct and colorspace == _opj2.CLRSPC_GRAY: - # Cannot check for this in the validate routine, as we need - # to know what the target colorspace has been determined to be. - msg = "Cannot specify usage of the multi component transform " - msg += "if the colorspace is gray." - raise IOError(msg) - cparams.tcp_mct = 1 if mct else 0 - - if img_array.dtype == np.uint8: - comp_prec = 8 - else: - # We already know it cannot be anything else than uint16. - comp_prec = 16 - comptparms = (_opj2.ImageComptParmType * num_comps)() for j in range(num_comps): comptparms[j].dx = cparams.subsampling_dx @@ -491,37 +568,22 @@ class Jp2k(Jp2kBox): comptparms[j].sgnd = 0 image = _opj2.image_create(comptparms, colorspace) + self._populate_image_struct(cparams, image, img_array) - # set image offset and reference grid - image.contents.x0 = cparams.image_offset_x0 - image.contents.y0 = cparams.image_offset_y0 - image.contents.x1 = (image.contents.x0 + - (numcols - 1) * cparams.subsampling_dx + 1) - image.contents.y1 = (image.contents.y0 + - (numrows - 1) * cparams.subsampling_dy + 1) - - # Stage the image data to the openjpeg data structure. - for k in range(0, num_comps): - layer = np.ascontiguousarray(img_array[:, :, k], dtype=np.int32) - dest = image.contents.comps[k].data - src = layer.ctypes.data - ctypes.memmove(dest, src, layer.nbytes) - - codec = _opj2.create_compress(codec_fmt) - - if verbose: - _opj2.set_info_handler(codec, _INFO_CALLBACK) - else: - _opj2.set_info_handler(codec, None) + codec = _opj2.create_compress(cparams.codec_fmt) + info_handler = _INFO_CALLBACK if verbose else None + _opj2.set_info_handler(codec, info_handler) _opj2.set_warning_handler(codec, _WARNING_CALLBACK) _opj2.set_error_handler(codec, _ERROR_CALLBACK) + _opj2.setup_encoder(codec, cparams, image) if _OPENJP2_IS_OFFICIAL_V2: fptr = _libc.fopen(self.filename, 'wb') strm = _opj2.stream_create_default_file_stream(fptr, False) else: + # This routine introduced in 2.0 devel series. strm = _opj2.stream_create_default_file_stream_v3(self.filename, False) @@ -534,6 +596,7 @@ class Jp2k(Jp2kBox): _opj2.stream_destroy(strm) _libc.fclose(fptr) else: + # This routine introduced in 2.0 devel series. _opj2.stream_destroy_v3(strm) _opj2.destroy_codec(codec) @@ -745,32 +808,11 @@ class Jp2k(Jp2kBox): stack.callback(_opj.destroy_decompress, dinfo) stack.callback(_opj.cio_close, cio) - ncomps = image.contents.numcomps - component = image.contents.comps[0] - dtype = component2dtype(component) - - nrows = image.contents.comps[0].h - ncols = image.contents.comps[0].w - ncomps = image.contents.numcomps - data = np.zeros((nrows, ncols, ncomps), dtype) - - for k in range(image.contents.numcomps): - component = image.contents.comps[k] - nrows = component.h - ncols = component.w - - _validate_nonzero_image_size(nrows, ncols, k) - - addr = ctypes.addressof(component.data.contents) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - nelts = nrows * ncols - band = np.ctypeslib.as_array( - (ctypes.c_int32 * nelts).from_address(addr)) - data[:, :, k] = np.reshape(band.astype(dtype), - (nrows, ncols)) + data = extract_image_cube(image) if data.shape[2] == 1: + # The third dimension has just a single layer. Make the image + # data 2D instead of 3D. data = data.view() data.shape = data.shape[0:2] @@ -820,6 +862,59 @@ class Jp2k(Jp2kBox): return img_array + def _populate_dparam(self, layer, rlevel, area, tile): + """Populate decompression structure with appropriate input parameters. + + Parameters + ---------- + layer : int, optional + Number of quality layer to decode. + rlevel : int, optional + Factor by which to rlevel output resolution. + area : tuple, optional + Specifies decoding image area, + (first_row, first_col, last_row, last_col) + tile : int, optional + Number of tile to decode. + + Returns + ------- + dparam : DecompressionParametersType (ctypes) + Corresponds to openjp2 decompression parameters structure. + """ + dparam = _opj2.set_default_decoder_parameters() + + infile = self.filename.encode() + nelts = _opj2.PATH_LEN - len(infile) + infile += b'0' * nelts + dparam.infile = infile + + dparam.decod_format = self._codec_format + + dparam.cp_layer = layer + + if rlevel == -1: + # Get the lowest resolution thumbnail. + codestream = self.get_codestream() + rlevel = codestream.segment[2].spcod[4] + dparam.cp_reduce = rlevel + + if area is not None: + if area[0] < 0 or area[1] < 0 or area[2] <= 0 or area[3] <= 0: + msg = "Upper left corner coordinates must be nonnegative and " + msg += "lower right corner coordinates must be positive: {0}" + raise IOError(msg.format(area)) + dparam.DA_y0 = area[0] + dparam.DA_x0 = area[1] + dparam.DA_y1 = area[2] + dparam.DA_x1 = area[3] + + if tile is not None: + dparam.tile_index = tile + dparam.nb_tile_to_decode = 1 + + return dparam + def _read_common(self, rlevel=0, layer=0, area=None, tile=None, verbose=False, as_bands=False): """Read a JPEG 2000 image. @@ -845,36 +940,7 @@ class Jp2k(Jp2kBox): img_array : ndarray The individual image components or a single array. """ - dparam = _opj2.set_default_decoder_parameters() - - infile = self.filename.encode() - nelts = _opj2.PATH_LEN - len(infile) - infile += b'0' * nelts - dparam.infile = infile - - dparam.decod_format = self._codec_format - - dparam.cp_layer = layer - - if rlevel == -1: - # Get the lowest resolution thumbnail. - codestream = self.get_codestream() - rlevel = codestream.segment[2].spcod[4] - - dparam.cp_reduce = rlevel - if area is not None: - if area[0] < 0 or area[1] < 0 or area[2] <= 0 or area[3] <= 0: - msg = "Upper left corner coordinates must be nonnegative and " - msg += "lower right corner coordinates must be positive: {0}" - raise IOError(msg.format(area)) - dparam.DA_y0 = area[0] - dparam.DA_x0 = area[1] - dparam.DA_y1 = area[2] - dparam.DA_x1 = area[3] - - if tile is not None: - dparam.tile_index = tile - dparam.nb_tile_to_decode = 1 + dparam = self._populate_dparam(layer, rlevel, area, tile) with ExitStack() as stack: if hasattr(_opj2.OPENJP2, @@ -911,34 +977,10 @@ class Jp2k(Jp2kBox): _opj2.decode(codec, stream, image) _opj2.end_decompress(codec, stream) - component = image.contents.comps[0] - dtype = component2dtype(component) - if as_bands: - data = [] + data = extract_image_bands(image) else: - nrows = image.contents.comps[0].h - ncols = image.contents.comps[0].w - ncomps = image.contents.numcomps - data = np.zeros((nrows, ncols, ncomps), dtype) - - for k in range(image.contents.numcomps): - component = image.contents.comps[k] - nrows = component.h - ncols = component.w - - _validate_nonzero_image_size(nrows, ncols, k) - - addr = ctypes.addressof(component.data.contents) - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - band = np.ctypeslib.as_array( - (ctypes.c_int32 * nrows * ncols).from_address(addr)) - if as_bands: - data.append(np.reshape(band.astype(dtype), (nrows, ncols))) - else: - data[:, :, k] = np.reshape(band.astype(dtype), - (nrows, ncols)) + data = extract_image_cube(image) return data @@ -1170,3 +1212,98 @@ def _validate_jp2_box_sequence(boxes): msg += "channel definition box." raise IOError(msg) +def extract_image_cube(image): + """Extract 3D image from openjpeg data structure. + """ + ncomps = image.contents.numcomps + component = image.contents.comps[0] + dtype = component2dtype(component) + + nrows = component.h + ncols = component.w + data = np.zeros((nrows, ncols, ncomps), dtype) + + for k in range(image.contents.numcomps): + component = image.contents.comps[k] + nrows = component.h + ncols = component.w + + _validate_nonzero_image_size(nrows, ncols, k) + + addr = ctypes.addressof(component.data.contents) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + nelts = nrows * ncols + band = np.ctypeslib.as_array( + (ctypes.c_int32 * nelts).from_address(addr)) + data[:, :, k] = np.reshape(band.astype(dtype), (nrows, ncols)) + + return data + +def extract_image_bands(image): + """Extract unequally-sized image bands. + + This routine need only be called when subsampling differs across image + components, such as is often the case with YCbCr imagery. + """ + data = [] + for k in range(image.contents.numcomps): + component = image.contents.comps[k] + + dtype = component2dtype(component) + nrows = component.h + ncols = component.w + + _validate_nonzero_image_size(nrows, ncols, k) + + addr = ctypes.addressof(component.data.contents) + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + band = np.ctypeslib.as_array( + (ctypes.c_int32 * nrows * ncols).from_address(addr)) + data.append(np.reshape(band.astype(dtype), (nrows, ncols))) + + return data + +def _unpack_colorspace(colorspace, img_array, cparams): + """Determine the colorspace from the supplied inputs. + + Parameters + ---------- + colorspace : int + Either CLRSPC_SRGB or CLRSPC_GRAY + img_array : ndarray + Image data to be written to file. + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + """ + if colorspace is None: + # Must infer the colorspace from the image dimensions. + if img_array.ndim < 3: + # A single channel image is grayscale. + colorspace = _opj2.CLRSPC_GRAY + elif img_array.shape[2] == 1 or img_array.shape[2] == 2: + # A single channel image or an image with two channels is going + # to be greyscale. + colorspace = _opj2.CLRSPC_GRAY + else: + # Anything else must be RGB, right? + colorspace = _opj2.CLRSPC_SRGB + else: + # Supplied a string colorspace, so we must validate it. + if cparams.codec_fmt == _opj2.CODEC_J2K: + msg = 'Do not specify a colorspace when writing a raw ' + msg += 'codestream.' + raise IOError(msg) + if colorspace.lower() not in ('rgb', 'grey', 'gray'): + msg = 'Invalid colorspace "{0}"'.format(colorspace) + raise IOError(msg) + elif colorspace.lower() == 'rgb' and img_array.shape[2] < 3: + msg = 'RGB colorspace requires at least 3 components.' + raise IOError(msg) + + # Turn the colorspace from a string to the enumerated value that + # the library expects. + colorspace = _COLORSPACE_MAP[colorspace.lower()] + + return colorspace From 0eb58e4ae48a44edbea4954e18b868dcbb412bf3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 10 Aug 2013 07:12:31 -0400 Subject: [PATCH 020/122] pylint work, #99 --- glymur/jp2k.py | 54 ++++++++++++-------------------- glymur/lib/openjp2.py | 1 - glymur/lib/test/__init__.py | 4 ++- glymur/lib/test/test_openjpeg.py | 49 ++++++++++++++--------------- 4 files changed, 47 insertions(+), 61 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 0785178..75eca03 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -187,8 +187,6 @@ class Jp2k(Jp2kBox): msg += "profile if the file type box brand is 'jp2 '." warnings.warn(msg) - #def _populate_cparams(self, cbsize, cratios, eph, grid_offset, modesw, - # numres, prog, psnr, psizes, sop, subsam, tilesize): def _populate_cparams(self, **kwargs): """Populate compression parameters structure from input arguments. @@ -374,36 +372,6 @@ class Jp2k(Jp2kBox): msg = "Only uint8 and uint16 images are currently supported." raise RuntimeError(msg) - def _set_multi_component_transform(self, colorspace, cparams, mct=None): - """Set multi component transform usage. - - Parameters - ---------- - colorspace : int - Either CLRSPC_SRGB or CLRSPC_GRAY - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - """ - if mct is None: - # If the multi component transform was not specified, we infer - # that it should be used if the color space is RGB. - if colorspace == _opj2.CLRSPC_SRGB: - cparams.tcp_mct = 1 - else: - cparams.tcp_mct = 0 - else: - # MCT was specified. Does it make sense? - if mct and colorspace == _opj2.CLRSPC_GRAY: - # Cannot check for this in the validate routine, as we need - # to know what the target colorspace has been determined to be. - msg = "Cannot specify usage of the multi component transform " - msg += "if the colorspace is gray." - raise IOError(msg) - cparams.tcp_mct = 1 if mct else 0 - def _process_write_inputs(self, img_array, colorspace=None, **kwargs): """Directs processing of write method arguments. @@ -414,6 +382,10 @@ class Jp2k(Jp2kBox): Parameters ---------- + img_array : ndarray + Image data to be written to file. + colorspace : str, optional + Either 'rgb' or 'gray'. Returns ------- @@ -421,6 +393,9 @@ class Jp2k(Jp2kBox): Corresponds to cparameters_t type in openjp2 headers. colorspace : int Either CLRSPC_SRGB or CLRSPC_GRAY + mct : bool, optional + Specifies usage of the multi component transform. If not + specified, defaults to True if the colorspace is RGB. """ if 'cratios' in kwargs and 'psnr' in kwargs: @@ -434,9 +409,20 @@ class Jp2k(Jp2kBox): try: mct = kwargs['mct'] + if mct and colorspace == _opj2.CLRSPC_GRAY: + # Cannot check for this in the validate routine, as we need + # to know what the target colorspace has been determined to be. + msg = "Cannot specify usage of the multi component transform " + msg += "if the colorspace is gray." + raise IOError(msg) + cparams.tcp_mct = 1 if mct else 0 except KeyError: - mct = None - self._set_multi_component_transform(colorspace, cparams, mct) + # If the multi component transform was not specified, we infer + # that it should be used if the color space is RGB. + if colorspace == _opj2.CLRSPC_SRGB: + cparams.tcp_mct = 1 + else: + cparams.tcp_mct = 0 return cparams, colorspace diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 66a3cba..468bb51 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -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) diff --git a/glymur/lib/test/__init__.py b/glymur/lib/test/__init__.py index 5aea3ab..47a3d86 100644 --- a/glymur/lib/test/__init__.py +++ b/glymur/lib/test/__init__.py @@ -1 +1,3 @@ -#from .test_openjp2 import TestOpenJP2 as openjp2 +""" +Test suite for openjp2, openjpeg low-level functionality. +""" diff --git a/glymur/lib/test/test_openjpeg.py b/glymur/lib/test/test_openjpeg.py index 3dc7628..5363a1f 100644 --- a/glymur/lib/test/test_openjpeg.py +++ b/glymur/lib/test/test_openjpeg.py @@ -1,4 +1,6 @@ -#pylint: disable-all +""" +Tests for OpenJPEG module. +""" import ctypes import re import sys @@ -10,43 +12,40 @@ else: import glymur +# pylint: disable=E1101,R0904 -@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) From d7a06f29edb6c88fe79a5a8b9b225e9ae8cee095 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 10 Aug 2013 13:04:58 -0400 Subject: [PATCH 021/122] pylint work, #99 --- glymur/lib/test/test_openjp2.py | 538 +++++++++++++++++--------------- 1 file changed, 284 insertions(+), 254 deletions(-) diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index 710f265..13c5975 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -1,9 +1,10 @@ -#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 import os -import pkg_resources -import shutil -import struct import sys import tempfile @@ -15,28 +16,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 +53,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 +63,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 +102,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 +142,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() From 8a8b4cb0ad21d0c63dbbc903ff2ea4a2ac9262fc Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 10 Aug 2013 13:05:10 -0400 Subject: [PATCH 022/122] pep8 work, #99 --- glymur/jp2box.py | 24 ++++-- glymur/jp2k.py | 185 +++++++++++++++++++++------------------- glymur/lib/__init__.py | 4 +- glymur/test/fixtures.py | 7 +- 4 files changed, 120 insertions(+), 100 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 56021b9..6d5c3ee 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1249,14 +1249,28 @@ class PaletteBox(Jp2kBox): # This means that we store the palette as a list of 1D arrays, # which reverses the usual indexing scheme. read_buffer = fptr.read(num_entries * row_nbytes) - palette = buffer2palette(read_buffer, num_entries, num_columns, bps) + palette = _buffer2palette(read_buffer, num_entries, num_columns, bps) - 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): + +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 = [] @@ -1278,7 +1292,6 @@ def buffer2palette(read_buffer, num_rows, num_cols, bps): 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) @@ -1498,6 +1511,7 @@ def _parse_standard_flag(fptr, mask_length): return standard_flag, standard_mask + def _parse_vendor_features(fptr, mask_length): """Construct vendor features, vendor mask data from the file. diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 75eca03..fade3a8 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -30,22 +30,22 @@ from .jp2box import JP2HeaderBox from .jp2box import ContiguousCodestreamBox from .jp2box import ImageHeaderBox from .jp2box import ColourSpecificationBox -from .lib import _openjpeg as _opj -from .lib import _openjp2 as _opj2 +from .lib import openjpeg as opj +from .lib import openjp2 as opj2 from .lib import c as _libc # Need to known if openjp2 library is the officially release v2.0.0 or not. _OPENJP2_IS_OFFICIAL_V2 = False -if _opj2.OPENJP2 is not None: - if _opj2.version() == '2.0.0': - if not hasattr(_opj2.OPENJP2, +if opj2.OPENJP2 is not None: + if opj2.version() == '2.0.0': + if not hasattr(opj2.OPENJP2, 'opj_stream_create_default_file_stream_v3'): _OPENJP2_IS_OFFICIAL_V2 = True -_COLORSPACE_MAP = {'rgb': _opj2.CLRSPC_SRGB, - 'gray': _opj2.CLRSPC_GRAY, - 'grey': _opj2.CLRSPC_GRAY, - 'ycc': _opj2.CLRSPC_YCC} +_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, + 'gray': opj2.CLRSPC_GRAY, + 'grey': opj2.CLRSPC_GRAY, + 'ycc': opj2.CLRSPC_YCC} # Setup the default callback handlers. See the callback functions subsection # in the ctypes section of the Python documentation for a solid explanation of @@ -56,7 +56,7 @@ _CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) def _default_error_handler(msg, _): """Default error handler callback for openjpeg library.""" msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) - _opj2.set_error_message(msg) + opj2.set_error_message(msg) def _default_info_handler(msg, _): @@ -143,12 +143,12 @@ class Jp2k(Jp2kBox): read_buffer = fptr.read(2) signature, = struct.unpack('>H', read_buffer) if signature == 0xff4f: - self._codec_format = _opj2.CODEC_J2K + self._codec_format = opj2.CODEC_J2K # That's it, we're done. The codestream object is only # produced upon explicit request. return - self._codec_format = _opj2.CODEC_JP2 + self._codec_format = opj2.CODEC_JP2 # Should be JP2. # First 4 bytes should be 12, the length of the 'jP ' box. @@ -234,17 +234,17 @@ class Jp2k(Jp2kBox): Corresponds to cparameters_t type in openjp2 headers. """ - cparams = _opj2.set_default_encoder_parameters() + cparams = opj2.set_default_encoder_parameters() outfile = self.filename.encode() - num_pad_bytes = _opj2.PATH_LEN - len(outfile) + num_pad_bytes = opj2.PATH_LEN - len(outfile) outfile += b'0' * num_pad_bytes cparams.outfile = outfile if self.filename[-4:].lower() == '.jp2': - cparams.codec_fmt = _opj2.CODEC_JP2 + cparams.codec_fmt = opj2.CODEC_JP2 else: - cparams.codec_fmt = _opj2.CODEC_J2K + cparams.codec_fmt = opj2.CODEC_J2K # Set defaults to lossless to begin. cparams.tcp_rates[0] = 0 @@ -304,13 +304,13 @@ class Jp2k(Jp2kBox): if 'tilesize' in kwargs: cparams.cp_tdx = kwargs['tilesize'][1] cparams.cp_tdy = kwargs['tilesize'][0] - cparams.tile_size_on = _opj2.TRUE + cparams.tile_size_on = opj2.TRUE return cparams def _validate_compression_params(self, img_array, cparams): """Check that the compression parameters are valid. - + Parameters ---------- img_array : ndarray @@ -335,7 +335,7 @@ class Jp2k(Jp2kBox): msg = "Bad code block size ({0}, {1}), " msg += "must be powers of 2." raise IOError(msg.format(height, width)) - + # Precinct size if cparams.res_spec != 0: # precinct size was not specified if this field is zero. @@ -353,12 +353,12 @@ class Jp2k(Jp2kBox): msg = "Bad precinct sizes ({0}, {1}), " msg += "must be powers of 2." raise IOError(msg.format(prch, prcw)) - + # What would the point of 1D images be? if img_array.ndim == 1 or img_array.ndim > 3: msg = "{0}D imagery is not allowed.".format(img_array.ndim) raise IOError(msg) - + if _OPENJP2_IS_OFFICIAL_V2: if (((img_array.ndim != 2) and (img_array.shape[2] != 1 and img_array.shape[2] != 3))): @@ -367,16 +367,16 @@ class Jp2k(Jp2kBox): msg += "the OpenJPEG library version is the official 2.0.0 " msg += "release." raise IOError(msg) - + if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: msg = "Only uint8 and uint16 images are currently supported." raise RuntimeError(msg) - + def _process_write_inputs(self, img_array, colorspace=None, **kwargs): """Directs processing of write method arguments. It's somewhat awkward to process all the kwargs arguments at once. - The "colorspace" is not a parameter that gets processed into the + The "colorspace" is not a parameter that gets processed into the compression parameters structure, and it unfortunately must be handled in the middle of the compression parameter processing. @@ -409,7 +409,7 @@ class Jp2k(Jp2kBox): try: mct = kwargs['mct'] - if mct and colorspace == _opj2.CLRSPC_GRAY: + if mct and colorspace == opj2.CLRSPC_GRAY: # Cannot check for this in the validate routine, as we need # to know what the target colorspace has been determined to be. msg = "Cannot specify usage of the multi component transform " @@ -419,7 +419,7 @@ class Jp2k(Jp2kBox): except KeyError: # If the multi component transform was not specified, we infer # that it should be used if the color space is RGB. - if colorspace == _opj2.CLRSPC_SRGB: + if colorspace == opj2.CLRSPC_SRGB: cparams.tcp_mct = 1 else: cparams.tcp_mct = 0 @@ -525,7 +525,7 @@ class Jp2k(Jp2kBox): glymur.LibraryNotFoundError If glymur is unable to load the openjp2 library. """ - if _opj2.OPENJP2 is None: + if opj2.OPENJP2 is None: raise LibraryNotFoundError("You must have the openjp2 library " "installed before using this " "functionality.") @@ -537,11 +537,11 @@ class Jp2k(Jp2kBox): numrows, numcols = img_array.shape img_array = img_array.reshape(numrows, numcols, 1) - # Only two precisions are possible. + # Only two precisions are possible. comp_prec = 8 if img_array.dtype == np.uint8 else 16 numrows, numcols, num_comps = img_array.shape - comptparms = (_opj2.ImageComptParmType * num_comps)() + comptparms = (opj2.ImageComptParmType * num_comps)() for j in range(num_comps): comptparms[j].dx = cparams.subsampling_dx comptparms[j].dy = cparams.subsampling_dy @@ -553,40 +553,40 @@ class Jp2k(Jp2kBox): comptparms[j].bpp = comp_prec comptparms[j].sgnd = 0 - image = _opj2.image_create(comptparms, colorspace) + image = opj2.image_create(comptparms, colorspace) self._populate_image_struct(cparams, image, img_array) - codec = _opj2.create_compress(cparams.codec_fmt) + codec = opj2.create_compress(cparams.codec_fmt) info_handler = _INFO_CALLBACK if verbose else None - _opj2.set_info_handler(codec, info_handler) - _opj2.set_warning_handler(codec, _WARNING_CALLBACK) - _opj2.set_error_handler(codec, _ERROR_CALLBACK) + opj2.set_info_handler(codec, info_handler) + opj2.set_warning_handler(codec, _WARNING_CALLBACK) + opj2.set_error_handler(codec, _ERROR_CALLBACK) - _opj2.setup_encoder(codec, cparams, image) + opj2.setup_encoder(codec, cparams, image) if _OPENJP2_IS_OFFICIAL_V2: fptr = _libc.fopen(self.filename, 'wb') - strm = _opj2.stream_create_default_file_stream(fptr, False) + strm = opj2.stream_create_default_file_stream(fptr, False) else: # This routine introduced in 2.0 devel series. - strm = _opj2.stream_create_default_file_stream_v3(self.filename, - False) + strm = opj2.stream_create_default_file_stream_v3(self.filename, + False) # Start to clean up after ourselves. - _opj2.start_compress(codec, image, strm) - _opj2.encode(codec, strm) - _opj2.end_compress(codec, strm) + opj2.start_compress(codec, image, strm) + opj2.encode(codec, strm) + opj2.end_compress(codec, strm) if _OPENJP2_IS_OFFICIAL_V2: - _opj2.stream_destroy(strm) + opj2.stream_destroy(strm) _libc.fclose(fptr) else: # This routine introduced in 2.0 devel series. - _opj2.stream_destroy_v3(strm) + opj2.stream_destroy_v3(strm) - _opj2.destroy_codec(codec) - _opj2.image_destroy(image) + opj2.destroy_codec(codec) + opj2.image_destroy(image) # Refresh the metadata. self.parse() @@ -713,9 +713,9 @@ class Jp2k(Jp2kBox): >>> thumbnail.shape (728, 1296, 3) """ - if _opj2.OPENJP2 is not None: + if opj2.OPENJP2 is not None: img = self._read_openjp2(**kwargs) - elif _opj.OPENJPEG is not None: + elif opj.OPENJPEG is not None: img = self._read_openjpeg(**kwargs) else: raise LibraryNotFoundError("You must have either a recent version " @@ -761,38 +761,38 @@ class Jp2k(Jp2kBox): with ExitStack() as stack: # Set decoding parameters. - dparameters = _opj.DecompressionParametersType() - _opj.set_default_decoder_parameters(ctypes.byref(dparameters)) + dparameters = opj.DecompressionParametersType() + opj.set_default_decoder_parameters(ctypes.byref(dparameters)) dparameters.cp_reduce = rlevel dparameters.decod_format = self._codec_format infile = self.filename.encode() - nelts = _opj.PATH_LEN - len(infile) + nelts = opj.PATH_LEN - len(infile) infile += b'0' * nelts dparameters.infile = infile - dinfo = _opj.create_decompress(dparameters.decod_format) + dinfo = opj.create_decompress(dparameters.decod_format) - event_mgr = _opj.EventMgrType() + event_mgr = opj.EventMgrType() info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) event_mgr.info_handler = info_handler if verbose else None event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, ctypes.c_void_p) event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, ctypes.c_void_p) - _opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) + opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) - _opj.setup_decoder(dinfo, dparameters) + opj.setup_decoder(dinfo, dparameters) with open(self.filename, 'rb') as fptr: src = fptr.read() - cio = _opj.cio_open(dinfo, src) + cio = opj.cio_open(dinfo, src) - image = _opj.decode(dinfo, cio) + image = opj.decode(dinfo, cio) - stack.callback(_opj.image_destroy, image) - stack.callback(_opj.destroy_decompress, dinfo) - stack.callback(_opj.cio_close, cio) + stack.callback(opj.image_destroy, image) + stack.callback(opj.destroy_decompress, dinfo) + stack.callback(opj.cio_close, cio) data = extract_image_cube(image) @@ -850,7 +850,7 @@ class Jp2k(Jp2kBox): def _populate_dparam(self, layer, rlevel, area, tile): """Populate decompression structure with appropriate input parameters. - + Parameters ---------- layer : int, optional @@ -868,10 +868,10 @@ class Jp2k(Jp2kBox): dparam : DecompressionParametersType (ctypes) Corresponds to openjp2 decompression parameters structure. """ - dparam = _opj2.set_default_decoder_parameters() + dparam = opj2.set_default_decoder_parameters() infile = self.filename.encode() - nelts = _opj2.PATH_LEN - len(infile) + nelts = opj2.PATH_LEN - len(infile) infile += b'0' * nelts dparam.infile = infile @@ -929,39 +929,39 @@ class Jp2k(Jp2kBox): dparam = self._populate_dparam(layer, rlevel, area, tile) with ExitStack() as stack: - if hasattr(_opj2.OPENJP2, + if hasattr(opj2.OPENJP2, 'opj_stream_create_default_file_stream_v3'): filename = self.filename - stream = _opj2.stream_create_default_file_stream_v3(filename, - True) - stack.callback(_opj2.stream_destroy_v3, stream) + stream = opj2.stream_create_default_file_stream_v3(filename, + True) + stack.callback(opj2.stream_destroy_v3, stream) else: fptr = _libc.fopen(self.filename, 'rb') stack.callback(_libc.fclose, fptr) - stream = _opj2.stream_create_default_file_stream(fptr, True) - stack.callback(_opj2.stream_destroy, stream) - codec = _opj2.create_decompress(self._codec_format) - stack.callback(_opj2.destroy_codec, codec) + stream = opj2.stream_create_default_file_stream(fptr, True) + stack.callback(opj2.stream_destroy, stream) + codec = opj2.create_decompress(self._codec_format) + stack.callback(opj2.destroy_codec, codec) - _opj2.set_error_handler(codec, _ERROR_CALLBACK) - _opj2.set_warning_handler(codec, _WARNING_CALLBACK) + opj2.set_error_handler(codec, _ERROR_CALLBACK) + opj2.set_warning_handler(codec, _WARNING_CALLBACK) if verbose: - _opj2.set_info_handler(codec, _INFO_CALLBACK) + opj2.set_info_handler(codec, _INFO_CALLBACK) else: - _opj2.set_info_handler(codec, None) + opj2.set_info_handler(codec, None) - _opj2.setup_decoder(codec, dparam) - image = _opj2.read_header(stream, codec) - stack.callback(_opj2.image_destroy, image) + opj2.setup_decoder(codec, dparam) + image = opj2.read_header(stream, codec) + stack.callback(opj2.image_destroy, image) if dparam.nb_tile_to_decode: - _opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) + opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) else: - _opj2.set_decode_area(codec, image, - dparam.DA_x0, dparam.DA_y0, - dparam.DA_x1, dparam.DA_y1) - _opj2.decode(codec, stream, image) - _opj2.end_decompress(codec, stream) + opj2.set_decode_area(codec, image, + dparam.DA_x0, dparam.DA_y0, + dparam.DA_x1, dparam.DA_y1) + opj2.decode(codec, stream, image) + opj2.end_decompress(codec, stream) if as_bands: data = extract_image_bands(image) @@ -1013,7 +1013,7 @@ class Jp2k(Jp2kBox): glymur.LibraryNotFoundError If glymur is unable to load the openjp2 library. """ - if _opj2.OPENJP2 is None: + if opj2.OPENJP2 is None: raise LibraryNotFoundError("You must have the development version " "of OpenJP2 installed before using " "this functionality.") @@ -1063,7 +1063,7 @@ class Jp2k(Jp2kBox): If the file is JPX with more than one codestream. """ with open(self.filename, 'rb') as fptr: - if self._codec_format == _opj2.CODEC_J2K: + if self._codec_format == opj2.CODEC_J2K: codestream = Codestream(fptr, self.length, header_only=header_only) else: @@ -1087,6 +1087,7 @@ class Jp2k(Jp2kBox): return codestream + def component2dtype(component): """Take an OpenJPEG component structure and determine the numpy datatype. @@ -1127,6 +1128,7 @@ def _validate_nonzero_image_size(nrows, ncols, component_index): msg = msg.format(component_index, nrows, ncols) raise IOError(msg) + def _validate_jp2_box_sequence(boxes): """Run through series of tests for JP2 box legality. @@ -1198,6 +1200,7 @@ def _validate_jp2_box_sequence(boxes): msg += "channel definition box." raise IOError(msg) + def extract_image_cube(image): """Extract 3D image from openjpeg data structure. """ @@ -1226,6 +1229,7 @@ def extract_image_cube(image): return data + def extract_image_bands(image): """Extract unequally-sized image bands. @@ -1246,11 +1250,12 @@ def extract_image_bands(image): with warnings.catch_warnings(): warnings.simplefilter("ignore") band = np.ctypeslib.as_array( - (ctypes.c_int32 * nrows * ncols).from_address(addr)) + (ctypes.c_int32 * nrows * ncols).from_address(addr)) data.append(np.reshape(band.astype(dtype), (nrows, ncols))) return data + def _unpack_colorspace(colorspace, img_array, cparams): """Determine the colorspace from the supplied inputs. @@ -1267,17 +1272,17 @@ def _unpack_colorspace(colorspace, img_array, cparams): # Must infer the colorspace from the image dimensions. if img_array.ndim < 3: # A single channel image is grayscale. - colorspace = _opj2.CLRSPC_GRAY + colorspace = opj2.CLRSPC_GRAY elif img_array.shape[2] == 1 or img_array.shape[2] == 2: # A single channel image or an image with two channels is going # to be greyscale. - colorspace = _opj2.CLRSPC_GRAY + colorspace = opj2.CLRSPC_GRAY else: # Anything else must be RGB, right? - colorspace = _opj2.CLRSPC_SRGB + colorspace = opj2.CLRSPC_SRGB else: # Supplied a string colorspace, so we must validate it. - if cparams.codec_fmt == _opj2.CODEC_J2K: + if cparams.codec_fmt == opj2.CODEC_J2K: msg = 'Do not specify a colorspace when writing a raw ' msg += 'codestream.' raise IOError(msg) diff --git a/glymur/lib/__init__.py b/glymur/lib/__init__.py index 20fee5f..a283f7f 100644 --- a/glymur/lib/__init__.py +++ b/glymur/lib/__init__.py @@ -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 diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index b6ba85d..ad4fe6d 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -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 - From fbc9bbcf14d533d59206f905d6a94a2dcdd27178 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 10 Aug 2013 14:39:25 -0400 Subject: [PATCH 023/122] Pylint work, #99 --- glymur/codestream.py | 62 ++- glymur/test/test_opj_suite.py | 504 ++++++++++---------- glymur/test/test_opj_suite_write.py | 689 ++++++++++++++++------------ 3 files changed, 673 insertions(+), 582 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 2c24bef..7bd0215 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -807,6 +807,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 +822,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 +849,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 +878,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 +903,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 +914,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 +952,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 ' @@ -1411,7 +1419,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 +1471,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 +1495,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 diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 102b145..0a15879 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -1549,9 +1549,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -1568,10 +1568,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[3].scod & 2) # no sop self.assertFalse(c.segment[3].scod & 4) # no eph self.assertEqual(c.segment[3].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[3]._layers, 1) # layers = 1 + self.assertEqual(c.segment[3].layers, 1) # layers = 1 self.assertEqual(c.segment[3].spcod[3], 0) # mct self.assertEqual(c.segment[3].spcod[4], 3) # layers - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcod[7] & 0x01) @@ -1611,9 +1611,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(2, 1)]) @@ -1622,10 +1622,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) # sop self.assertTrue(c.segment[2].scod & 4) # eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 6) # layers = 6 + self.assertEqual(c.segment[2].layers, 6) # layers = 6 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -1645,7 +1645,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 0) self.assertEqual(c.segment[3].spcoc[0], 3) # levels - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) @@ -1717,9 +1717,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (4,)) + self.assertEqual(c.segment[1].bitdepth, (4,)) # signed - self.assertEqual(c.segment[1]._signed, (True,)) + self.assertEqual(c.segment[1].signed, (True,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -1728,10 +1728,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 8) # 8 + self.assertEqual(c.segment[2].layers, 8) # 8 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 1) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -1834,9 +1834,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (1, 1), (1, 1)]) @@ -1845,10 +1845,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 20) # 20 + self.assertEqual(c.segment[2].layers, 20) # 20 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 6) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -1864,7 +1864,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(c.segment[2].precinct_size, [(128, 128), (128, 128), (128, 128), (128, 128), (128, 128), (128, 128), (128, 128)]) @@ -1943,9 +1943,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (1, 1), (2, 2), (2, 2)]) @@ -1954,10 +1954,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 7) # 7 + self.assertEqual(c.segment[2].layers, 7) # 7 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 6) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -1978,7 +1978,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 1) self.assertEqual(c.segment[3].spcoc[0], 3) # levels - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) @@ -1998,7 +1998,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[4].ccoc, 3) self.assertEqual(c.segment[4].spcoc[0], 6) # levels - self.assertEqual(tuple(c.segment[4]._code_block_size), + self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[4].spcoc[3] & 0x01) @@ -2086,9 +2086,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12, 12, 12, 12)) + self.assertEqual(c.segment[1].bitdepth, (12, 12, 12, 12)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (2, 1), (1, 2), (2, 2)]) @@ -2097,10 +2097,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.RPCL) - self.assertEqual(c.segment[2]._layers, 4) # 4 + self.assertEqual(c.segment[2].layers, 4) # 4 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 6) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2169,7 +2169,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[7].ccoc, 3) self.assertEqual(c.segment[7].spcoc[0], 6) # levels - self.assertEqual(tuple(c.segment[7]._code_block_size), + self.assertEqual(tuple(c.segment[7].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[7].spcoc[3] & 0x01) @@ -2223,9 +2223,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12, 12, 12)) + self.assertEqual(c.segment[1].bitdepth, (12, 12, 12)) # signed - self.assertEqual(c.segment[1]._signed, (True, True, True)) + self.assertEqual(c.segment[1].signed, (True, True, True)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (1, 1), (1, 1)]) @@ -2234,10 +2234,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) self.assertTrue(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 8) # 8 + self.assertEqual(c.segment[2].layers, 8) # 8 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2308,9 +2308,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12, 12, 12)) + self.assertEqual(c.segment[1].bitdepth, (12, 12, 12)) # signed - self.assertEqual(c.segment[1]._signed, (True, True, True)) + self.assertEqual(c.segment[1].signed, (True, True, True)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (1, 1), (1, 1)]) @@ -2319,10 +2319,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) self.assertTrue(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.CPRL) - self.assertEqual(c.segment[2]._layers, 30) # 30 + self.assertEqual(c.segment[2].layers, 30) # 30 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 7) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2343,7 +2343,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 0) self.assertEqual(c.segment[3].spcoc[0], 6) # levels - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) @@ -2363,7 +2363,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[4].ccoc, 1) self.assertEqual(c.segment[4].spcoc[0], 7) # levels - self.assertEqual(tuple(c.segment[4]._code_block_size), + self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[4].spcoc[3] & 0x01) @@ -2383,7 +2383,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[5].ccoc, 2) self.assertEqual(c.segment[5].spcoc[0], 8) # levels - self.assertEqual(tuple(c.segment[5]._code_block_size), + self.assertEqual(tuple(c.segment[5].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[5].spcoc[3] & 0x01) @@ -2461,9 +2461,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -2472,10 +2472,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # 1 + self.assertEqual(c.segment[2].layers, 1) # 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2541,9 +2541,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(4, 4), (4, 4), (4, 4)]) @@ -2552,10 +2552,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 2) # 2 + self.assertEqual(c.segment[2].layers, 2) # 2 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 3) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2682,9 +2682,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -2693,10 +2693,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertTrue(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # 1 + self.assertEqual(c.segment[2].layers, 1) # 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 0) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2712,7 +2712,7 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, [(128, 2)]) + self.assertEqual(c.segment[2].precinct_size, [(128, 2)]) # QCD: Quantization default # quantization type @@ -2763,9 +2763,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -2774,10 +2774,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # 1 + self.assertEqual(c.segment[2].layers, 1) # 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -2845,9 +2845,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, tuple([8] * 257)) + self.assertEqual(c.segment[1].bitdepth, tuple([8] * 257)) # signed - self.assertEqual(c.segment[1]._signed, tuple([False] * 257)) + self.assertEqual(c.segment[1].signed, tuple([False] * 257)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 257) @@ -2856,10 +2856,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 1) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -2879,7 +2879,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 2) self.assertEqual(c.segment[3].spcoc[0], 1) # levels - self.assertEqual(tuple(c.segment[3]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) # Reset context probabilities @@ -2971,9 +2971,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -2982,10 +2982,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # 1 layer + self.assertEqual(c.segment[2].layers, 1) # 1 layer self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3047,9 +3047,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (4,)) + self.assertEqual(c.segment[1].bitdepth, (4,)) # signed - self.assertEqual(c.segment[1]._signed, (True,)) + self.assertEqual(c.segment[1].signed, (True,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -3058,10 +3058,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 8) # layers = 8 + self.assertEqual(c.segment[2].layers, 8) # layers = 8 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 1) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3201,9 +3201,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -3212,10 +3212,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) self.assertFalse(c.segment[2].scod & 4) self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 + self.assertEqual(c.segment[2].layers, 3) # layers = 3 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3269,9 +3269,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (1, 101)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(2, 1)]) @@ -3280,10 +3280,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) # SOP self.assertTrue(c.segment[2].scod & 4) # EPH self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 5) # layers = 5 + self.assertEqual(c.segment[2].layers, 5) # layers = 5 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3303,7 +3303,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 0) self.assertEqual(c.segment[3].spcoc[0], 3) # level - self.assertEqual(tuple(c.segment[3]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) # Reset context probabilities @@ -3369,9 +3369,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, tuple([8] * 3)) + self.assertEqual(c.segment[1].bitdepth, tuple([8] * 3)) # signed - self.assertEqual(c.segment[1]._signed, tuple([False] * 3)) + self.assertEqual(c.segment[1].signed, tuple([False] * 3)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -3380,10 +3380,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 19) # layers = 19 + self.assertEqual(c.segment[2].layers, 19) # layers = 19 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 6) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -3399,7 +3399,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(c.segment[2].precinct_size, [(128, 128), (256, 256), (512, 512), (1024, 1024), (2048, 2048), (4096, 4096), (8192, 8192)]) @@ -3484,9 +3484,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, tuple([8] * 4)) + self.assertEqual(c.segment[1].bitdepth, tuple([8] * 4)) # signed - self.assertEqual(c.segment[1]._signed, tuple([False] * 4)) + self.assertEqual(c.segment[1].signed, tuple([False] * 4)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (1, 1), (2, 2), (2, 2)]) @@ -3495,10 +3495,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 10) # layers = 10 + self.assertEqual(c.segment[2].layers, 10) # layers = 10 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 6) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertTrue(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3518,7 +3518,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 1) self.assertEqual(c.segment[3].spcoc[0], 3) # level - self.assertEqual(tuple(c.segment[3]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[3].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertTrue(c.segment[3].spcoc[3] & 0x01) # Reset context probabilities @@ -3537,7 +3537,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[4].ccoc, 3) self.assertEqual(c.segment[4].spcoc[0], 6) # level - self.assertEqual(tuple(c.segment[4]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertTrue(c.segment[4].spcoc[3] & 0x01) # Reset context probabilities @@ -3630,9 +3630,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12,)) + self.assertEqual(c.segment[1].bitdepth, (12,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -3641,10 +3641,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 3) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3757,9 +3757,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (8, 2)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -3768,10 +3768,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) # sop self.assertTrue(c.segment[2].scod & 4) # eph self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 2) # levels = 2 + self.assertEqual(c.segment[2].layers, 2) # levels = 2 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 7) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 8)) # cblk + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 8)) # cblk # Selective arithmetic coding bypass self.assertTrue(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3786,7 +3786,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, [(16, 16)] * 8) + self.assertEqual(c.segment[2].precinct_size, [(16, 16)] * 8) self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # expounded self.assertEqual(c.segment[3]._guard_bits, 3) @@ -3845,9 +3845,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -3856,10 +3856,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) # sop self.assertTrue(c.segment[2].scod & 4) # eph self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 4) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (32, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3938,9 +3938,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (4, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False)) + self.assertEqual(c.segment[1].signed, (False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(4, 1), (1, 1)]) @@ -3949,10 +3949,10 @@ class TestSuiteDump(unittest.TestCase): self.assertTrue(c.segment[2].scod & 2) # sop self.assertTrue(c.segment[2].scod & 4) # eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RPCL) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 1) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -3967,12 +3967,12 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, [(1, 1), (2, 2)]) + self.assertEqual(c.segment[2].precinct_size, [(1, 1), (2, 2)]) # COC: Coding style component self.assertEqual(c.segment[3].ccoc, 1) self.assertEqual(c.segment[3].spcoc[0], 1) # level - self.assertEqual(tuple(c.segment[3]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcoc[3] & 0x01) # Reset context probabilities @@ -3987,7 +3987,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[3].spcoc[3] & 0x0020) self.assertEqual(c.segment[3].spcoc[4], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[3]._precinct_size, [(2, 2), (4, 4)]) + self.assertEqual(c.segment[3].precinct_size, [(2, 2), (4, 4)]) # QCD: Quantization default # quantization type @@ -4481,9 +4481,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12, 12, 12)) + self.assertEqual(c.segment[1].bitdepth, (12, 12, 12)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -4492,10 +4492,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.CPRL) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4510,8 +4510,8 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size[0], (128, 128)) - self.assertEqual(c.segment[2]._precinct_size[1:], [(256, 256)] * 5) + self.assertEqual(c.segment[2].precinct_size[0], (128, 128)) + self.assertEqual(c.segment[2].precinct_size[1:], [(256, 256)] * 5) # QCD: Quantization default # quantization type @@ -4527,7 +4527,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[4].ccoc, 1) self.assertEqual(c.segment[4].spcoc[0], 5) # level - self.assertEqual(tuple(c.segment[4]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[4].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[4].spcoc[3] & 0x01) # Reset context probabilities @@ -4559,7 +4559,7 @@ class TestSuiteDump(unittest.TestCase): # COC: Coding style component self.assertEqual(c.segment[6].ccoc, 2) self.assertEqual(c.segment[6].spcoc[0], 5) # level - self.assertEqual(tuple(c.segment[6]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[6].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[6].spcoc[3] & 0x01) # Reset context probabilities @@ -4633,9 +4633,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -4644,10 +4644,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 + self.assertEqual(c.segment[2].layers, 3) # layers = 3 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (32, 32)) + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4662,7 +4662,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(c.segment[2].precinct_size, [(16, 16), (32, 32), (64, 64), (128, 128), (128, 128), (128, 128)]) @@ -4690,9 +4690,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -4701,10 +4701,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 2) # layers = 2 + self.assertEqual(c.segment[2].layers, 2) # layers = 2 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4743,9 +4743,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -4754,10 +4754,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 2) # layers = 2 + self.assertEqual(c.segment[2].layers, 2) # layers = 2 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4805,9 +4805,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -4816,10 +4816,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4867,9 +4867,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12,)) + self.assertEqual(c.segment[1].bitdepth, (12,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -4878,10 +4878,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -4938,9 +4938,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -4949,10 +4949,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5015,9 +5015,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5026,10 +5026,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5075,9 +5075,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (True, True, True)) + self.assertEqual(c.segment[1].signed, (True, True, True)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5086,10 +5086,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5141,9 +5141,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5152,10 +5152,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 12) # layers = 12 + self.assertEqual(c.segment[2].layers, 12) # layers = 12 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 8) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5226,9 +5226,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5237,10 +5237,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5286,9 +5286,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5297,10 +5297,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5344,9 +5344,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5355,10 +5355,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5402,9 +5402,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5413,10 +5413,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5463,9 +5463,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 4) @@ -5474,10 +5474,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5524,9 +5524,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 4) @@ -5535,10 +5535,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5584,9 +5584,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (True,)) + self.assertEqual(c.segment[1].signed, (True,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5595,10 +5595,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 16) # layers = 16 + self.assertEqual(c.segment[2].layers, 16) # layers = 16 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5654,9 +5654,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12,)) + self.assertEqual(c.segment[1].bitdepth, (12,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5665,10 +5665,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), (64, 64)) + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) # Reset context probabilities @@ -5723,9 +5723,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5734,10 +5734,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -5785,9 +5785,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(c.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 1) @@ -5796,10 +5796,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 11) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -5848,9 +5848,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (12, 12, 12)) + self.assertEqual(c.segment[1].bitdepth, (12, 12, 12)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5859,10 +5859,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 2) # layers = 2 + self.assertEqual(c.segment[2].layers, 2) # layers = 2 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -5878,7 +5878,7 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].spcod[7] & 0x0020) self.assertEqual(c.segment[2].spcod[8], glymur.core.WAVELET_XFORM_9X7_IRREVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(c.segment[2].precinct_size, [(128, 128)] + [(256, 256)] * 5) # QCD: Quantization default @@ -5957,9 +5957,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -5975,10 +5975,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[3].scod & 2) # no sop self.assertFalse(c.segment[3].scod & 4) # no eph self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[3]._layers, 1) # layers = 1 + self.assertEqual(c.segment[3].layers, 1) # layers = 1 self.assertEqual(c.segment[3].spcod[3], 1) # mct self.assertEqual(c.segment[3].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcod[7] & 0x01) @@ -6094,9 +6094,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -6112,10 +6112,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[3].scod & 2) # no sop self.assertFalse(c.segment[3].scod & 4) # no eph self.assertEqual(c.segment[3].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[3]._layers, 1) # layers = 1 + self.assertEqual(c.segment[3].layers, 1) # layers = 1 self.assertEqual(c.segment[3].spcod[3], 1) # mct self.assertEqual(c.segment[3].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[3]._code_block_size), + self.assertEqual(tuple(c.segment[3].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[3].spcod[7] & 0x01) @@ -6227,9 +6227,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (2, 1), (2, 1)]) @@ -6238,10 +6238,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 128)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6381,9 +6381,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8,)) + self.assertEqual(c.segment[1].bitdepth, (8,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -6392,10 +6392,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6482,9 +6482,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -6493,10 +6493,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6581,9 +6581,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -6592,10 +6592,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6685,9 +6685,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False)) + self.assertEqual(c.segment[1].signed, (False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 2) @@ -6696,10 +6696,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 2) # layers = 2 + self.assertEqual(c.segment[2].layers, 2) # layers = 2 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6813,9 +6813,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (1,)) + self.assertEqual(c.segment[1].bitdepth, (1,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -6824,10 +6824,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -6928,9 +6928,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (4,)) + self.assertEqual(c.segment[1].bitdepth, (4,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(c.segment[1].signed, (False,)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)]) @@ -6939,10 +6939,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -7022,9 +7022,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1), (2, 1), (2, 1)]) @@ -7033,10 +7033,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 128)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -7131,9 +7131,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 4) @@ -7142,10 +7142,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -7231,9 +7231,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 4) @@ -7242,10 +7242,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 + self.assertEqual(c.segment[2].layers, 1) # layers = 1 self.assertEqual(c.segment[2].spcod[3], 0) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (64, 64)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) @@ -7343,9 +7343,9 @@ class TestSuiteDump(unittest.TestCase): # Tile offset self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(c.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(c.segment[1].signed, (False, False, False)) # subsampling self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), [(1, 1)] * 3) @@ -7354,10 +7354,10 @@ class TestSuiteDump(unittest.TestCase): self.assertFalse(c.segment[2].scod & 2) # no sop self.assertFalse(c.segment[2].scod & 4) # no eph self.assertEqual(c.segment[2].spcod[0], glymur.core.RLCP) - self.assertEqual(c.segment[2]._layers, 6) # layers = 6 + self.assertEqual(c.segment[2].layers, 6) # layers = 6 self.assertEqual(c.segment[2].spcod[3], 1) # mct self.assertEqual(c.segment[2].spcod[4], 5) # level - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertEqual(tuple(c.segment[2].code_block_size), (32, 32)) # cblk # Selective arithmetic coding bypass self.assertFalse(c.segment[2].spcod[7] & 0x01) diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 766297b..09722dc 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -2,9 +2,10 @@ The tests defined here roughly correspond to what is in the OpenJPEG test suite. """ -#pylint: disable-all +# C0103: method names longer that 30 chars are ok in tests, IMHO +# R0904: Seems like pylint is fooled in this situation +# pylint: disable=R0904,C0103 import os -import platform import sys import tempfile @@ -13,10 +14,6 @@ if sys.hexversion < 0x02070000: else: import unittest -import numpy as np - -from glymur.lib import openjp2 as opj2 - from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from glymur import Jp2k @@ -37,7 +34,11 @@ except: @unittest.skipIf(data_root is None, "OPJ_DATA_ROOT environment variable not set") class TestSuiteWrite(unittest.TestCase): + """Tests for writing with openjp2 backend. + These tests roughly correspond with those tests with similar names in the + OpenJPEG test suite. + """ def setUp(self): pass @@ -45,7 +46,7 @@ class TestSuiteWrite(unittest.TestCase): pass def test_NR_ENC_Bretagne1_ppm_1_encode(self): - # NR-ENC-Bretagne1.ppm-1-encode + """NR-ENC-Bretagne1.ppm-1-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: @@ -53,57 +54,63 @@ class TestSuiteWrite(unittest.TestCase): j.write(data, cratios=[200, 100, 50]) # Should be three layers. - c = j.get_codestream() + codestream = j.get_codestream() # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (640, 480)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 3) # layers = 3 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Bretagne1_ppm_2_encode(self): - # NR-ENC-Bretagne1.ppm-2-encode + """NR-ENC-Bretagne1.ppm-2-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: @@ -111,57 +118,64 @@ class TestSuiteWrite(unittest.TestCase): j.write(data, psnr=[30, 35, 40], numres=2) # Should be three layers. - c = j.get_codestream() + codestream = j.get_codestream() # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (640, 480)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, + (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 1) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 3) # layers = 3 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 1) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Bretagne1_ppm_3_encode(self): - # NR-ENC-Bretagne1.ppm-3-encode + """NR-ENC-Bretagne1.ppm-3-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: @@ -170,58 +184,65 @@ class TestSuiteWrite(unittest.TestCase): psizes=[(64, 64)]) # Should be three layers. - c = j.get_codestream() + codestream = j.get_codestream() # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (640, 480)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 3) # layers = 3 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (16, 16)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(codestream.segment[2].precinct_size, [(2, 2), (4, 4), (8, 8), (16, 16), (32, 32), (64, 64)]) def test_NR_ENC_Bretagne2_ppm_4_encode(self): + """NR-ENC-Bretagne2.ppm-4-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: @@ -233,413 +254,459 @@ class TestSuiteWrite(unittest.TestCase): cbsize=(32, 32)) # Should be three layers. - c = j.get_codestream() + codestream = j.get_codestream() # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (data.shape[1], data.shape[0])) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size. Reported as XY, not RC. - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 3) # layers = 3 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (32, 32)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(c.segment[2]._precinct_size, + self.assertEqual(codestream.segment[2].precinct_size, [(16, 16), (32, 32), (64, 64)] + [(128, 128)] * 3) def test_NR_ENC_Bretagne2_ppm_5_encode(self): - # NR-ENC-Bretagne2.ppm-4-encode + """NR-ENC-Bretagne2.ppm-5-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, tilesize=(127, 127), prog="PCRL") - c = j.get_codestream() + codestream = j.get_codestream() # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (data.shape[1], data.shape[0])) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (127, 127)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.PCRL) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.PCRL) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Bretagne2_ppm_6_encode(self): - # NR-ENC-Bretagne2.ppm-6-encode + """NR-ENC-Bretagne2.ppm-6-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, subsam=(2, 2), sop=True) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (5183, 3887)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (5183, 3887)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(2, 2)] * 3) # COD: Coding style default - self.assertTrue(c.segment[2].scod & 2) # sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertTrue(codestream.segment[2].scod & 2) # sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding bypass - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # Reset context probabilities - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) # 18 SOP segments. - nsops = [x.nsop for x in c.segment if x.marker_id == 'SOP'] + nsops = [x.nsop for x in codestream.segment if x.marker_id == 'SOP'] self.assertEqual(nsops, list(range(18))) def test_NR_ENC_Bretagne2_ppm_7_encode(self): + """NR-ENC-Bretagne2.ppm-7-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, modesw=38, eph=True) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (2592, 1944)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (2592, 1944)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertTrue(c.segment[2].scod & 4) # eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertTrue(codestream.segment[2].scod & 4) # eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertTrue(c.segment[2].spcod[7] & 0x02) + self.assertTrue(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertTrue(c.segment[2].spcod[7] & 0x04) + self.assertTrue(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertTrue(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertTrue(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) # 18 EPH segments. - ephs = [x for x in c.segment if x.marker_id == 'EPH'] + ephs = [x for x in codestream.segment if x.marker_id == 'EPH'] self.assertEqual(len(ephs), 18) def test_NR_ENC_Bretagne2_ppm_8_encode(self): + """NR-ENC-Bretagne2.ppm-8-encode""" infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, grid_offset=[300, 150], cratios=[800]) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (2742, 2244)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (150, 300)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (2742, 2244)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Cevennes1_bmp_9_encode(self): + """NR-ENC-Cevennes1.bmp-9-encode""" infile = os.path.join(data_root, 'input/nonregression/Cevennes1.bmp') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, cratios=[800]) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (2592, 1944)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (2592, 1944)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Cevennes2_ppm_10_encode(self): + """NR-ENC-Cevennes2.ppm-10-encode""" infile = os.path.join(data_root, 'input/nonregression/Cevennes2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') j.write(data, cratios=[50]) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (640, 480)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) def test_NR_ENC_Rome_bmp_11_encode(self): - infile = os.path.join(data_root, 'input/nonregression/Rome.bmp') - data = read_image(infile) + """NR-ENC-Rome.bmp-11-encode""" + data = read_image(os.path.join(data_root, + 'input/nonregression/Rome.bmp')) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: jp2 = Jp2k(tfile.name, 'wb') jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) ids = [box.box_id for box in jp2.box] - lst = ['jP ', 'ftyp', 'jp2h', 'jp2c'] - self.assertEqual(ids, lst) + self.assertEqual(ids, ['jP ', 'ftyp', 'jp2h', 'jp2c']) ids = [box.box_id for box in jp2.box[2].box] self.assertEqual(ids, ['ihdr', 'colr']) @@ -671,58 +738,65 @@ class TestSuiteWrite(unittest.TestCase): self.assertIsNone(jp2.box[2].box[1].icc_profile) self.assertEqual(jp2.box[2].box[1].colorspace, glymur.core.SRGB) - c = jp2.box[3].main_header + codestream = jp2.box[3].main_header # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (640, 480)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (640, 480)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (8, 8, 8)) + self.assertEqual(codestream.segment[1].bitdepth, (8, 8, 8)) # signed - self.assertEqual(c.segment[1]._signed, (False, False, False)) + self.assertEqual(codestream.segment[1].signed, + (False, False, False)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)] * 3) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 3) # layers = 3 - self.assertEqual(c.segment[2].spcod[3], 1) # mct - self.assertEqual(c.segment[2].spcod[4], 2) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 3) # layers = 3 + self.assertEqual(codestream.segment[2].spcod[3], 1) # mct + self.assertEqual(codestream.segment[2].spcod[4], 2) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) @unittest.skip("Known failure in openjpeg test suite.") def test_NR_ENC_random_issue_0005_tif_12_encode(self): + """NR-ENC-random-issue-0005.tif-12-encode""" # opj_decompress has trouble reading it, but that is not an issue here. # The nature of the image itself seems to give the compressor trouble. infile = os.path.join(data_root, @@ -732,54 +806,59 @@ class TestSuiteWrite(unittest.TestCase): j = Jp2k(tfile.name, 'wb') j.write(data) - c = j.get_codestream(header_only=False) + codestream = j.get_codestream(header_only=False) # SIZ: Image and tile size # Profile: "0" means profile 2 - self.assertEqual(c.segment[1].rsiz, 0) + self.assertEqual(codestream.segment[1].rsiz, 0) # Reference grid size - self.assertEqual((c.segment[1].xsiz, c.segment[1].ysiz), + self.assertEqual((codestream.segment[1].xsiz, + codestream.segment[1].ysiz), (1024, 1024)) # Reference grid offset - self.assertEqual((c.segment[1].xosiz, c.segment[1].yosiz), (0, 0)) + self.assertEqual((codestream.segment[1].xosiz, + codestream.segment[1].yosiz), (0, 0)) # Tile size - self.assertEqual((c.segment[1].xtsiz, c.segment[1].ytsiz), + self.assertEqual((codestream.segment[1].xtsiz, + codestream.segment[1].ytsiz), (1024, 1024)) # Tile offset - self.assertEqual((c.segment[1].xtosiz, c.segment[1].ytosiz), + self.assertEqual((codestream.segment[1].xtosiz, + codestream.segment[1].ytosiz), (0, 0)) # bitdepth - self.assertEqual(c.segment[1]._bitdepth, (16,)) + self.assertEqual(codestream.segment[1].bitdepth, (16,)) # signed - self.assertEqual(c.segment[1]._signed, (False,)) + self.assertEqual(codestream.segment[1].signed, (False,)) # subsampling - self.assertEqual(list(zip(c.segment[1].xrsiz, c.segment[1].yrsiz)), + self.assertEqual(list(zip(codestream.segment[1].xrsiz, + codestream.segment[1].yrsiz)), [(1, 1)]) # COD: Coding style default - self.assertFalse(c.segment[2].scod & 2) # no sop - self.assertFalse(c.segment[2].scod & 4) # no eph - self.assertEqual(c.segment[2].spcod[0], glymur.core.LRCP) - self.assertEqual(c.segment[2]._layers, 1) # layers = 1 - self.assertEqual(c.segment[2].spcod[3], 0) # mct - self.assertEqual(c.segment[2].spcod[4], 5) # levels - self.assertEqual(tuple(c.segment[2]._code_block_size), + self.assertFalse(codestream.segment[2].scod & 2) # no sop + self.assertFalse(codestream.segment[2].scod & 4) # no eph + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.LRCP) + self.assertEqual(codestream.segment[2].layers, 1) # layers = 1 + self.assertEqual(codestream.segment[2].spcod[3], 0) # mct + self.assertEqual(codestream.segment[2].spcod[4], 5) # levels + self.assertEqual(tuple(codestream.segment[2].code_block_size), (64, 64)) # cblksz # Selective arithmetic coding BYPASS - self.assertFalse(c.segment[2].spcod[7] & 0x01) + self.assertFalse(codestream.segment[2].spcod[7] & 0x01) # RESET context probabilities (RESET) - self.assertFalse(c.segment[2].spcod[7] & 0x02) + self.assertFalse(codestream.segment[2].spcod[7] & 0x02) # Termination on each coding pass, RESTART(TERMALL) - self.assertFalse(c.segment[2].spcod[7] & 0x04) + self.assertFalse(codestream.segment[2].spcod[7] & 0x04) # Vertically causal context (VSC) - self.assertFalse(c.segment[2].spcod[7] & 0x08) + self.assertFalse(codestream.segment[2].spcod[7] & 0x08) # Predictable termination, ERTERM(SEGTERM) - self.assertFalse(c.segment[2].spcod[7] & 0x0010) + self.assertFalse(codestream.segment[2].spcod[7] & 0x0010) # Segmentation symbols, SEGMARK(SEGSYSM) - self.assertFalse(c.segment[2].spcod[7] & 0x0020) - self.assertEqual(c.segment[2].spcod[8], + self.assertFalse(codestream.segment[2].spcod[7] & 0x0020) + self.assertEqual(codestream.segment[2].spcod[8], glymur.core.WAVELET_XFORM_5X3_REVERSIBLE) - self.assertEqual(len(c.segment[2].spcod), 9) + self.assertEqual(len(codestream.segment[2].spcod), 9) if __name__ == "__main__": unittest.main() From 63168e6b3ae538261489b95993e15ada35777ab4 Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 10 Aug 2013 16:42:08 -0400 Subject: [PATCH 024/122] pylint work, #99 --- glymur/jp2k.py | 287 ++++++++++++++++++++++-------------------- glymur/lib/openjp2.py | 2 +- 2 files changed, 151 insertions(+), 138 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index fade3a8..9518c22 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -3,7 +3,9 @@ License: MIT """ -# pylint: disable=C0302 +# W0201: Since we are using ctypes Structures, we often have to access +# attributes that are not defined in __init__ but in _fields_ instead. +# pylint: disable=W0201 import sys if sys.hexversion >= 0x03030000: @@ -32,7 +34,7 @@ from .jp2box import ImageHeaderBox from .jp2box import ColourSpecificationBox from .lib import openjpeg as opj from .lib import openjp2 as opj2 -from .lib import c as _libc +from .lib import c as libc # Need to known if openjp2 library is the officially release v2.0.0 or not. _OPENJP2_IS_OFFICIAL_V2 = False @@ -233,7 +235,6 @@ class Jp2k(Jp2kBox): cparams : CompressionParametersType(ctypes.Structure) Corresponds to cparameters_t type in openjp2 headers. """ - cparams = opj2.set_default_encoder_parameters() outfile = self.filename.encode() @@ -308,70 +309,6 @@ class Jp2k(Jp2kBox): return cparams - def _validate_compression_params(self, img_array, cparams): - """Check that the compression parameters are valid. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - """ - - # Code block size - code_block_specified = False - if cparams.cblockw_init != 0 and cparams.cblockh_init != 0: - # These fields ARE zero if uninitialized. - width = cparams.cblockw_init - height = cparams.cblockh_init - code_block_specified = True - if height * width > 4096 or height < 4 or width < 4: - msg = "Code block area cannot exceed 4096. " - msg += "Code block height and width must be larger than 4." - raise IOError(msg) - if ((math.log(height, 2) != math.floor(math.log(height, 2)) or - math.log(width, 2) != math.floor(math.log(width, 2)))): - msg = "Bad code block size ({0}, {1}), " - msg += "must be powers of 2." - raise IOError(msg.format(height, width)) - - # Precinct size - if cparams.res_spec != 0: - # precinct size was not specified if this field is zero. - for j in range(cparams.res_spec): - prch = cparams.prch_init[j] - prcw = cparams.prcw_init[j] - if j == 0 and code_block_specified: - height, width = cparams.cblockh_init, cparams.cblockw_init - if height * 2 > prch or width * 2 > prcw: - msg = "Highest Resolution precinct size must be at " - msg += "least twice that of the code block dimensions." - raise IOError(msg) - if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or - math.log(prcw, 2) != math.floor(math.log(prcw, 2)))): - msg = "Bad precinct sizes ({0}, {1}), " - msg += "must be powers of 2." - raise IOError(msg.format(prch, prcw)) - - # What would the point of 1D images be? - if img_array.ndim == 1 or img_array.ndim > 3: - msg = "{0}D imagery is not allowed.".format(img_array.ndim) - raise IOError(msg) - - if _OPENJP2_IS_OFFICIAL_V2: - if (((img_array.ndim != 2) and - (img_array.shape[2] != 1 and img_array.shape[2] != 3))): - msg = "Writing images is restricted to single-channel " - msg += "greyscale images or three-channel RGB images when " - msg += "the OpenJPEG library version is the official 2.0.0 " - msg += "release." - raise IOError(msg) - - if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: - msg = "Only uint8 and uint16 images are currently supported." - raise RuntimeError(msg) - def _process_write_inputs(self, img_array, colorspace=None, **kwargs): """Directs processing of write method arguments. @@ -403,7 +340,7 @@ class Jp2k(Jp2kBox): raise IOError(msg) cparams = self._populate_cparams(**kwargs) - self._validate_compression_params(img_array, cparams) + _validate_compression_params(img_array, cparams) colorspace = _unpack_colorspace(colorspace, img_array, cparams) @@ -426,38 +363,6 @@ class Jp2k(Jp2kBox): return cparams, colorspace - def _populate_image_struct(self, cparams, image, imgdata): - """Populates image struct needed for compression. - - Parameters - ---------- - cparams : CompressionParametersType(ctypes.Structure) - Corresponds to cparameters_t type in openjp2 headers. - image : ImageType(ctypes.Structure) - Corresponds to image_t type in openjp2 headers. - imgarray : ndarray - Image data to be written to file. - """ - - numrows, numcols, num_comps = imgdata.shape - - # set image offset and reference grid - image.contents.x0 = cparams.image_offset_x0 - image.contents.y0 = cparams.image_offset_y0 - image.contents.x1 = (image.contents.x0 + - (numcols - 1) * cparams.subsampling_dx + 1) - image.contents.y1 = (image.contents.y0 + - (numrows - 1) * cparams.subsampling_dy + 1) - - # Stage the image data to the openjpeg data structure. - for k in range(0, num_comps): - layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) - dest = image.contents.comps[k].data - src = layer.ctypes.data - ctypes.memmove(dest, src, layer.nbytes) - - return image - def write(self, img_array, verbose=False, **kwargs): """Write image data to a JP2/JPX/J2k file. Intended usage of the various parameters follows that of OpenJPEG's opj_compress utility. @@ -537,24 +442,10 @@ class Jp2k(Jp2kBox): numrows, numcols = img_array.shape img_array = img_array.reshape(numrows, numcols, 1) - # Only two precisions are possible. - comp_prec = 8 if img_array.dtype == np.uint8 else 16 - - numrows, numcols, num_comps = img_array.shape - comptparms = (opj2.ImageComptParmType * num_comps)() - for j in range(num_comps): - comptparms[j].dx = cparams.subsampling_dx - comptparms[j].dy = cparams.subsampling_dy - comptparms[j].w = numcols - comptparms[j].h = numrows - comptparms[j].x0 = cparams.image_offset_x0 - comptparms[j].y0 = cparams.image_offset_y0 - comptparms[j].prec = comp_prec - comptparms[j].bpp = comp_prec - comptparms[j].sgnd = 0 + comptparms = _populate_comptparms(img_array, cparams) image = opj2.image_create(comptparms, colorspace) - self._populate_image_struct(cparams, image, img_array) + _populate_image_struct(cparams, image, img_array) codec = opj2.create_compress(cparams.codec_fmt) @@ -566,7 +457,7 @@ class Jp2k(Jp2kBox): opj2.setup_encoder(codec, cparams, image) if _OPENJP2_IS_OFFICIAL_V2: - fptr = _libc.fopen(self.filename, 'wb') + fptr = libc.fopen(self.filename, 'wb') strm = opj2.stream_create_default_file_stream(fptr, False) else: # This routine introduced in 2.0 devel series. @@ -580,7 +471,7 @@ class Jp2k(Jp2kBox): if _OPENJP2_IS_OFFICIAL_V2: opj2.stream_destroy(strm) - _libc.fclose(fptr) + libc.fclose(fptr) else: # This routine introduced in 2.0 devel series. opj2.stream_destroy_v3(strm) @@ -804,8 +695,7 @@ class Jp2k(Jp2kBox): return data - def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, - verbose=False): + def _read_openjp2(self, **kwargs): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -835,12 +725,7 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - img_array = self._read_common(rlevel=rlevel, - layer=layer, - area=area, - tile=tile, - verbose=verbose, - as_bands=False) + img_array = self._read_common(as_bands=False, **kwargs) if img_array.shape[2] == 1: img_array = img_array.view() @@ -936,8 +821,8 @@ class Jp2k(Jp2kBox): True) stack.callback(opj2.stream_destroy_v3, stream) else: - fptr = _libc.fopen(self.filename, 'rb') - stack.callback(_libc.fclose, fptr) + fptr = libc.fopen(self.filename, 'rb') + stack.callback(libc.fclose, fptr) stream = opj2.stream_create_default_file_stream(fptr, True) stack.callback(opj2.stream_destroy, stream) codec = opj2.create_decompress(self._codec_format) @@ -970,8 +855,7 @@ class Jp2k(Jp2kBox): return data - def read_bands(self, rlevel=0, layer=0, area=None, tile=None, - verbose=False): + def read_bands(self, **kwargs): """Read a JPEG 2000 image. The only time you should use this method is when the image has @@ -1018,13 +902,7 @@ class Jp2k(Jp2kBox): "of OpenJP2 installed before using " "this functionality.") - lst = self._read_common(rlevel=rlevel, - layer=layer, - area=area, - tile=tile, - verbose=verbose, - as_bands=True) - + lst = self._read_common(as_bands=True, **kwargs) return lst def get_codestream(self, header_only=True): @@ -1298,3 +1176,138 @@ def _unpack_colorspace(colorspace, img_array, cparams): colorspace = _COLORSPACE_MAP[colorspace.lower()] return colorspace + +def _populate_comptparms(img_array, cparams): + """Instantiate and populate comptparms structure. + + This structure defines the image components. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + + Returns + ------- + comptparms : ImageCompType(ctypes.Structure) + Corresponds to image_comp_t type in openjp2 headers. + """ + # Only two precisions are possible. + if img_array.dtype == np.uint8: + comp_prec = 8 + else: + comp_prec = 16 + + numrows, numcols, num_comps = img_array.shape + comptparms = (opj2.ImageComptParmType * num_comps)() + for j in range(num_comps): + comptparms[j].dx = cparams.subsampling_dx + comptparms[j].dy = cparams.subsampling_dy + comptparms[j].w = numcols + comptparms[j].h = numrows + comptparms[j].x0 = cparams.image_offset_x0 + comptparms[j].y0 = cparams.image_offset_y0 + comptparms[j].prec = comp_prec + comptparms[j].bpp = comp_prec + comptparms[j].sgnd = 0 + + return comptparms + +def _populate_image_struct(cparams, image, imgdata): + """Populates image struct needed for compression. + + Parameters + ---------- + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + image : ImageType(ctypes.Structure) + Corresponds to image_t type in openjp2 headers. + imgarray : ndarray + Image data to be written to file. + """ + + numrows, numcols, num_comps = imgdata.shape + + # set image offset and reference grid + image.contents.x0 = cparams.image_offset_x0 + image.contents.y0 = cparams.image_offset_y0 + image.contents.x1 = (image.contents.x0 + + (numcols - 1) * cparams.subsampling_dx + 1) + image.contents.y1 = (image.contents.y0 + + (numrows - 1) * cparams.subsampling_dy + 1) + + # Stage the image data to the openjpeg data structure. + for k in range(0, num_comps): + layer = np.ascontiguousarray(imgdata[:, :, k], dtype=np.int32) + dest = image.contents.comps[k].data + src = layer.ctypes.data + ctypes.memmove(dest, src, layer.nbytes) + + return image + +def _validate_compression_params(img_array, cparams): + """Check that the compression parameters are valid. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + cparams : CompressionParametersType(ctypes.Structure) + Corresponds to cparameters_t type in openjp2 headers. + """ + + # Code block size + code_block_specified = False + if cparams.cblockw_init != 0 and cparams.cblockh_init != 0: + # These fields ARE zero if uninitialized. + width = cparams.cblockw_init + height = cparams.cblockh_init + code_block_specified = True + if height * width > 4096 or height < 4 or width < 4: + msg = "Code block area cannot exceed 4096. " + msg += "Code block height and width must be larger than 4." + raise IOError(msg) + if ((math.log(height, 2) != math.floor(math.log(height, 2)) or + math.log(width, 2) != math.floor(math.log(width, 2)))): + msg = "Bad code block size ({0}, {1}), " + msg += "must be powers of 2." + raise IOError(msg.format(height, width)) + + # Precinct size + if cparams.res_spec != 0: + # precinct size was not specified if this field is zero. + for j in range(cparams.res_spec): + prch = cparams.prch_init[j] + prcw = cparams.prcw_init[j] + if j == 0 and code_block_specified: + height, width = cparams.cblockh_init, cparams.cblockw_init + if height * 2 > prch or width * 2 > prcw: + msg = "Highest Resolution precinct size must be at " + msg += "least twice that of the code block dimensions." + raise IOError(msg) + if ((math.log(prch, 2) != math.floor(math.log(prch, 2)) or + math.log(prcw, 2) != math.floor(math.log(prcw, 2)))): + msg = "Bad precinct sizes ({0}, {1}), " + msg += "must be powers of 2." + raise IOError(msg.format(prch, prcw)) + + # What would the point of 1D images be? + if img_array.ndim == 1 or img_array.ndim > 3: + msg = "{0}D imagery is not allowed.".format(img_array.ndim) + raise IOError(msg) + + if _OPENJP2_IS_OFFICIAL_V2: + if (((img_array.ndim != 2) and + (img_array.shape[2] != 1 and img_array.shape[2] != 3))): + msg = "Writing images is restricted to single-channel " + msg += "greyscale images or three-channel RGB images when " + msg += "the OpenJPEG library version is the official 2.0.0 " + msg += "release." + raise IOError(msg) + + if img_array.dtype != np.uint8 and img_array.dtype != np.uint16: + msg = "Only uint8 and uint16 images are currently supported." + raise RuntimeError(msg) + diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 468bb51..f0f72c0 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -2,7 +2,7 @@ Wraps individual functions in openjp2 library. """ -# pylint: disable=C0302,R0903 +# pylint: disable=C0302,R0903,W0201 import ctypes import sys From ee2f9505000ce4b490351d3bcf21235e132a933d Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 10 Aug 2013 21:51:59 -0400 Subject: [PATCH 025/122] pylint work, #99 --- glymur/jp2k.py | 4 ---- glymur/test/test_callbacks.py | 32 ++++++++++++++++++++++++-------- glymur/test/test_config.py | 35 ++++++++++++++++++++++------------- glymur/test/test_icc.py | 35 ++++++++++++++++++++--------------- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 9518c22..37cad71 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -3,10 +3,6 @@ License: MIT """ -# W0201: Since we are using ctypes Structures, we often have to access -# attributes that are not defined in __init__ but in _fields_ instead. -# pylint: disable=W0201 - import sys if sys.hexversion >= 0x03030000: from contextlib import ExitStack diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index 712dd5f..992ca3a 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -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: diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 7833865..b475b91 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -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__": diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index 4334645..fc2f7c1 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -1,35 +1,35 @@ -#pylint: disable-all +""" +ICC profile tests. +""" + +# unittest doesn't work well with R0904. +# pylint: disable=R0904 + 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 +38,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 +71,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() From 1fe62a9d9e366a333f94d4ec7511cdc7dbddaf19 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 11 Aug 2013 07:34:40 -0400 Subject: [PATCH 026/122] pylint work, #99 --- glymur/codestream.py | 11 +++-- glymur/test/test_codestream.py | 78 +++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 7bd0215..bb3caf6 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -775,12 +775,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, @@ -1203,8 +1206,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 @@ -1213,7 +1216,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 diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py index f0d3e8a..3913d44 100644 --- a/glymur/test/test_codestream.py +++ b/glymur/test/test_codestream.py @@ -1,4 +1,13 @@ -#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 + import os import struct import sys @@ -9,23 +18,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 +42,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() From 2acb8d6c9469682bbea0e076e7adb4a765946750 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 11 Aug 2013 14:49:44 -0400 Subject: [PATCH 027/122] pylint work, #99 --- glymur/test/test_jp2box.py | 310 +++++++++++++++++++++---------------- 1 file changed, 175 insertions(+), 135 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index a563b58..15c0209 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -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'0') - 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) From 0497576e6fb7157ef8bc01e5fa8a46939ea5cb6b Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 11 Aug 2013 19:16:34 -0400 Subject: [PATCH 028/122] pylint work, #99 --- glymur/test/test_jp2k.py | 321 +++++++++++++++++++++------------------ 1 file changed, 177 insertions(+), 144 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 1371a05..8b04dfa 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -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 = 'this is a test' - buffer = buffer.encode() - tfile.write(buffer) + write_buffer = '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,41 @@ 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_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 +235,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 +250,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 +260,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 +322,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 +366,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 +375,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 +401,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 +436,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 +488,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 +498,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 +510,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 +522,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 +538,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 +551,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 +561,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 +628,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 = 'this is a test' + chr(0) - buffer = buffer.encode() - tfile.write(buffer) + write_buffer = 'this is a 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 +660,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 +671,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 = 'this is a test' - buffer = buffer.encode() - tfile2.write(buffer) + write_buffer = 'this is a test' + write_buffer = write_buffer.encode() + tfile2.write(write_buffer) # Now append the codestream. tfile2.write(codestream) @@ -678,10 +710,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 +737,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 +755,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 +765,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(' Date: Sun, 11 Aug 2013 20:08:15 -0400 Subject: [PATCH 029/122] pylint work, #99 --- glymur/test/test_opj_suite_neg.py | 84 +++++---- glymur/test/test_printing.py | 280 ++++++++++++++++-------------- 2 files changed, 197 insertions(+), 167 deletions(-) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index f851926..2f61675 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -2,7 +2,12 @@ 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 + import os import sys import tempfile @@ -13,9 +18,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 +25,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 +35,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 +48,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 +99,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)]) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 50babe2..f533aa4 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -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 = 'this is a test' - buffer = buffer.encode() - tfile2.write(buffer) + wbuffer = 'this is a 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: From 11b29028fc927b1259a54949fa84f225f31895a6 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 11 Aug 2013 20:23:50 -0400 Subject: [PATCH 030/122] pylint work, #99 --- glymur/test/test_conformance.py | 82 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/glymur/test/test_conformance.py b/glymur/test/test_conformance.py index 9e1ad1a..8c022bb 100644 --- a/glymur/test/test_conformance.py +++ b/glymur/test/test_conformance.py @@ -1,9 +1,15 @@ """ 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 + import os +from os.path import join import sys if sys.hexversion < 0x02070000: @@ -11,106 +17,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 +116,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() From fc95b9d54c9563a1d1d94b88ceeaabbaab47f1c3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 12 Aug 2013 06:57:56 -0400 Subject: [PATCH 031/122] pylint work (head is now broken), #99 --- glymur/test/test_opj_suite.py | 176 +++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 78 deletions(-) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 0a15879..4106e94 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -2,14 +2,20 @@ The tests defined here roughly correspond to what is in the OpenJPEG test suite. """ -#pylint: disable-all -from contextlib import contextmanager +# Some test names correspond with openjpeg tests. Long names are ok in this +# case. +# pylint: disable=C0103 + +# unittest fools pylint with "too many public methods" +# pylint: disable=R0904 + +# asserWarns introduced in python 3.2 (python2.7/pylint issue) +# pylint: disable=E1101 + import os -import platform import re import sys -from xml.etree import cElementTree as ET if sys.hexversion < 0x02070000: import unittest2 as unittest @@ -18,13 +24,6 @@ else: import warnings -if sys.hexversion <= 0x03030000: - from mock import patch - from StringIO import StringIO -else: - from unittest.mock import patch - from io import StringIO - import numpy as np from glymur import Jp2k @@ -33,7 +32,6 @@ import glymur from .fixtures import OPENJPEG_VERSION from .fixtures import OPENJP2_IS_V2_OFFICIAL -from .fixtures import * try: data_root = os.environ['OPJ_DATA_ROOT'] @@ -7762,30 +7760,35 @@ class TestSuite15(unittest.TestCase): self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file5(self): + """ETS_JP2_file5""" jfile = os.path.join(data_root, 'input/conformance/file5.jp2') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): + """ETS_JP2_file6""" jfile = os.path.join(data_root, 'input/conformance/file6.jp2') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): + """ETS_JP2_file7""" jfile = os.path.join(data_root, 'input/conformance/file7.jp2') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): + """ETS_JP2_file8""" jfile = os.path.join(data_root, 'input/conformance/file8.jp2') jp2k = Jp2k(jfile) - jpdata = jp2k.read() + jp2k.read() self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): + """ETS_JP2_file9""" jfile = os.path.join(data_root, 'input/conformance/file9.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() @@ -7796,214 +7799,231 @@ class TestSuite15(unittest.TestCase): self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_DEC_Bretagne2_j2k_1_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Bretagne2.j2k') + """test_NR_DEC_Bretagne2_j2k_1_decode""" + jfile = os.path.join(data_root, 'input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/_00042.j2k') + """NR_DEC__00042_j2k_2_decode""" + jfile = os.path.join(data_root, 'input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_123_j2c_3_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/123.j2c') + """NR_DEC_123_j2c_3_decode""" + jfile = os.path.join(data_root, 'input/nonregression/123.j2c') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken_jp2_4_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken.jp2') - with self.assertWarns(UserWarning) as cw: + """NR_DEC_broken_jp2_4_decode""" + jfile = os.path.join(data_root, 'input/nonregression/broken.jp2') + with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) with self.assertRaises(ValueError): - data = jp2.read() + jp2.read() self.assertTrue(True) @unittest.skipIf(re.match('[01]\.[34]', OPENJPEG_VERSION), "Segfaults openjpeg 1.4 and earlier.") def test_NR_DEC_broken2_jp2_5_decode(self): + """NR_DEC_broken2_jp2_5_decode""" # Null pointer access jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2') with self.assertRaises(ValueError): with warnings.catch_warnings(): # Library warning, invalid number of subbands. warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): + """NR_DEC_broken3_jp2_6_decode""" jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2') - with self.assertWarns(UserWarning) as cw: + with self.assertWarns(UserWarning): # colr box has bad length. j = Jp2k(jfile) - with self.assertRaises(ValueError) as ce: - d = j.read() + with self.assertRaises(ValueError): + j.read() @unittest.skipIf(re.match('[01]\.[34]', OPENJPEG_VERSION), "Segfaults openjpeg 1.4 and earlier.") def test_NR_DEC_broken4_jp2_7_decode(self): + """NR_DEC_broken4_jp2_7_decode""" # Null pointer access jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2') with self.assertRaises(ValueError): with warnings.catch_warnings(): # Library warning, invalid number of subbands. warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_bug_j2c_8_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/bug.j2c') - data = Jp2k(jfile).read() + """NR_DEC_bug_j2c_8_decode""" + jfile = os.path.join(data_root, 'input/nonregression/bug.j2c') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxI.j2k') - data = Jp2k(jfile).read() + """NR_DEC_buxI_j2k_9_decode""" + jfile = os.path.join(data_root, 'input/nonregression/buxI.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxR.j2k') - data = Jp2k(jfile).read() + """NR_DEC_buxR_j2k_10_decode""" + jfile = os.path.join(data_root, 'input/nonregression/buxR.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): + """NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode""" relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/cthead1.j2k') - data = Jp2k(jfile).read() + """NR_DEC_cthead1_j2k_12_decode""" + jfile = os.path.join(data_root, 'input/nonregression/cthead1.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): + """NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode""" relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): - # Stream too short, expected SOT. + """Stream too short, expected SOT.""" jfile = os.path.join(data_root, 'input/nonregression/illegalcolortransform.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/j2k32.j2k') - data = Jp2k(jfile).read() + """NR_DEC_j2k32_j2k_15_decode""" + jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): + """NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode""" relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' jfile = os.path.join(data_root, relpath) with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): + """NR_DEC_MarkerIsNotCompliant_j2k_17_decode""" jfile = os.path.join(data_root, 'input/nonregression/MarkerIsNotCompliant.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Marrin.jp2') - data = Jp2k(jfile).read() + """NR_DEC_Marrin_jp2_18_decode""" + jfile = os.path.join(data_root, 'input/nonregression/Marrin.jp2') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): + """test_NR_DEC_movie_00000_j2k_20_decode""" jfile = os.path.join(data_root, 'input/nonregression/movie_00000.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): + """NR_DEC_movie_00001_j2k_21_decode""" jfile = os.path.join(data_root, 'input/nonregression/movie_00001.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00002.j2k') - data = Jp2k(jfile).read() + """NR_DEC_movie_00002_j2k_22_decode""" + jfile = os.path.join(data_root, 'input/nonregression/movie_00002.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): + """NR_DEC_orb_blue_lin_j2k_j2k_23_decode""" jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-lin-j2k.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): + """NR_DEC_orb_blue_win_j2k_j2k_24_decode""" jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-win-j2k.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_orb_blue_lin_jp2_25_decode(self): + def test_nc_dec_orb_blue_lin_jp2_25_decode(self): + """NR-DEC-orb-blue-lin.jp2-25-decode""" jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-lin-jp2.jp2') with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_orb_blue_win_jp2_26_decode(self): + def test_nr_dec_orb_blue_win_jp2_26_decode(self): + """NR-DEC-orb-blue-win.jp2-26-decode""" jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-win-jp2.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_relax_jp2_27_decode(self): + def test_nr_dec_relax_jp2_27_decode(self): + """NR-DEC-relax.jp2-27-decode""" jfile = os.path.join(data_root, 'input/nonregression/relax.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_test_lossless_j2k_28_decode(self): + def test_nr_dec_test_lossless_j2k_28_decode(self): + """NR-DEC-test-lossless.j2k-28-decode""" jfile = os.path.join(data_root, 'input/nonregression/test_lossless.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): + def test_nr_dec_issue104_jpxstream_jp2_33_decode(self): + """NR-DEC-issue104-jpxstream.jp2-33-decode""" jfile = os.path.join(data_root, 'input/nonregression/issue104_jpxstream.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_file_409752_jp2_40_decode(self): + def test_nr_dec_file_409752_jp2_40_decode(self): + """NR-DEC-file-409752.jp2-40-decode""" jfile = os.path.join(data_root, 'input/nonregression/file409752.jp2') j = Jp2k(jfile) - with self.assertRaises(RuntimeError) as ce: - data = j.read() + with self.assertRaises(RuntimeError): + j.read() if __name__ == "__main__": unittest.main() From f55963db81d3164d569b107a20c8292fbc46e013 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 12 Aug 2013 19:22:13 -0400 Subject: [PATCH 032/122] pylint work, exposed mantissa, exponent, guard bits in QCC, QCD issue #99 --- CHANGES.txt | 3 + glymur/codestream.py | 18 +- glymur/test/test_opj_suite.py | 643 +++++++++++++++++----------------- 3 files changed, 336 insertions(+), 328 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 42b5b4b..7283bfb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Aug 11, 2013 - v0.3.1 Exposed mantissa, exponent, and guard_bits fields in QCC + and QCD segments. + Jul 31, 2013 - v0.3.0 Added support for official 2.0.0. Jul 27, 2013 - v0.2.8 Fixed inconsistency regarding configuration diff --git a/glymur/codestream.py b/glymur/codestream.py index bb3caf6..c60bc1b 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -1291,18 +1291,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 @@ -1339,18 +1339,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 diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 4106e94..bfefbc6 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -7,9 +7,23 @@ suite. # case. # pylint: disable=C0103 +# All of these tests correspond to tests in openjpeg, so no docstring is really +# needed. +# pylint: disable=C0111 + +# This module is very long, cannot be helped. +# pylint: disable=C0302 + # unittest fools pylint with "too many public methods" # pylint: disable=R0904 +# Some tests use numpy test infrastructure, which means the tests never +# reference "self", so pylint claims it should be a function. No, no, no. +# pylint: disable=R0201 + +# Many tests are pretty long and that can't be helped. +# pylint: disable=R0915 + # asserWarns introduced in python 3.2 (python2.7/pylint issue) # pylint: disable=E1101 @@ -31,6 +45,7 @@ import glymur from .fixtures import OPENJPEG_VERSION from .fixtures import OPENJP2_IS_V2_OFFICIAL +from .fixtures import mse, peak_tolerance, read_pgx try: @@ -788,14 +803,14 @@ class TestSuite(unittest.TestCase): jfile = os.path.join(data_root, 'input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): jfile = os.path.join(data_root, 'input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") @@ -803,7 +818,7 @@ class TestSuite(unittest.TestCase): jfile = os.path.join(data_root, 'input/nonregression/123.j2c') jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) @unittest.skipIf(sys.hexversion < 0x03020000, @@ -811,11 +826,11 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_broken_jp2_4_decode(self): jfile = os.path.join(data_root, 'input/nonregression/broken.jp2') - with self.assertWarns(UserWarning) as cw: + with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) with self.assertRaises(IOError): - data = jp2.read() + jp2.read() self.assertTrue(True) def test_NR_DEC_broken2_jp2_5_decode(self): @@ -825,66 +840,60 @@ class TestSuite(unittest.TestCase): with warnings.catch_warnings(): # Invalid marker ID. warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken3.jp2') - with self.assertWarns(UserWarning) as cw: + jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2') + with self.assertWarns(UserWarning): # colr box has bad length. j = Jp2k(jfile) - with self.assertRaises(IOError) as ce: - d = j.read() + with self.assertRaises(IOError): + j.read() def test_NR_DEC_broken4_jp2_7_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken4.jp2') + jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2') with self.assertRaises(IOError): with warnings.catch_warnings(): # invalid number of subbands, bad marker ID warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_bug_j2c_8_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/bug.j2c') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/bug.j2c') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxI.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/buxI.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/buxR.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/buxR.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/cthead1.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/cthead1.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") @@ -892,67 +901,64 @@ class TestSuite(unittest.TestCase): # Stream too short, expected SOT. jfile = os.path.join(data_root, 'input/nonregression/illegalcolortransform.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/j2k32.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' jfile = os.path.join(data_root, relpath) - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): jfile = os.path.join(data_root, 'input/nonregression/MarkerIsNotCompliant.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): jfile = os.path.join(data_root, 'input/nonregression/Marrin.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_merged_jp2_19_decode(self): jfile = os.path.join(data_root, 'input/nonregression/merged.jp2') - data = Jp2k(jfile).read_bands() + Jp2k(jfile).read_bands() self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): jfile = os.path.join(data_root, 'input/nonregression/movie_00000.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00001.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/movie_00001.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00002.j2k') - data = Jp2k(jfile).read() + jfile = os.path.join(data_root, 'input/nonregression/movie_00002.j2k') + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-lin-j2k.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-win-j2k.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_jp2_25_decode(self): @@ -961,25 +967,25 @@ class TestSuite(unittest.TestCase): with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_win_jp2_26_decode(self): jfile = os.path.join(data_root, 'input/nonregression/orb-blue10-win-jp2.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_relax_jp2_27_decode(self): jfile = os.path.join(data_root, 'input/nonregression/relax.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_test_lossless_j2k_28_decode(self): jfile = os.path.join(data_root, 'input/nonregression/test_lossless.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, @@ -991,13 +997,13 @@ class TestSuite(unittest.TestCase): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") jp2 = Jp2k(jfile) - data = jp2.read() + jp2.read() self.assertTrue(True) def test_NR_DEC_pacs_ge_j2k_30_decode(self): jfile = os.path.join(data_root, 'input/nonregression/pacs.ge.j2k') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, @@ -1005,7 +1011,7 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): jfile = os.path.join(data_root, 'input/nonregression/kodak_2layers_lrcp.j2c') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, @@ -1013,13 +1019,13 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): jfile = os.path.join(data_root, 'input/nonregression/kodak_2layers_lrcp.j2c') - data = Jp2k(jfile).read(layer=2) + Jp2k(jfile).read(layer=2) self.assertTrue(True) def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): jfile = os.path.join(data_root, 'input/nonregression/issue104_jpxstream.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, @@ -1031,7 +1037,7 @@ class TestSuite(unittest.TestCase): # This file has a bad pclr box, we test for this elsewhere. warnings.simplefilter("ignore") j = Jp2k(jfile) - data = j.read() + j.read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, @@ -1039,7 +1045,7 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): jfile = os.path.join(data_root, 'input/nonregression/mem-b2b86b74-2753.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): @@ -1050,7 +1056,7 @@ class TestSuite(unittest.TestCase): warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): - data = j.read() + j.read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") @@ -1064,7 +1070,7 @@ class TestSuite(unittest.TestCase): warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): - data = j.read() + j.read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") @@ -1076,7 +1082,7 @@ class TestSuite(unittest.TestCase): warnings.simplefilter("ignore") j = Jp2k(jfile) with self.assertRaises(IOError): - data = j.read() + j.read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") @@ -1087,13 +1093,12 @@ class TestSuite(unittest.TestCase): # Invalid subsampling value warnings.simplefilter("ignore") with self.assertRaises(IOError): - j = Jp2k(jfile).read() + Jp2k(jfile).read() def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/file409752.jp2') + jfile = os.path.join(data_root, 'input/nonregression/file409752.jp2') with self.assertRaises(RuntimeError): - data = Jp2k(jfile).read() + Jp2k(jfile).read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") @@ -1104,15 +1109,15 @@ class TestSuite(unittest.TestCase): # really does deserve a warning. relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' jfile = os.path.join(data_root, relpath) - with self.assertWarns(UserWarning) as cw: - data = Jp2k(jfile).read() + with self.assertWarns(UserWarning): + Jp2k(jfile).read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") def test_NR_DEC_issue206_image_000_jp2_42_decode(self): jfile = os.path.join(data_root, 'input/nonregression/issue206_image-000.jp2') - data = Jp2k(jfile).read() + Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_p1_04_j2k_43_decode(self): @@ -1347,8 +1352,8 @@ class TestSuite(unittest.TestCase): # Image size would be 0 x 0. jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) - with self.assertRaises((IOError, OSError)) as ce: - ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=2) + with self.assertRaises((IOError, OSError)): + jp2k.read(area=(9, 9, 12, 12), rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_76_decode(self): @@ -1393,7 +1398,7 @@ class TestSuite(unittest.TestCase): jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=0, rlevel=2) + jp2k.read(tile=0, rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_81_decode(self): @@ -1402,7 +1407,7 @@ class TestSuite(unittest.TestCase): jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=5, rlevel=2) + jp2k.read(tile=5, rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_82_decode(self): @@ -1411,7 +1416,7 @@ class TestSuite(unittest.TestCase): jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") - tiledata = jp2k.read(tile=9, rlevel=2) + jp2k.read(tile=9, rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_83_decode(self): @@ -1420,15 +1425,15 @@ class TestSuite(unittest.TestCase): jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") - with self.assertRaises((IOError, OSError)) as ce: - tiledata = jp2k.read(tile=15, rlevel=2) + with self.assertRaises((IOError, OSError)): + jp2k.read(tile=15, rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_84_decode(self): # Just read the data, don't bother verifying. jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) - data = jp2k.read(rlevel=4) + jp2k.read(rlevel=4) def test_NR_DEC_p0_04_j2k_85_decode(self): jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') @@ -1556,10 +1561,10 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[2].sqcd & 0x1f, 0) - self.assertEqual(c.segment[2]._guard_bits, 2) - self.assertEqual(c.segment[2]._exponent, + self.assertEqual(c.segment[2].guard_bits, 2) + self.assertEqual(c.segment[2].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - self.assertEqual(c.segment[2]._mantissa, + self.assertEqual(c.segment[2].mantissa, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # COD: Coding style default @@ -1663,10 +1668,10 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[4].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[4]._guard_bits, 3) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 3) + self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - self.assertEqual(c.segment[4]._mantissa, + self.assertEqual(c.segment[4].mantissa, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # COM: comment @@ -1749,18 +1754,18 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 1) # scalar implicit - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._exponent, [0]) - self.assertEqual(c.segment[3]._mantissa, [0]) + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].exponent, [0]) + self.assertEqual(c.segment[3].mantissa, [0]) # QCC: Quantization component # associated component self.assertEqual(c.segment[4].cqcc, 0) - self.assertEqual(c.segment[4]._guard_bits, 2) + self.assertEqual(c.segment[4].guard_bits, 2) # quantization type self.assertEqual(c.segment[4].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[4]._exponent, [4, 5, 5, 6]) - self.assertEqual(c.segment[4]._mantissa, [0, 0, 0, 0]) + self.assertEqual(c.segment[4].exponent, [4, 5, 5, 6]) + self.assertEqual(c.segment[4].mantissa, [0, 0, 0, 0]) # POD: progression order change self.assertEqual(c.segment[5].rspod, (0,)) @@ -1869,11 +1874,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # scalar expounded - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].exponent, [16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) @@ -1883,11 +1888,11 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[4].cqcc, 1) # quantization type self.assertEqual(c.segment[4].sqcc & 0x1f, 2) # none - self.assertEqual(c.segment[4]._guard_bits, 3) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 3) + self.assertEqual(c.segment[4].exponent, [14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 9, 9, 9, 9, 9, 9]) - self.assertEqual(c.segment[4]._mantissa, + self.assertEqual(c.segment[4].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) @@ -1897,11 +1902,11 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[5].cqcc, 2) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 2) # none - self.assertEqual(c.segment[5]._guard_bits, 3) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].guard_bits, 3) + self.assertEqual(c.segment[5].exponent, [14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 9, 9, 9, 9, 9, 9]) - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) @@ -2016,11 +2021,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[5].sqcd & 0x1f, 2) # scalar expounded - self.assertEqual(c.segment[5]._guard_bits, 3) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].guard_bits, 3) + self.assertEqual(c.segment[5].exponent, [16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) @@ -2030,20 +2035,20 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[6].cqcc, 0) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 1) # scalar derived - self.assertEqual(c.segment[6]._guard_bits, 3) - self.assertEqual(c.segment[6]._exponent, [14]) - self.assertEqual(c.segment[6]._mantissa, [0]) + self.assertEqual(c.segment[6].guard_bits, 3) + self.assertEqual(c.segment[6].exponent, [14]) + self.assertEqual(c.segment[6].mantissa, [0]) # QCC: Quantization component # associated component self.assertEqual(c.segment[7].cqcc, 3) # quantization type self.assertEqual(c.segment[7].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[7]._guard_bits, 3) - self.assertEqual(c.segment[7]._exponent, + self.assertEqual(c.segment[7].guard_bits, 3) + self.assertEqual(c.segment[7].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) - self.assertEqual(c.segment[7]._mantissa, [0] * 19) + self.assertEqual(c.segment[7].mantissa, [0] * 19) # COM: comment # Registration @@ -2119,11 +2124,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # scalar expounded - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [512, 518, 522, 524, 516, 524, 522, 527, 523, 549, 557, 561, 853, 852, 700, 163, 78, 1508, 1831]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 1, 2, 1]) @@ -2132,11 +2137,11 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[4].cqcc, 1) # quantization type self.assertEqual(c.segment[4].sqcc & 0x1f, 2) # scalar derived - self.assertEqual(c.segment[4]._guard_bits, 4) - self.assertEqual(c.segment[4]._mantissa, + self.assertEqual(c.segment[4].guard_bits, 4) + self.assertEqual(c.segment[4].mantissa, [1527, 489, 665, 506, 487, 502, 493, 493, 500, 485, 505, 491, 490, 491, 499, 509, 503, 496, 558]) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].exponent, [10, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5]) @@ -2145,11 +2150,11 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[5].cqcc, 2) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 2) # scalar derived - self.assertEqual(c.segment[5]._guard_bits, 5) - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].guard_bits, 5) + self.assertEqual(c.segment[5].mantissa, [1337, 728, 890, 719, 716, 726, 700, 718, 704, 704, 712, 712, 717, 719, 701, 749, 753, 718, 841]) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].exponent, [10, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5]) @@ -2158,9 +2163,9 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[6].cqcc, 3) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[6]._guard_bits, 6) - self.assertEqual(c.segment[6]._mantissa, [0] * 19) - self.assertEqual(c.segment[6]._exponent, + self.assertEqual(c.segment[6].guard_bits, 6) + self.assertEqual(c.segment[6].mantissa, [0] * 19) + self.assertEqual(c.segment[6].exponent, [12, 13, 13, 14, 13, 13, 14, 13, 13, 14, 13, 13, 14, 13, 13, 14, 13, 13, 14]) @@ -2256,9 +2261,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 10) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 10) + self.assertEqual(c.segment[3].exponent, [14, 15, 15, 16, 15, 15, 16, 15, 15, 16]) # COM: comment @@ -2401,9 +2406,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[6].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[6]._guard_bits, 4) - self.assertEqual(c.segment[6]._mantissa, [0] * 22) - self.assertEqual(c.segment[6]._exponent, + self.assertEqual(c.segment[6].guard_bits, 4) + self.assertEqual(c.segment[6].mantissa, [0] * 22) + self.assertEqual(c.segment[6].exponent, [11, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13]) @@ -2412,9 +2417,9 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[7].cqcc, 0) # quantization type self.assertEqual(c.segment[7].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[7]._guard_bits, 4) - self.assertEqual(c.segment[7]._mantissa, [0] * 19) - self.assertEqual(c.segment[7]._exponent, + self.assertEqual(c.segment[7].guard_bits, 4) + self.assertEqual(c.segment[7].mantissa, [0] * 19) + self.assertEqual(c.segment[7].exponent, [11, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13]) @@ -2423,9 +2428,9 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[8].cqcc, 2) # quantization type self.assertEqual(c.segment[8].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[8]._guard_bits, 4) - self.assertEqual(c.segment[8]._mantissa, [0] * 25) - self.assertEqual(c.segment[8]._exponent, + self.assertEqual(c.segment[8].guard_bits, 4) + self.assertEqual(c.segment[8].mantissa, [0] * 25) + self.assertEqual(c.segment[8].exponent, [11, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13]) @@ -2494,11 +2499,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # scalar expounded - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [1915, 1884, 1884, 1853, 1884, 1884, 1853, 1962, 1962, 1986, 53, 53, 120, 26, 26, 1983]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 12, 12, 12, 11, 11, 12]) @@ -2574,9 +2579,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 0) - self.assertEqual(c.segment[3]._mantissa, [0] * 10) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 0) + self.assertEqual(c.segment[3].mantissa, [0] * 10) + self.assertEqual(c.segment[3].exponent, [11, 12, 12, 13, 12, 12, 13, 12, 12, 13]) # SOT: start of tile part @@ -2715,9 +2720,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, [0]) - self.assertEqual(c.segment[3]._exponent, [8]) + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [0]) + self.assertEqual(c.segment[3].exponent, [8]) # COM: comment # Registration @@ -2796,9 +2801,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, [0] * 10) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [0] * 10) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) # COM: comment @@ -2896,28 +2901,28 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[4].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[4]._guard_bits, 2) - self.assertEqual(c.segment[4]._mantissa, [0] * 4) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 2) + self.assertEqual(c.segment[4].mantissa, [0] * 4) + self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10]) # QCC: Quantization component # associated component self.assertEqual(c.segment[5].cqcc, 1) - self.assertEqual(c.segment[5]._guard_bits, 3) + self.assertEqual(c.segment[5].guard_bits, 3) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[5]._exponent, [9, 10, 10, 11]) - self.assertEqual(c.segment[5]._mantissa, [0, 0, 0, 0]) + self.assertEqual(c.segment[5].exponent, [9, 10, 10, 11]) + self.assertEqual(c.segment[5].mantissa, [0, 0, 0, 0]) # QCC: Quantization component # associated component self.assertEqual(c.segment[6].cqcc, 2) - self.assertEqual(c.segment[6]._guard_bits, 2) + self.assertEqual(c.segment[6].guard_bits, 2) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[6]._exponent, [9, 10, 10, 11]) - self.assertEqual(c.segment[6]._mantissa, [0, 0, 0, 0]) + self.assertEqual(c.segment[6].exponent, [9, 10, 10, 11]) + self.assertEqual(c.segment[6].mantissa, [0, 0, 0, 0]) # RGN: region of interest self.assertEqual(c.segment[7].crgn, 3) @@ -3003,9 +3008,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [10, 11, 11, 12, 11, 11, 12, 11, 11, 12, 11, 11, 12, 11, 11, 12]) @@ -3079,18 +3084,18 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 1) # derived - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0]) - self.assertEqual(c.segment[3]._exponent, [0]) + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0]) + self.assertEqual(c.segment[3].exponent, [0]) # QCC: Quantization component # associated component self.assertEqual(c.segment[4].cqcc, 0) - self.assertEqual(c.segment[4]._guard_bits, 2) + self.assertEqual(c.segment[4].guard_bits, 2) # quantization type self.assertEqual(c.segment[4].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[4]._mantissa, [0] * 4) - self.assertEqual(c.segment[4]._exponent, [4, 5, 5, 6]) + self.assertEqual(c.segment[4].mantissa, [0] * 4) + self.assertEqual(c.segment[4].exponent, [4, 5, 5, 6]) # POD: progression order change self.assertEqual(c.segment[5].rspod, (0,)) @@ -3233,9 +3238,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 10) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 10) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) # SOT: start of tile part @@ -3320,9 +3325,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[4].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[4]._guard_bits, 3) - self.assertEqual(c.segment[4]._mantissa, [0] * 10) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 3) + self.assertEqual(c.segment[4].mantissa, [0] * 10) + self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10]) # COM: comment @@ -3404,40 +3409,40 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) # QCC: Quantization component # associated component self.assertEqual(c.segment[4].cqcc, 1) - self.assertEqual(c.segment[4]._guard_bits, 3) + self.assertEqual(c.segment[4].guard_bits, 3) # quantization type self.assertEqual(c.segment[4].sqcc & 0x1f, 2) # expounded - self.assertEqual(c.segment[4]._mantissa, + self.assertEqual(c.segment[4].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].exponent, [14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 9, 9, 9, 9, 9, 9]) # QCC: Quantization component # associated component self.assertEqual(c.segment[5].cqcc, 2) - self.assertEqual(c.segment[5]._guard_bits, 3) + self.assertEqual(c.segment[5].guard_bits, 3) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 2) # expounded - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].exponent, [14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 9, 9, 9, 9, 9, 9]) @@ -3554,32 +3559,32 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[5].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[5]._guard_bits, 3) - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].guard_bits, 3) + self.assertEqual(c.segment[5].mantissa, [1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].exponent, [16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) # QCC: Quantization component # associated component self.assertEqual(c.segment[6].cqcc, 0) - self.assertEqual(c.segment[6]._guard_bits, 3) + self.assertEqual(c.segment[6].guard_bits, 3) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 1) # derived - self.assertEqual(c.segment[6]._mantissa, [0]) - self.assertEqual(c.segment[6]._exponent, [14]) + self.assertEqual(c.segment[6].mantissa, [0]) + self.assertEqual(c.segment[6].exponent, [14]) # QCC: Quantization component # associated component self.assertEqual(c.segment[7].cqcc, 3) - self.assertEqual(c.segment[7]._guard_bits, 3) + self.assertEqual(c.segment[7].guard_bits, 3) # quantization type self.assertEqual(c.segment[7].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[7]._mantissa, [0] * 19) - self.assertEqual(c.segment[7]._exponent, + self.assertEqual(c.segment[7].mantissa, [0] * 19) + self.assertEqual(c.segment[7].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) @@ -3662,10 +3667,10 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [84, 423, 408, 435, 450, 435, 470, 549, 520, 618]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [8, 10, 10, 10, 9, 9, 9, 8, 8, 8]) # TLM (tile-part length) @@ -3705,11 +3710,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[9].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[9]._guard_bits, 2) - self.assertEqual(c.segment[9]._mantissa, + self.assertEqual(c.segment[9].guard_bits, 2) + self.assertEqual(c.segment[9].mantissa, [75, 1093, 1098, 1115, 1157, 1134, 1186, 1217, 1245, 1248]) - self.assertEqual(c.segment[9]._exponent, + self.assertEqual(c.segment[9].exponent, [8, 10, 10, 10, 9, 9, 9, 8, 8, 8]) # SOD: start of data @@ -3787,12 +3792,12 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[2].precinct_size, [(16, 16)] * 8) self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [1813, 1814, 1814, 1814, 1815, 1815, 1817, 1821, 1821, 1827, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [17, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) @@ -3877,11 +3882,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) # expounded - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [1821, 1845, 1845, 1868, 1925, 1925, 2007, 32, 32, 131, 2002, 2002, 1888]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [14, 14, 14, 14, 13, 13, 13, 11, 11, 11, 11, 11, 11]) @@ -3990,9 +3995,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[4].sqcd & 0x1f, 0) # none - self.assertEqual(c.segment[4]._guard_bits, 2) - self.assertEqual(c.segment[4]._mantissa, [0] * 4) - self.assertEqual(c.segment[4]._exponent, [8, 9, 9, 10]) + self.assertEqual(c.segment[4].guard_bits, 2) + self.assertEqual(c.segment[4].mantissa, [0] * 4) + self.assertEqual(c.segment[4].exponent, [8, 9, 9, 10]) # COM: comment # Registration @@ -4514,11 +4519,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [1824, 1776, 1776, 1728, 1792, 1792, 1760, 1872, 1872, 1896, 5, 5, 71, 2003, 2003, 1890]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 14, 14, 14, 14, 14, 14]) @@ -4544,13 +4549,13 @@ class TestSuiteDump(unittest.TestCase): # QCC: Quantization component # associated component self.assertEqual(c.segment[5].cqcc, 1) - self.assertEqual(c.segment[5]._guard_bits, 2) + self.assertEqual(c.segment[5].guard_bits, 2) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 2) - self.assertEqual(c.segment[5]._mantissa, + self.assertEqual(c.segment[5].mantissa, [1824, 1776, 1776, 1728, 1792, 1792, 1760, 1872, 1872, 1896, 5, 5, 71, 2003, 2003, 1890]) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].exponent, [18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 14, 14, 14, 14, 14, 14]) @@ -4576,13 +4581,13 @@ class TestSuiteDump(unittest.TestCase): # QCC: Quantization component # associated component self.assertEqual(c.segment[7].cqcc, 2) - self.assertEqual(c.segment[7]._guard_bits, 2) + self.assertEqual(c.segment[7].guard_bits, 2) # quantization type self.assertEqual(c.segment[7].sqcc & 0x1f, 2) # none - self.assertEqual(c.segment[7]._mantissa, + self.assertEqual(c.segment[7].mantissa, [1824, 1776, 1776, 1728, 1792, 1792, 1760, 1872, 1872, 1896, 5, 5, 71, 2003, 2003, 1890]) - self.assertEqual(c.segment[7]._exponent, + self.assertEqual(c.segment[7].exponent, [18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 14, 14, 14, 14, 14, 14]) @@ -4837,9 +4842,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 4) - self.assertEqual(c.segment[3]._mantissa, [0] * 34) - self.assertEqual(c.segment[3]._exponent, [16] + [17, 17, 18] * 11) + self.assertEqual(c.segment[3].guard_bits, 4) + self.assertEqual(c.segment[3].mantissa, [0] * 34) + self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_CT_Phillips_JPEG2K_Decompr_Problem_dump(self): jfile = os.path.join(data_root, @@ -4899,11 +4904,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [442, 422, 422, 403, 422, 422, 403, 472, 472, 487, 591, 591, 676, 558, 558, 485]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [22, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18]) @@ -4970,9 +4975,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [9, 10, 10, 11, 10, 10, 11, 10, 10, 11, 10, 10, 10, 9, 9, 10]) @@ -5047,9 +5052,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 4) - self.assertEqual(c.segment[3]._mantissa, [0] * 34) - self.assertEqual(c.segment[3]._exponent, [16] + [17, 17, 18] * 11) + self.assertEqual(c.segment[3].guard_bits, 4) + self.assertEqual(c.segment[3].mantissa, [0] * 34) + self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_j2k32_dump(self): jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') @@ -5107,9 +5112,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default # quantization type self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) # COM: comment @@ -5172,9 +5177,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 25) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 25) + self.assertEqual(c.segment[3].exponent, [17, 18, 18, 19, 18, 18, 19, 18, 18, 19, 18, 18, 19, 18, 18, 19, 18, 18, 19, 18, 18, 19, 18, 18, 19]) @@ -5257,9 +5262,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 4) - self.assertEqual(c.segment[3]._mantissa, [0] * 34) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 4) + self.assertEqual(c.segment[3].mantissa, [0] * 34) + self.assertEqual(c.segment[3].exponent, [16, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18, 17, 17, 18]) @@ -5317,9 +5322,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_movie_00001(self): @@ -5375,9 +5380,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_movie_00002(self): @@ -5433,9 +5438,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_lin_j2k_dump(self): @@ -5494,9 +5499,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_win_j2k_dump(self): @@ -5555,9 +5560,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_pacs_ge_j2k_dump(self): @@ -5615,9 +5620,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [18, 19, 19, 20, 19, 19, 20, 19, 19, 20, 19, 19, 20, 19, 19, 20]) @@ -5685,9 +5690,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [12, 13, 13, 14, 13, 13, 14, 13, 13, 14, 13, 13, 14, 13, 13, 14]) @@ -5755,9 +5760,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 4) - self.assertEqual(c.segment[3]._mantissa, [0] * 34) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 4) + self.assertEqual(c.segment[3].mantissa, [0] * 34) + self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_bug_j2c_dump(self): @@ -5817,9 +5822,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 4) - self.assertEqual(c.segment[3]._mantissa, [0] * 34) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 4) + self.assertEqual(c.segment[3].mantissa, [0] * 34) + self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_kodak_2layers_lrcp_j2c_dump(self): @@ -5881,9 +5886,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [13, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13]) @@ -5899,7 +5904,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_broken_jp2_dump(self): jfile = os.path.join(data_root, 'input/nonregression/broken.jp2') - with self.assertWarns(UserWarning) as cw: + with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -5996,29 +6001,29 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[4].sqcd & 0x1f, 0) - self.assertEqual(c.segment[4]._guard_bits, 2) - self.assertEqual(c.segment[4]._mantissa, [0] * 16) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 2) + self.assertEqual(c.segment[4].mantissa, [0] * 16) + self.assertEqual(c.segment[4].exponent, [8] + [9, 9, 10] * 5) # QCC: Quantization component # associated component self.assertEqual(c.segment[5].cqcc, 1) - self.assertEqual(c.segment[5]._guard_bits, 2) + self.assertEqual(c.segment[5].guard_bits, 2) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[5]._mantissa, [0] * 16) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].mantissa, [0] * 16) + self.assertEqual(c.segment[5].exponent, [8] + [9, 9, 10] * 5) # QCC: Quantization component # associated component self.assertEqual(c.segment[6].cqcc, 2) - self.assertEqual(c.segment[6]._guard_bits, 2) + self.assertEqual(c.segment[6].guard_bits, 2) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[6]._mantissa, [0] * 16) - self.assertEqual(c.segment[6]._exponent, + self.assertEqual(c.segment[6].mantissa, [0] * 16) + self.assertEqual(c.segment[6].exponent, [8] + [9, 9, 10] * 5) @unittest.skipIf(sys.hexversion < 0x03020000, @@ -6036,7 +6041,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_broken3_jp2_dump(self): jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2') - with self.assertWarns(UserWarning) as cw: + with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -6133,29 +6138,29 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[4].sqcd & 0x1f, 0) - self.assertEqual(c.segment[4]._guard_bits, 2) - self.assertEqual(c.segment[4]._mantissa, [0] * 16) - self.assertEqual(c.segment[4]._exponent, + self.assertEqual(c.segment[4].guard_bits, 2) + self.assertEqual(c.segment[4].mantissa, [0] * 16) + self.assertEqual(c.segment[4].exponent, [8] + [9, 9, 10] * 5) # QCC: Quantization component # associated component self.assertEqual(c.segment[5].cqcc, 1) - self.assertEqual(c.segment[5]._guard_bits, 2) + self.assertEqual(c.segment[5].guard_bits, 2) # quantization type self.assertEqual(c.segment[5].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[5]._mantissa, [0] * 16) - self.assertEqual(c.segment[5]._exponent, + self.assertEqual(c.segment[5].mantissa, [0] * 16) + self.assertEqual(c.segment[5].exponent, [8] + [9, 9, 10] * 5) # QCC: Quantization component # associated component self.assertEqual(c.segment[6].cqcc, 2) - self.assertEqual(c.segment[6]._guard_bits, 2) + self.assertEqual(c.segment[6].guard_bits, 2) # quantization type self.assertEqual(c.segment[6].sqcc & 0x1f, 0) # none - self.assertEqual(c.segment[6]._mantissa, [0] * 16) - self.assertEqual(c.segment[6]._exponent, + self.assertEqual(c.segment[6].mantissa, [0] * 16) + self.assertEqual(c.segment[6].exponent, [8] + [9, 9, 10] * 5) @unittest.skipIf(sys.hexversion < 0x03020000, @@ -6259,11 +6264,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [1816, 1792, 1792, 1724, 1770, 1770, 1724, 1868, 1868, 1892, 3, 3, 69, 2002, 2002, 1889]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [13] * 4 + [12] * 3 + [11] * 3 + [9] * 6) @unittest.skipIf(sys.hexversion < 0x03020000, @@ -6273,7 +6278,7 @@ class TestSuiteDump(unittest.TestCase): 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2'] jfile = os.path.join(data_root, '/'.join(lst)) with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) + Jp2k(jfile) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") @@ -6281,7 +6286,7 @@ class TestSuiteDump(unittest.TestCase): lst = ['input', 'nonregression', 'gdal_fuzzer_check_comp_dx_dy.jp2'] jfile = os.path.join(data_root, '/'.join(lst)) with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) + Jp2k(jfile) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") @@ -6291,7 +6296,7 @@ class TestSuiteDump(unittest.TestCase): 'gdal_fuzzer_check_number_of_tiles.jp2'] jfile = os.path.join(data_root, '/'.join(lst)) with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) + Jp2k(jfile) @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") @@ -6301,7 +6306,7 @@ class TestSuiteDump(unittest.TestCase): 'gdal_fuzzer_unchecked_numresolutions.jp2'] jfile = os.path.join(data_root, '/'.join(lst)) with self.assertWarns(UserWarning): - jp2 = Jp2k(jfile) + Jp2k(jfile) def test_NR_issue104_jpxstream_dump(self): jfile = os.path.join(data_root, @@ -6413,9 +6418,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [8] + [9, 9, 10] * 5) + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8] + [9, 9, 10] * 5) def test_NR_issue188_beach_64bitsbox(self): lst = ['input', 'nonregression', 'issue188_beach_64bitsbox.jp2'] @@ -6514,7 +6519,7 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 1) + self.assertEqual(c.segment[3].guard_bits, 1) def test_NR_issue206_image_000_dump(self): jfile = os.path.join(data_root, @@ -6613,9 +6618,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [8] + [9, 9, 10] * 5) + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8] + [9, 9, 10] * 5) def test_NR_Marrin_jp2_dump(self): jfile = os.path.join(data_root, @@ -6717,11 +6722,11 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 2) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [1822, 1770, 1770, 1724, 1792, 1792, 1762, 1868, 1868, 1892, 3, 3, 69, 2002, 2002, 1889]) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].exponent, [14] * 4 + [13] * 3 + [12] * 3 + [10] * 6) # COM: comment @@ -6845,9 +6850,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 3) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [1] + [2, 2, 3] * 5) + self.assertEqual(c.segment[3].guard_bits, 3) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [1] + [2, 2, 3] * 5) def test_NR_mem_b2b86b74_2753_dump(self): jfile = os.path.join(data_root, @@ -6960,9 +6965,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [4] + [5, 5, 6] * 5) + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [4] + [5, 5, 6] * 5) def test_NR_merged_dump(self): jfile = os.path.join(data_root, 'input/nonregression/merged.jp2') @@ -7054,9 +7059,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 1) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, [8] + [9, 9, 10] * 5) + self.assertEqual(c.segment[3].guard_bits, 1) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8] + [9, 9, 10] * 5) # POD: progression order change self.assertEqual(c.segment[4].rspod, (0, 0)) @@ -7163,9 +7168,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_win_jp2_dump(self): @@ -7263,9 +7268,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_text_GBR_dump(self): @@ -7375,9 +7380,9 @@ class TestSuiteDump(unittest.TestCase): # QCD: Quantization default self.assertEqual(c.segment[3].sqcd & 0x1f, 0) - self.assertEqual(c.segment[3]._guard_bits, 2) - self.assertEqual(c.segment[3]._mantissa, [0] * 16) - self.assertEqual(c.segment[3]._exponent, + self.assertEqual(c.segment[3].guard_bits, 2) + self.assertEqual(c.segment[3].mantissa, [0] * 16) + self.assertEqual(c.segment[3].exponent, [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) @@ -7763,28 +7768,28 @@ class TestSuite15(unittest.TestCase): """ETS_JP2_file5""" jfile = os.path.join(data_root, 'input/conformance/file5.jp2') jp2k = Jp2k(jfile) - jp2k.read() + jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): """ETS_JP2_file6""" jfile = os.path.join(data_root, 'input/conformance/file6.jp2') jp2k = Jp2k(jfile) - jp2k.read() + jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): """ETS_JP2_file7""" jfile = os.path.join(data_root, 'input/conformance/file7.jp2') jp2k = Jp2k(jfile) - jp2k.read() + jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): """ETS_JP2_file8""" jfile = os.path.join(data_root, 'input/conformance/file8.jp2') jp2k = Jp2k(jfile) - jp2k.read() + jpdata = jp2k.read() self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): @@ -7792,7 +7797,7 @@ class TestSuite15(unittest.TestCase): jfile = os.path.join(data_root, 'input/conformance/file9.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() - if re.match('[01]\.3', OPENJPEG_VERSION): + if re.match(r'[01]\.3', OPENJPEG_VERSION): # Version 1.3 reads in the image as the palette indices. self.assertEqual(jpdata.shape, (512, 768)) else: @@ -7832,7 +7837,7 @@ class TestSuite15(unittest.TestCase): jp2.read() self.assertTrue(True) - @unittest.skipIf(re.match('[01]\.[34]', OPENJPEG_VERSION), + @unittest.skipIf(re.match(r'[01]\.[34]', OPENJPEG_VERSION), "Segfaults openjpeg 1.4 and earlier.") def test_NR_DEC_broken2_jp2_5_decode(self): """NR_DEC_broken2_jp2_5_decode""" @@ -7857,7 +7862,7 @@ class TestSuite15(unittest.TestCase): with self.assertRaises(ValueError): j.read() - @unittest.skipIf(re.match('[01]\.[34]', OPENJPEG_VERSION), + @unittest.skipIf(re.match(r'[01]\.[34]', OPENJPEG_VERSION), "Segfaults openjpeg 1.4 and earlier.") def test_NR_DEC_broken4_jp2_7_decode(self): """NR_DEC_broken4_jp2_7_decode""" From 4db8763056989460425b8f1301e0d7123db38b5e Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 12 Aug 2013 20:12:23 -0400 Subject: [PATCH 033/122] Refactored out read_common, remove ambiguity on return type. It was the case that _read_common could return either a list, a view, or an image cube depending upon the jp2 subsampling or the image dimensions. No more. Closed #100 --- glymur/jp2k.py | 156 +++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 75 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 37cad71..ea3c859 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -686,12 +686,12 @@ class Jp2k(Jp2kBox): if data.shape[2] == 1: # The third dimension has just a single layer. Make the image # data 2D instead of 3D. - data = data.view() data.shape = data.shape[0:2] return data - def _read_openjp2(self, **kwargs): + def _read_openjp2(self, rlevel=0, layer=0, area=None, tile=None, + verbose=False): """Read a JPEG 2000 image using libopenjp2. Parameters @@ -721,10 +721,46 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - img_array = self._read_common(as_bands=False, **kwargs) + dparam = self._populate_dparam(layer, rlevel, area, tile) + + with ExitStack() as stack: + if hasattr(opj2.OPENJP2, + 'opj_stream_create_default_file_stream_v3'): + filename = self.filename + stream = opj2.stream_create_default_file_stream_v3(filename, + True) + stack.callback(opj2.stream_destroy_v3, stream) + else: + fptr = libc.fopen(self.filename, 'rb') + stack.callback(libc.fclose, fptr) + stream = opj2.stream_create_default_file_stream(fptr, True) + stack.callback(opj2.stream_destroy, stream) + codec = opj2.create_decompress(self._codec_format) + stack.callback(opj2.destroy_codec, codec) + + opj2.set_error_handler(codec, _ERROR_CALLBACK) + opj2.set_warning_handler(codec, _WARNING_CALLBACK) + if verbose: + opj2.set_info_handler(codec, _INFO_CALLBACK) + else: + opj2.set_info_handler(codec, None) + + opj2.setup_decoder(codec, dparam) + image = opj2.read_header(stream, codec) + stack.callback(opj2.image_destroy, image) + + if dparam.nb_tile_to_decode: + opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) + else: + opj2.set_decode_area(codec, image, + dparam.DA_x0, dparam.DA_y0, + dparam.DA_x1, dparam.DA_y1) + opj2.decode(codec, stream, image) + opj2.end_decompress(codec, stream) + + img_array = extract_image_cube(image) if img_array.shape[2] == 1: - img_array = img_array.view() img_array.shape = img_array.shape[0:2] return img_array @@ -782,76 +818,8 @@ class Jp2k(Jp2kBox): return dparam - def _read_common(self, rlevel=0, layer=0, area=None, tile=None, - verbose=False, as_bands=False): - """Read a JPEG 2000 image. - - Parameters - ---------- - layer : int, optional - Number of quality layer to decode. - rlevel : int, optional - Factor by which to rlevel output resolution. - area : tuple, optional - Specifies decoding image area, - (first_row, first_col, last_row, last_col) - tile : int, optional - Number of tile to decode. - verbose : bool, optional - Print informational messages produced by the OpenJPEG library. - as_bands : bool, optional - If true, return the individual 2D components in a list. - - Returns - ------- - img_array : ndarray - The individual image components or a single array. - """ - dparam = self._populate_dparam(layer, rlevel, area, tile) - - with ExitStack() as stack: - if hasattr(opj2.OPENJP2, - 'opj_stream_create_default_file_stream_v3'): - filename = self.filename - stream = opj2.stream_create_default_file_stream_v3(filename, - True) - stack.callback(opj2.stream_destroy_v3, stream) - else: - fptr = libc.fopen(self.filename, 'rb') - stack.callback(libc.fclose, fptr) - stream = opj2.stream_create_default_file_stream(fptr, True) - stack.callback(opj2.stream_destroy, stream) - codec = opj2.create_decompress(self._codec_format) - stack.callback(opj2.destroy_codec, codec) - - opj2.set_error_handler(codec, _ERROR_CALLBACK) - opj2.set_warning_handler(codec, _WARNING_CALLBACK) - if verbose: - opj2.set_info_handler(codec, _INFO_CALLBACK) - else: - opj2.set_info_handler(codec, None) - - opj2.setup_decoder(codec, dparam) - image = opj2.read_header(stream, codec) - stack.callback(opj2.image_destroy, image) - - if dparam.nb_tile_to_decode: - opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) - else: - opj2.set_decode_area(codec, image, - dparam.DA_x0, dparam.DA_y0, - dparam.DA_x1, dparam.DA_y1) - opj2.decode(codec, stream, image) - opj2.end_decompress(codec, stream) - - if as_bands: - data = extract_image_bands(image) - else: - data = extract_image_cube(image) - - return data - - def read_bands(self, **kwargs): + def read_bands(self, rlevel=0, layer=0, area=None, tile=None, + verbose=False): """Read a JPEG 2000 image. The only time you should use this method is when the image has @@ -898,7 +866,45 @@ class Jp2k(Jp2kBox): "of OpenJP2 installed before using " "this functionality.") - lst = self._read_common(as_bands=True, **kwargs) + dparam = self._populate_dparam(layer, rlevel, area, tile) + + with ExitStack() as stack: + if hasattr(opj2.OPENJP2, + 'opj_stream_create_default_file_stream_v3'): + filename = self.filename + stream = opj2.stream_create_default_file_stream_v3(filename, + True) + stack.callback(opj2.stream_destroy_v3, stream) + else: + fptr = libc.fopen(self.filename, 'rb') + stack.callback(libc.fclose, fptr) + stream = opj2.stream_create_default_file_stream(fptr, True) + stack.callback(opj2.stream_destroy, stream) + codec = opj2.create_decompress(self._codec_format) + stack.callback(opj2.destroy_codec, codec) + + opj2.set_error_handler(codec, _ERROR_CALLBACK) + opj2.set_warning_handler(codec, _WARNING_CALLBACK) + if verbose: + opj2.set_info_handler(codec, _INFO_CALLBACK) + else: + opj2.set_info_handler(codec, None) + + opj2.setup_decoder(codec, dparam) + image = opj2.read_header(stream, codec) + stack.callback(opj2.image_destroy, image) + + if dparam.nb_tile_to_decode: + opj2.get_decoded_tile(codec, stream, image, dparam.tile_index) + else: + opj2.set_decode_area(codec, image, + dparam.DA_x0, dparam.DA_y0, + dparam.DA_x1, dparam.DA_y1) + opj2.decode(codec, stream, image) + opj2.end_decompress(codec, stream) + + lst = extract_image_bands(image) + return lst def get_codestream(self, header_only=True): From 6f964ce1468e25689027f75db9ad5b98d9ce5cdc Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 12 Aug 2013 20:31:48 -0400 Subject: [PATCH 034/122] Closes #101 --- glymur/jp2k.py | 2 +- glymur/test/test_jp2k.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index ea3c859..2994742 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -238,7 +238,7 @@ class Jp2k(Jp2kBox): outfile += b'0' * num_pad_bytes cparams.outfile = outfile - if self.filename[-4:].lower() == '.jp2': + if self.filename[-4:].endswith(('.jp2', '.JP2')): cparams.codec_fmt = opj2.CODEC_JP2 else: cparams.codec_fmt = opj2.CODEC_J2K diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 8b04dfa..c018897 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -224,6 +224,17 @@ class TestJp2k(unittest.TestCase): filename = 'this file does not actually exist on the file system.' Jp2k(filename) + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_write_with_JP2_suffix(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""" From 3753dc5e60edb99abdc3a54355303aa05588b95e Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 13 Aug 2013 06:53:59 -0400 Subject: [PATCH 035/122] pylint work, #99 --- glymur/lib/config.py | 3 +++ glymur/lib/test/test_openjp2.py | 4 ++++ glymur/lib/test/test_openjpeg.py | 7 +++++-- glymur/test/test_codestream.py | 3 +++ glymur/test/test_conformance.py | 2 ++ glymur/test/test_icc.py | 3 +++ glymur/test/test_opj_suite.py | 3 +++ glymur/test/test_opj_suite_neg.py | 3 +++ glymur/test/test_opj_suite_write.py | 4 ++++ 9 files changed, 30 insertions(+), 2 deletions(-) diff --git a/glymur/lib/config.py b/glymur/lib/config.py index e2b780a..e3a5c1d 100644 --- a/glymur/lib/config.py +++ b/glymur/lib/config.py @@ -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 diff --git a/glymur/lib/test/test_openjp2.py b/glymur/lib/test/test_openjp2.py index 13c5975..54d8254 100644 --- a/glymur/lib/test/test_openjp2.py +++ b/glymur/lib/test/test_openjp2.py @@ -4,6 +4,10 @@ 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 sys import tempfile diff --git a/glymur/lib/test/test_openjpeg.py b/glymur/lib/test/test_openjpeg.py index 5363a1f..91e6d84 100644 --- a/glymur/lib/test/test_openjpeg.py +++ b/glymur/lib/test/test_openjpeg.py @@ -1,6 +1,11 @@ """ 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 @@ -12,8 +17,6 @@ else: import glymur -# pylint: disable=E1101,R0904 - @unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, "Missing openjpeg library.") class TestOpenJPEG(unittest.TestCase): diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py index 3913d44..f9d4d75 100644 --- a/glymur/test/test_codestream.py +++ b/glymur/test/test_codestream.py @@ -8,6 +8,9 @@ Test suite for codestream parsing. # 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 diff --git a/glymur/test/test_conformance.py b/glymur/test/test_conformance.py index 8c022bb..3c7c9c4 100644 --- a/glymur/test/test_conformance.py +++ b/glymur/test/test_conformance.py @@ -7,6 +7,8 @@ These tests deal with JPX/JP2/J2K images in the format-corpus repository. # 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 diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index fc2f7c1..bf589a5 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -5,6 +5,9 @@ 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 sys diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index bfefbc6..a264019 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -27,6 +27,9 @@ suite. # asserWarns introduced in python 3.2 (python2.7/pylint issue) # pylint: disable=E1101 +# unittest2 is python2.6 only (pylint/python-2.7) +# pylint: disable=F0401 + import os import re import sys diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 2f61675..e8675aa 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -8,6 +8,9 @@ seem like logical negative tests to add. # 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 diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 09722dc..6cc37f3 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -5,6 +5,10 @@ suite. # C0103: method names longer that 30 chars are ok in tests, IMHO # R0904: Seems like pylint is fooled in this situation # pylint: disable=R0904,C0103 + +# unittest2 is python2.6 only (pylint/python-2.7) +# pylint: disable=F0401 + import os import sys import tempfile From b8fe75984e3bb618e22afe2f58a3a71a98bd8c02 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 13 Aug 2013 18:46:47 -0400 Subject: [PATCH 036/122] pylint work, closes #99 --- CHANGES.txt | 5 +- glymur/__init__.py | 2 + glymur/codestream.py | 22 +++++++- glymur/jp2k.py | 105 ++++++++++++++++++++------------------- glymur/test/test_jp2k.py | 2 +- 5 files changed, 80 insertions(+), 56 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 7283bfb..1874042 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,6 @@ -Aug 11, 2013 - v0.3.1 Exposed mantissa, exponent, and guard_bits fields in QCC - and QCD segments. +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. diff --git a/glymur/__init__.py b/glymur/__init__.py index fb1c504..cc80a72 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -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. """ diff --git a/glymur/codestream.py b/glymur/codestream.py index c60bc1b..7a32190 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -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 @@ -1276,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 ---------- @@ -1323,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 ---------- diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 2994742..ea8ef5e 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -4,10 +4,14 @@ License: MIT """ import sys + +# Exitstack not found in contextlib in 2.7 +# pylint: disable=E0611 if sys.hexversion >= 0x03030000: from contextlib import ExitStack else: from contextlib2 import ExitStack + import ctypes import math import os @@ -22,63 +26,13 @@ from .core import GREYSCALE from .core import PROGRESSION_ORDER from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE from .jp2box import Jp2kBox -from .jp2box import JPEG2000SignatureBox -from .jp2box import FileTypeBox -from .jp2box import JP2HeaderBox -from .jp2box import ContiguousCodestreamBox +from .jp2box import JPEG2000SignatureBox, FileTypeBox, JP2HeaderBox +from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox from .jp2box import ImageHeaderBox -from .jp2box import ColourSpecificationBox from .lib import openjpeg as opj from .lib import openjp2 as opj2 from .lib import c as libc -# Need to known if openjp2 library is the officially release v2.0.0 or not. -_OPENJP2_IS_OFFICIAL_V2 = False -if opj2.OPENJP2 is not None: - if opj2.version() == '2.0.0': - if not hasattr(opj2.OPENJP2, - 'opj_stream_create_default_file_stream_v3'): - _OPENJP2_IS_OFFICIAL_V2 = True - -_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, - 'gray': opj2.CLRSPC_GRAY, - 'grey': opj2.CLRSPC_GRAY, - 'ycc': opj2.CLRSPC_YCC} - -# Setup the default callback handlers. See the callback functions subsection -# in the ctypes section of the Python documentation for a solid explanation of -# what's going on here. -_CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) - - -def _default_error_handler(msg, _): - """Default error handler callback for openjpeg library.""" - msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) - opj2.set_error_message(msg) - - -def _default_info_handler(msg, _): - """Default info handler callback for openjpeg library.""" - print("[INFO] {0}".format(msg.decode('utf-8').rstrip())) - - -def _default_warning_handler(library_msg, _): - """Default warning handler callback for openjpeg library.""" - library_msg = library_msg.decode('utf-8').rstrip() - msg = "OpenJPEG library warning: {0}".format(library_msg) - warnings.warn(msg) - -_ERROR_CALLBACK = _CMPFUNC(_default_error_handler) -_INFO_CALLBACK = _CMPFUNC(_default_info_handler) -_WARNING_CALLBACK = _CMPFUNC(_default_warning_handler) - - -class LibraryNotFoundError(IOError): - """Raised if functionality is requested without the necessary library. - """ - def __init__(self, msg): - IOError.__init__(self, msg) - class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -1313,3 +1267,50 @@ def _validate_compression_params(img_array, cparams): msg = "Only uint8 and uint16 images are currently supported." raise RuntimeError(msg) +# Need to known if openjp2 library is the officially release v2.0.0 or not. +_OPENJP2_IS_OFFICIAL_V2 = False +if opj2.OPENJP2 is not None: + if opj2.version() == '2.0.0': + if not hasattr(opj2.OPENJP2, + 'opj_stream_create_default_file_stream_v3'): + _OPENJP2_IS_OFFICIAL_V2 = True + +_COLORSPACE_MAP = {'rgb': opj2.CLRSPC_SRGB, + 'gray': opj2.CLRSPC_GRAY, + 'grey': opj2.CLRSPC_GRAY, + 'ycc': opj2.CLRSPC_YCC} + +# Setup the default callback handlers. See the callback functions subsection +# in the ctypes section of the Python documentation for a solid explanation of +# what's going on here. +_CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) + + +def _default_error_handler(msg, _): + """Default error handler callback for openjpeg library.""" + msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) + opj2.set_error_message(msg) + + +def _default_info_handler(msg, _): + """Default info handler callback for openjpeg library.""" + print("[INFO] {0}".format(msg.decode('utf-8').rstrip())) + + +def _default_warning_handler(library_msg, _): + """Default warning handler callback for openjpeg library.""" + library_msg = library_msg.decode('utf-8').rstrip() + msg = "OpenJPEG library warning: {0}".format(library_msg) + warnings.warn(msg) + +_ERROR_CALLBACK = _CMPFUNC(_default_error_handler) +_INFO_CALLBACK = _CMPFUNC(_default_info_handler) +_WARNING_CALLBACK = _CMPFUNC(_default_warning_handler) + + +class LibraryNotFoundError(IOError): + """Raised if functionality is requested without the necessary library. + """ + def __init__(self, msg): + IOError.__init__(self, msg) + diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index c018897..747782f 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -225,7 +225,7 @@ class TestJp2k(unittest.TestCase): Jp2k(filename) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - def test_write_with_JP2_suffix(self): + def test_write_with_jp2_in_caps(self): """should be able to write with JP2 suffix.""" j2k = Jp2k(self.j2kfile) expdata = j2k.read() From 86cdb9b36ac721a5231706be65eb66727c7f7655 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 14 Aug 2013 20:24:41 -0400 Subject: [PATCH 037/122] Bumping for 0.3.1 --- CHANGES.txt | 2 +- docs/source/conf.py | 4 ++-- setup.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 1874042..cc297ba 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -Aug 13, 2013 - v0.3.1 Exposed mantissa, exponent, and guard_bits fields in QCC +Aug 14, 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. diff --git a/docs/source/conf.py b/docs/source/conf.py index 79e33af..573ddd5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -76,9 +76,9 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.2' +version = '0.3' # The full version, including alpha/beta/rc tags. -release = '0.3.0' +release = '0.3.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index ae875c0..ac05b8d 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.3.0', + 'version': '0.3.1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From d036c12a0768652be8aa25c3e6cc9fc28ab31664 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 15 Aug 2013 17:10:41 -0400 Subject: [PATCH 038/122] Handles testing gracefully when PIL not present. If PIL is not present, certain writing tests should not be run. These tests would show up as errors instead. Closes #102. --- glymur/test/fixtures.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index ad4fe6d..1c196fb 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -29,6 +29,12 @@ NO_READ_BACKEND_MSG += "order to run the tests in this suite." try: from matplotlib.pyplot import imread + + # The whole point of trying to import PIL is to determine if it's there + # or not. We won't use it directly. + # pylint: disable=F0401,W0611 + import PIL + NO_READ_BACKEND = False except ImportError: NO_READ_BACKEND = True From 61a5497ba74abcdf5d559211591cc43c08e8a608 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 15 Aug 2013 20:28:15 -0400 Subject: [PATCH 039/122] Bumping for 0.3.2 release. --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index cc297ba..bba1195 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Aug 15, 2013 - v0.3.2 Fixed test bug where missing Pillow package caused test + failures. + Aug 14, 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. diff --git a/docs/source/conf.py b/docs/source/conf.py index 573ddd5..cf140a3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.3' # The full version, including alpha/beta/rc tags. -release = '0.3.1' +release = '0.3.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index ac05b8d..5cd8376 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.3.1', + 'version': '0.3.2', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From 08ff86e4a24985f6e0eec93b1ed578660b4bb854 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 18 Aug 2013 14:47:49 -0400 Subject: [PATCH 040/122] Added append capability, #103 --- glymur/jp2k.py | 40 ++++++++++++++- glymur/test/test_jp2box.py | 101 ++++++++++++++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 3 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index ea8ef5e..d5c604c 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -432,6 +432,42 @@ class Jp2k(Jp2kBox): # Refresh the metadata. self.parse() + def append(self, box): + """Append a JP2 box to the file in-place. + + Parameters + ---------- + box : Jp2Box + Instance of a JP2 box. Currently only XML boxes are allowed. + """ + if self._codec_format == opj2.CODEC_J2K: + msg = "Only JP2 files can currently have boxes appended to them." + raise IOError(msg) + + if box.box_id != 'xml ': + raise IOError("Only XML boxes can currently be appended.") + + # Check the last box. If the length field is zero, then rewrite + # the length field to reflect the true length of the box. + with open(self.filename, 'rb') as ifile: + offset = self.box[-1].offset + ifile.seek(offset) + read_buffer = ifile.read(4) + box_length, = struct.unpack('>I', read_buffer) + if box_length == 0: + # Reopen the file in write mode and rewrite the length field. + true_box_length = os.path.getsize(ifile.name) - offset + with open(self.filename, 'r+b') as ofile: + ofile.seek(offset) + write_buffer = struct.pack('>I', true_box_length) + ofile.write(write_buffer) + + # Can now safely append the box. + with open(self.filename, 'ab') as ofile: + box.write(ofile) + + self.parse() + def wrap(self, filename, boxes=None): """Write the codestream back out to file, wrapped in new JP2 jacket. @@ -1133,6 +1169,7 @@ def _unpack_colorspace(colorspace, img_array, cparams): return colorspace + def _populate_comptparms(img_array, cparams): """Instantiate and populate comptparms structure. @@ -1171,6 +1208,7 @@ def _populate_comptparms(img_array, cparams): return comptparms + def _populate_image_struct(cparams, image, imgdata): """Populates image struct needed for compression. @@ -1203,6 +1241,7 @@ def _populate_image_struct(cparams, image, imgdata): return image + def _validate_compression_params(img_array, cparams): """Check that the compression parameters are valid. @@ -1313,4 +1352,3 @@ class LibraryNotFoundError(IOError): """ def __init__(self, msg): IOError.__init__(self, msg) - diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 15c0209..71dbd72 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -18,8 +18,11 @@ Test suite specifically targeting JP2 box layout. import doctest import os +import shutil +import struct import sys import tempfile +import uuid import xml.etree.cElementTree as ET if sys.hexversion < 0x02070000: @@ -502,6 +505,100 @@ class TestColourSpecificationBox(unittest.TestCase): approximation=approx) +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, + "Missing openjp2 library.") +class TestAppend(unittest.TestCase): + """Tests for append method.""" + + def setUp(self): + self.j2kfile = glymur.data.goodstuff() + self.jp2file = glymur.data.nemo() + + def tearDown(self): + pass + + def test_append_xml(self): + """Should be able to append an XML box.""" + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + shutil.copyfile(self.jp2file, tfile.name) + + jp2 = Jp2k(tfile.name) + the_xml = ET.fromstring('0') + xmlbox = glymur.jp2box.XMLBox(xml=the_xml) + jp2.append(xmlbox) + + # The sequence of box IDs should be the same as before, but with an + # xml box at the end. + box_ids = [box.box_id for box in jp2.box] + expected = ['jP ', 'ftyp', 'jp2h', 'uuid', 'uuid', 'jp2c', 'xml '] + self.assertEqual(box_ids, expected) + self.assertEqual(ET.tostring(jp2.box[-1].xml.getroot()), + b'0') + + def test_only_jp2_allowed_to_append(self): + """Only JP2 files are allowed to be appended.""" + with tempfile.NamedTemporaryFile(suffix=".j2k") as tfile: + shutil.copyfile(self.j2kfile, tfile.name) + + jp2 = Jp2k(tfile.name) + + # Make a UUID box. + uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') + data = b'0123456789' + uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) + with self.assertRaises(IOError): + jp2.append(uuidbox) + + def test_length_field_is_zero(self): + """L=0 (length field in box header) is handled. + + L=0 implies that the containing box is the last box. If this is not + handled properly, the appended box is never seen. + """ + baseline_jp2 = Jp2k(self.jp2file) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + with open(self.jp2file, 'rb') as ifile: + # Everything up until the jp2c box. + offset = baseline_jp2.box[-1].offset + tfile.write(ifile.read(offset)) + + # Write the L, T fields of the jp2c box such that L == 0 + write_buffer = struct.pack('>I4s', int(0), b'jp2c') + tfile.write(write_buffer) + + # Write out the rest of the codestream. + ifile.seek(offset+8) + tfile.write(ifile.read()) + tfile.flush() + + jp2 = Jp2k(tfile.name) + the_xml = ET.fromstring('0') + xmlbox = glymur.jp2box.XMLBox(xml=the_xml) + jp2.append(xmlbox) + + # The sequence of box IDs should be the same as before, but with an + # xml box at the end. + box_ids = [box.box_id for box in jp2.box] + expected = ['jP ', 'ftyp', 'jp2h', 'uuid', 'uuid', 'jp2c', 'xml '] + self.assertEqual(box_ids, expected) + self.assertEqual(ET.tostring(jp2.box[-1].xml.getroot()), + b'0') + + def test_only_xml_allowed_to_append(self): + """Only XML boxes are allowed to be appended.""" + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + shutil.copyfile(self.jp2file, tfile.name) + + jp2 = Jp2k(tfile.name) + + # Make a UUID box. + uuid_instance = uuid.UUID('00000000-0000-0000-0000-000000000000') + data = b'0123456789' + uuidbox = glymur.jp2box.UUIDBox(uuid_instance, data) + with self.assertRaises(IOError): + jp2.append(uuidbox) + + @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") class TestWrap(unittest.TestCase): @@ -703,7 +800,7 @@ class TestJp2Boxes(unittest.TestCase): 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) + num_components=3) self.assertEqual(ihdr.height, 512) self.assertEqual(ihdr.width, 256) self.assertEqual(ihdr.num_components, 3) @@ -715,7 +812,7 @@ class TestJp2Boxes(unittest.TestCase): """Should be able to set jp2h boxes.""" box = JP2HeaderBox() box.box = [ImageHeaderBox(height=512, width=256), - ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)] + ColourSpecificationBox(colorspace=glymur.core.GREYSCALE)] self.assertTrue(True) def test_default_ccodestreambox(self): From 5edbe6f078ff12b2d64df5757145cca6104fa7d3 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 18 Aug 2013 14:48:17 -0400 Subject: [PATCH 041/122] pylint, pep8 work. --- glymur/codestream.py | 2 +- glymur/test/fixtures.py | 2 +- glymur/test/test_callbacks.py | 2 +- glymur/test/test_codestream.py | 2 +- glymur/test/test_config.py | 2 +- glymur/test/test_opj_suite.py | 2 +- glymur/test/test_opj_suite_write.py | 3 ++- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/glymur/codestream.py b/glymur/codestream.py index 7a32190..e83c5cc 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -1308,7 +1308,7 @@ class QCCsegment(Segment): self.offset = offset self.mantissa, self.exponent = parse_quantization(self.spqcc, - self.sqcc) + self.sqcc) self.guard_bits = (self.sqcc & 0xe0) >> 5 def __str__(self): diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 1c196fb..eec9e22 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -30,7 +30,7 @@ NO_READ_BACKEND_MSG += "order to run the tests in this suite." try: from matplotlib.pyplot import imread - # The whole point of trying to import PIL is to determine if it's there + # The whole point of trying to import PIL is to determine if it's there # or not. We won't use it directly. # pylint: disable=F0401,W0611 import PIL diff --git a/glymur/test/test_callbacks.py b/glymur/test/test_callbacks.py index 992ca3a..722c5da 100644 --- a/glymur/test/test_callbacks.py +++ b/glymur/test/test_callbacks.py @@ -91,7 +91,7 @@ class TestCallbacks15(unittest.TestCase): def test_info_callbacks_on_read(self): """Verify stdout when reading. - + Verify that we get the expected stdio output when our internal info callback handler is enabled. """ diff --git a/glymur/test/test_codestream.py b/glymur/test/test_codestream.py index f9d4d75..8db5039 100644 --- a/glymur/test/test_codestream.py +++ b/glymur/test/test_codestream.py @@ -5,7 +5,7 @@ Test suite for codestream parsing. # unittest doesn't work well with R0904. # pylint: disable=R0904 -# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2 +# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2 # pylint: disable=E1101 # unittest2 is python2.6 only (pylint/python-2.7) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index b475b91..3a70ee1 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -4,7 +4,7 @@ OPENJP2 may be present in some form or other. # unittest doesn't work well with R0904. # pylint: disable=R0904 -# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2 +# tempfile.TemporaryDirectory, unittest.assertWarns introduced in 3.2 # pylint: disable=E1101 # unittest.mock only in Python 3.3 (python2.7/pylint import issue) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a264019..c622f44 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -17,7 +17,7 @@ suite. # unittest fools pylint with "too many public methods" # pylint: disable=R0904 -# Some tests use numpy test infrastructure, which means the tests never +# Some tests use numpy test infrastructure, which means the tests never # reference "self", so pylint claims it should be a function. No, no, no. # pylint: disable=R0201 diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 6cc37f3..e6f1575 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -441,7 +441,8 @@ class TestSuiteWrite(unittest.TestCase): self.assertEqual(len(codestream.segment[2].spcod), 9) # 18 SOP segments. - nsops = [x.nsop for x in codestream.segment if x.marker_id == 'SOP'] + nsops = [x.nsop for x in codestream.segment + if x.marker_id == 'SOP'] self.assertEqual(nsops, list(range(18))) def test_NR_ENC_Bretagne2_ppm_7_encode(self): From e74718655fcbb80ff8bf40eae22d0c459752b82d Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 18 Aug 2013 19:58:45 -0400 Subject: [PATCH 042/122] Added example for append method. Closes #103. --- docs/source/how_do_i.rst | 50 +++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index eee558c..110ca81 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -3,7 +3,7 @@ How do I...? ------------ -Read the lowest resolution thumbnail? +read the lowest resolution thumbnail? ===================================== Printing the Jp2k object should reveal the number of resolutions (look in the COD segment section), but you can take a shortcut by supplying -1 as the @@ -14,7 +14,7 @@ resolution level. :: >>> j = glymur.Jp2k(file) >>> thumbnail = j.read(rlevel=-1) -Display metadata? +display metadata? ================= There are two ways. From the unix command line, the script *jp2dump* is available. :: @@ -34,8 +34,41 @@ codestream box, only the main header is printed. It is possible to print >>> print(j.get_codestream()) -Add XML Metadata? +add XML metadata? ================= +You can append any number of XML boxes to a JP2 file (not to a raw codestream). +Consider the following XML file `data.xml` : :: + + + + + Boston + 24.9 inches + + + Portland + 31.9 inches + + + New York City + 11.4 inches + + + +The **append** method can add an XML box (only XML boxes are currently +allowed):: + + >>> import shutil + >>> import glymur + >>> shutil.copyfile(glymur.data.nemo(), 'myfile.jp2') + >>> from xml.etree import cElementTree as ET + >>> jp2 = glymur.Jp2k('myfile.jp2') + >>> xmlbox = glymur.jp2box.XMLBox(filename='data.xml') + >>> jp2.append(xmlbox) + >>> print(jp2) + +add metadata in a more general fashion? +======================================= An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the codestream provided by `goodstuff.j2k` (a file consisting of a raw codestream), @@ -87,7 +120,7 @@ though. Take the following example content in an XML file `favorites.xml` : :: and add it after the JP2 header box, but before the codestream box :: >>> boxes = jp2.box # The box attribute is the list of JP2 boxes - >>> xmlbox = glymur.jp2box.XMLBox(file='favorites.xml') + >>> xmlbox = glymur.jp2box.XMLBox(filename='favorites.xml') >>> boxes.insert(3, xmlbox) >>> jp2_xml = jp2.wrap("newfile_with_xml.jp2", boxes=boxes) >>> print(jp2_xml) @@ -119,7 +152,12 @@ and add it after the JP2 header box, but before the codestream box :: . (truncated) . -Create an image with an alpha layer? +As to the question of which method you should use, **append** or **wrap**, +to add metadata, you should keep in mind that **wrap** produces a new JP2 file, +while **append** modifies an existing file and is currently limited to XML +boxes. + +create an image with an alpha layer? ==================================== OpenJPEG can create JP2 files with more than 3 components (requires @@ -181,7 +219,7 @@ Here's how the Preview application on the mac shows the RGBA image. .. image:: goodstuff_alpha.png -Work with XMP UUIDs? +work with XMP UUIDs? ==================== The example JP2 file shipped with glymur has an XMP UUID. :: From c16280df59ed02256d4ba14daa124f4edfd5cc04 Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 18 Aug 2013 20:02:21 -0400 Subject: [PATCH 043/122] Prepping for 0.4 release. --- CHANGES.txt | 2 ++ docs/source/conf.py | 4 ++-- setup.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index bba1195..8a4fe86 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,5 @@ +Aug 18, 2013 - v0.4.0 Added append method. + Aug 15, 2013 - v0.3.2 Fixed test bug where missing Pillow package caused test failures. diff --git a/docs/source/conf.py b/docs/source/conf.py index cf140a3..fb2a685 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -76,9 +76,9 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.3' +version = '0.4' # The full version, including alpha/beta/rc tags. -release = '0.3.2' +release = '0.4.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index 5cd8376..b57fef1 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.3.2', + 'version': '0.4.0rc1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From 0750fed2d07aae6ff5e4a8bcf55bef57605900be Mon Sep 17 00:00:00 2001 From: jevans Date: Sun, 18 Aug 2013 20:13:56 -0400 Subject: [PATCH 044/122] Finalizing 0.4.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b57fef1..6249662 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.4.0rc1', + 'version': '0.4.0', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From 3e91c145501a3f760398febf08e613fcb6ade9ea Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 19 Aug 2013 18:47:46 -0400 Subject: [PATCH 045/122] First attempt at travis ci --- .travis.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3c58f95 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.3" + +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qq numpy + +# command to install dependencies +install: + - pip install numpy -q --use-mirrors + - pip install matplotlib --use-mirrors + - pip install . --use-mirrors +# command to run tests +script: + - "python -m unittest discover" From d265968682caa2212a13893de38623984781d69f Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 19 Aug 2013 18:53:36 -0400 Subject: [PATCH 046/122] Make the travis build more verbose. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3c58f95..d365344 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ install: - pip install . --use-mirrors # command to run tests script: - - "python -m unittest discover" + - "python -m unittest discover -v" From d636a0e3e9805fd0cfdf7a9b284baa5bd273b295 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 19 Aug 2013 19:03:11 -0400 Subject: [PATCH 047/122] Adding libopenjpeg2 to apt-get install, taking out numpy --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d365344..8b436de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ python: before_install: - sudo apt-get update -qq - - sudo apt-get install -qq numpy + - sudo apt-get install -qq libopenjpeg2 # command to install dependencies install: From efa2e23d628339306bf85934d6a9ac112f8ba932 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 19 Aug 2013 19:19:07 -0400 Subject: [PATCH 048/122] Remove 2.6 build because it uses unittest2 instead of unittest. Closes #105 --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8b436de..0ff068a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - "2.6" - "2.7" - "3.3" @@ -15,4 +14,4 @@ install: - pip install . --use-mirrors # command to run tests script: - - "python -m unittest discover -v" + - "python -m unittest discover" From bbc7808175469acdf95567abb3e16127f30648bc Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 20 Aug 2013 18:53:37 -0400 Subject: [PATCH 049/122] Moved TestConfig tests into config. Reworked two jp2k tests. The jp2k tests were relying on the OPJ_DATA_ROOT test files, which was not necessary. #105 --- glymur/test/test_config.py | 43 +++++++++++++++++++++++++++++++ glymur/test/test_jp2k.py | 52 ++------------------------------------ 2 files changed, 45 insertions(+), 50 deletions(-) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 3a70ee1..af95bd3 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -90,5 +90,48 @@ class TestSuite(unittest.TestCase): with self.assertWarns(UserWarning): imp.reload(glymur.lib.openjp2) + +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and + 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() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + 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): + glymur.Jp2k(self.jp2file).read() + + 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): + glymur.Jp2k(self.jp2file).read_bands() + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_write_without_library(self): + """Don't have openjp2 library? Must error out. + """ + data = glymur.Jp2k(self.j2kfile).read() + with patch('glymur.lib.openjp2.OPENJP2', new=None): + with patch('glymur.lib.openjpeg.OPENJPEG', new=None): + with self.assertRaises(glymur.jp2k.LibraryNotFoundError): + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(data) + + if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 747782f..f44906e 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -65,48 +65,6 @@ def load_tests(loader, tests, ignore): return tests -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and - 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() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - 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): - glymur.Jp2k(self.jp2file).read() - - 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): - glymur.Jp2k(self.jp2file).read_bands() - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - def test_write_without_library(self): - """Don't have openjp2 library? Must error out. - """ - data = glymur.Jp2k(self.j2kfile).read() - with patch('glymur.lib.openjp2.OPENJP2', new=None): - with patch('glymur.lib.openjpeg.OPENJPEG', new=None): - with self.assertRaises(glymur.jp2k.LibraryNotFoundError): - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(data) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") @@ -333,13 +291,10 @@ 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, - "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') - jp2k = Jp2k(filename) + jp2k = Jp2k(self.j2kfile) self.assertEqual(len(jp2k.box), 0) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") @@ -425,14 +380,11 @@ class TestJp2k(unittest.TestCase): with self.assertRaises(RuntimeError): j.read() - @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') - j = Jp2k(filename) + j = Jp2k(self.j2kfile) self.assertEqual(j.box, []) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") From 5c190e8d9e7c450c326e736c67f61e69977f84dc Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 20 Aug 2013 20:01:01 -0400 Subject: [PATCH 050/122] Added check for rlevel=-1 for openjpeg 1.5. Added 2.x tests to 1.5 suite. Closes #106 --- glymur/jp2k.py | 5 + glymur/test/test_jp2k.py | 617 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 622 insertions(+) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index d5c604c..9623abc 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -636,6 +636,11 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() + if rlevel == -1: + # Get the lowest resolution thumbnail. + codestream = self.get_codestream() + rlevel = codestream.segment[2].spcod[4] + with ExitStack() as stack: # Set decoding parameters. dparameters = opj.DecompressionParametersType() diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index f44906e..2ca5d9b 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -38,6 +38,7 @@ import glymur from glymur import Jp2k from .fixtures import OPENJP2_IS_V2_OFFICIAL +from .fixtures import OPENJPEG_VERSION try: DATA_ROOT = os.environ['OPJ_DATA_ROOT'] @@ -367,6 +368,18 @@ class TestJp2k(unittest.TestCase): self.assertEqual(new_jp2.box[j].length, baseline_jp2.box[j].length) + def test_basic_jp2(self): + """Just a very basic test that reading a JP2 file does not error out. + """ + j2k = Jp2k(self.jp2file) + j2k.read(rlevel=1) + + def test_basic_j2k(self): + """Just a very basic test that reading a J2K file does not error out. + """ + j2k = Jp2k(self.j2kfile) + j2k.read() + @unittest.skipIf(DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_read_differing_subsamples(self): @@ -772,6 +785,14 @@ class TestJp2k15(unittest.TestCase): def tearDown(self): pass + def test_rlevel_max(self): + """Verify that rlevel=-1 gets us the lowest resolution image""" + j = Jp2k(self.j2kfile) + thumbnail2 = j.read(rlevel=5) + thumbnail1 = j.read(rlevel=-1) + np.testing.assert_array_equal(thumbnail1, thumbnail2) + self.assertEqual(thumbnail1.shape, (25, 15, 3)) + def test_area(self): """Area option not allowed for 1.5.1. """ @@ -793,6 +814,215 @@ class TestJp2k15(unittest.TestCase): with self.assertRaises(TypeError): j2k.read(layer=1) + def test_rlevel_too_high(self): + """Should error out appropriately if reduce level too high""" + j = Jp2k(self.jp2file) + with self.assertRaises(ValueError): + j.read(rlevel=6) + + 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(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. + with self.assertRaises(OSError): + filename = 'this file does not actually exist on the file system.' + Jp2k(filename) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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.skip("Writing requires openjp2 library at the moment.") + @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: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, mct=False) + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + codestream = ofile.get_codestream() + self.assertEqual(codestream.segment[2].spcod[3], 0) # no mct + + @unittest.skip("Writing requires openjp2 library at the moment.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_write_grayscale_with_mct(self): + """MCT usage makes no sense for grayscale images.""" + j2k = Jp2k(self.j2kfile) + expdata = j2k.read() + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + ofile.write(expdata[:, :, 0], mct=True) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, prog='CPRL') + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + 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. Basic jp2 test.""" + jp2k = Jp2k(self.jp2file) + + # top-level boxes + self.assertEqual(len(jp2k.box), 6) + + self.assertEqual(jp2k.box[0].box_id, 'jP ') + self.assertEqual(jp2k.box[0].offset, 0) + self.assertEqual(jp2k.box[0].length, 12) + self.assertEqual(jp2k.box[0].longname, 'JPEG 2000 Signature') + + self.assertEqual(jp2k.box[1].box_id, 'ftyp') + self.assertEqual(jp2k.box[1].offset, 12) + self.assertEqual(jp2k.box[1].length, 20) + self.assertEqual(jp2k.box[1].longname, 'File Type') + + self.assertEqual(jp2k.box[2].box_id, 'jp2h') + self.assertEqual(jp2k.box[2].offset, 32) + self.assertEqual(jp2k.box[2].length, 45) + self.assertEqual(jp2k.box[2].longname, 'JP2 Header') + + self.assertEqual(jp2k.box[3].box_id, 'uuid') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 638) + + self.assertEqual(jp2k.box[4].box_id, 'uuid') + self.assertEqual(jp2k.box[4].offset, 715) + self.assertEqual(jp2k.box[4].length, 2412) + + self.assertEqual(jp2k.box[5].box_id, 'jp2c') + self.assertEqual(jp2k.box[5].offset, 3127) + self.assertEqual(jp2k.box[5].length, 1132296) + + # jp2h super box + self.assertEqual(len(jp2k.box[2].box), 2) + + self.assertEqual(jp2k.box[2].box[0].box_id, 'ihdr') + self.assertEqual(jp2k.box[2].box[0].offset, 40) + self.assertEqual(jp2k.box[2].box[0].length, 22) + self.assertEqual(jp2k.box[2].box[0].longname, 'Image Header') + self.assertEqual(jp2k.box[2].box[0].height, 1456) + self.assertEqual(jp2k.box[2].box[0].width, 2592) + self.assertEqual(jp2k.box[2].box[0].num_components, 3) + self.assertEqual(jp2k.box[2].box[0].bits_per_component, 8) + self.assertEqual(jp2k.box[2].box[0].signed, False) + self.assertEqual(jp2k.box[2].box[0].compression, 7) + self.assertEqual(jp2k.box[2].box[0].colorspace_unknown, False) + self.assertEqual(jp2k.box[2].box[0].ip_provided, False) + + self.assertEqual(jp2k.box[2].box[1].box_id, 'colr') + self.assertEqual(jp2k.box[2].box[1].offset, 62) + self.assertEqual(jp2k.box[2].box[1].length, 15) + self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification') + self.assertEqual(jp2k.box[2].box[1].precedence, 0) + self.assertEqual(jp2k.box[2].box[1].approximation, 0) + self.assertEqual(jp2k.box[2].box[1].colorspace, glymur.core.SRGB) + self.assertIsNone(jp2k.box[2].box[1].icc_profile) + + def test_j2k_box(self): + """A J2K/J2C file must not have any boxes.""" + # Verify that a J2K file has no boxes. + jp2k = Jp2k(self.j2kfile) + self.assertEqual(len(jp2k.box), 0) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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. + 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). + 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) + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + jp2k = Jp2k(tfile.name) + + self.assertEqual(jp2k.box[5].box_id, 'jp2c') + self.assertEqual(jp2k.box[5].offset, 3127) + self.assertEqual(jp2k.box[5].length, 1133427 + 8) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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. + baseline_jp2 = Jp2k(self.jp2file) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + with open(self.jp2file, 'rb') as ifile: + # Everything up until the jp2c box. + write_buffer = ifile.read(588458) + tfile.write(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) + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + new_jp2 = Jp2k(tfile.name) + + # The top level boxes in each file should match. + for j in range(len(baseline_jp2.box)): + self.assertEqual(new_jp2.box[j].box_id, + baseline_jp2.box[j].box_id) + self.assertEqual(new_jp2.box[j].offset, + baseline_jp2.box[j].offset) + self.assertEqual(new_jp2.box[j].length, + baseline_jp2.box[j].length) + def test_basic_jp2(self): """This test is only useful when openjp2 is not available and OPJ_DATA_ROOT is not set. We need at least one @@ -809,6 +1039,393 @@ class TestJp2k15(unittest.TestCase): j2k = Jp2k(self.j2kfile) j2k.read() + @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') + j = Jp2k(filename) + with self.assertRaises(RuntimeError): + j.read() + + def test_empty_box_with_j2k(self): + """Verify that the list of boxes in a J2C/J2K file is present, but + empty. + """ + j = Jp2k(self.j2kfile) + self.assertEqual(j.box, []) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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') + + # The code block dimensions are given as rows x columns. + j.write(data, cbsize=(16, 32)) + + codestream = j.get_codestream() + + # Code block size is reported as XY in the codestream. + self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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_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): + 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.""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + data = np.zeros((128, 128, 2), dtype=np.uint8) + j.write(data, colorspace='rgb') + + @unittest.skip("Writing requires openjp2 library at the moment.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_colorspace_with_j2k(self): + """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): + data = np.zeros((128, 128, 3), dtype=np.uint8) + j.write(data, colorspace='rgb') + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + j.write(data, colorspace='rgb') + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + j.write(data, colorspace='grey') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 2) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 3) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 4) + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @unittest.skip("Writing requires openjp2 library at the moment.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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: + j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 4), dtype=np.uint8) + j.write(data) + + @unittest.skip("Writing requires openjp2 library at the moment.") + def test_specify_ycc(self): + """Should reject YCC""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + 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. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the UINF superbox + # Length = 50, id is uinf. + 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. + 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. + 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. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + jp2k = Jp2k(tfile.name) + + self.assertEqual(jp2k.box[3].box_id, 'uinf') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 50) + + self.assertEqual(jp2k.box[3].box[0].box_id, 'ulst') + self.assertEqual(jp2k.box[3].box[0].offset, 85) + self.assertEqual(jp2k.box[3].box[0].length, 26) + ulst = [] + ulst.append(uuid.UUID('00000000-0000-0000-0000-000000000000')) + self.assertEqual(jp2k.box[3].box[0].ulst, ulst) + + self.assertEqual(jp2k.box[3].box[1].box_id, 'url ') + self.assertEqual(jp2k.box[3].box[1].offset, 111) + self.assertEqual(jp2k.box[3].box[1].length, 16) + self.assertEqual(jp2k.box[3].box[1].version, 0) + self.assertEqual(jp2k.box[3].box[1].flag, (0, 0, 0)) + self.assertEqual(jp2k.box[3].box[1].url, 'abcd') + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the xml box + # Length = 36, id is 'xml '. + write_buffer = struct.pack('>I4s', int(36), b'xml ') + tfile.write(write_buffer) + + write_buffer = 'this is a test' + chr(0) + write_buffer = write_buffer.encode() + tfile.write(write_buffer) + + # Get the rest of the input file. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + jp2k = Jp2k(tfile.name) + + self.assertEqual(jp2k.box[3].box_id, 'xml ') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 36) + self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), + b'this is a test') + + @unittest.skip("Writing requires openjp2 library at the moment.") + @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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data) + + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: + + # Offset of the codestream is where we start. + 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'. + write_buffer = struct.pack('>I4s', int(56), b'asoc') + tfile2.write(write_buffer) + + # Write the contained label box + 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 '. + write_buffer = struct.pack('>I4s', int(35), b'xml ') + tfile2.write(write_buffer) + + write_buffer = 'this is a test' + write_buffer = write_buffer.encode() + tfile2.write(write_buffer) + + # Now append the codestream. + tfile2.write(codestream) + tfile2.flush() + + jasoc = Jp2k(tfile2.name) + self.assertEqual(jasoc.box[3].box_id, 'asoc') + self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') + self.assertEqual(jasoc.box[3].box[0].label, 'label') + self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(re.match('1\.[345]\.\d', OPENJPEG_VERSION) is not None, + "Segfault on official v1.x series.") + def test_openjpeg_library_message(self): + """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 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. + tfile.write(data[0:3179]) + + # Make the DY bytes of the SIZ segment zero. That means that + # a subsampling factor is zero, which is illegal. + tfile.write(b'\x00') + tfile.write(data[3180:3182]) + tfile.write(b'\x00') + tfile.write(data[3184:3186]) + tfile.write(b'\x00') + + tfile.write(data[3186:]) + tfile.flush() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(tfile.name) + regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ + Invalid\svalues\sfor\scomp\s=\s0\s+ + :\sdx=1\sdy=0''', re.VERBOSE) + if sys.hexversion < 0x03020000: + with self.assertRaisesRegexp((IOError, OSError), regexp): + j.read(rlevel=1) + else: + with self.assertRaisesRegex((IOError, OSError), regexp): + j.read(rlevel=1) + + def test_xmp_attribute(self): + """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#}' + ns1 = '{http://ns.adobe.com/xap/1.0/}' + name = '{0}RDF/{0}Description'.format(ns0) + elt = xmp.find(name) + attr_value = elt.attrib['{0}CreatorTool'.format(ns1)] + self.assertEqual(attr_value, 'glymur') + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_unrecognized_exif_tag(self): + """An unrecognized exif tag should be handled gracefully.""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + shutil.copyfile(self.jp2file, tfile.name) + + # The Exif UUID starts at byte 77. There are 8 bytes for the L and + # T fields, then 16 bytes for the UUID identifier, then 6 exif + # header bytes, then 8 bytes for the TIFF header, then 2 bytes + # 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 fptr: + fptr.seek(117) + write_buffer = struct.pack(' Date: Tue, 20 Aug 2013 20:23:51 -0400 Subject: [PATCH 051/122] Trying to install debs for numpy and matplotlib instead of pip --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ff068a..c1c3b39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,13 @@ python: before_install: - sudo apt-get update -qq - sudo apt-get install -qq libopenjpeg2 + - sudo apt-get install -qq numpy + - sudo apt-get install -qq matplotlib # command to install dependencies +# - pip install numpy -q --use-mirrors +# - pip install matplotlib --use-mirrors install: - - pip install numpy -q --use-mirrors - - pip install matplotlib --use-mirrors - pip install . --use-mirrors # command to run tests script: From b7e589c7819aaadf7dce3a83bf76465895f12e38 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 20 Aug 2013 20:36:03 -0400 Subject: [PATCH 052/122] Don't need matplotlib yet, try python-numpy instead of numpy. --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c1c3b39..3e6ca20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,11 @@ python: before_install: - sudo apt-get update -qq - sudo apt-get install -qq libopenjpeg2 - - sudo apt-get install -qq numpy - - sudo apt-get install -qq matplotlib + - sudo apt-get install -qq python-numpy # command to install dependencies -# - pip install numpy -q --use-mirrors -# - pip install matplotlib --use-mirrors install: + - pip install numpy -q --use-mirrors - pip install . --use-mirrors # command to run tests script: From 08578115f625d4288ed491d36f19c5b54342dcc9 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 20 Aug 2013 20:45:47 -0400 Subject: [PATCH 053/122] No need to use apt-get with numpy, and then also install with pip still on #105 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3e6ca20..30dd864 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,10 @@ before_install: - sudo apt-get update -qq - sudo apt-get install -qq libopenjpeg2 - sudo apt-get install -qq python-numpy + - sudo apt-get install -qq python3-numpy # command to install dependencies install: - - pip install numpy -q --use-mirrors - pip install . --use-mirrors # command to run tests script: From 009bd647726b3291115bb20b2633be52ae426cd4 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 20 Aug 2013 22:10:38 -0400 Subject: [PATCH 054/122] Must explicitly check max rlevel on 1.x versions of library. Otherwise it errors badly on 1.5, segfaults on 1.3. Closes #106. --- glymur/jp2k.py | 14 +++++++++++--- glymur/test/test_jp2k.py | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 9623abc..bd90dfe 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -636,10 +636,18 @@ class Jp2k(Jp2kBox): """ self._subsampling_sanity_check() - if rlevel == -1: - # Get the lowest resolution thumbnail. + if rlevel != 0: + # Must check the specified rlevel against the maximum. + # OpenJPEG 1.3 will segfault if rlevel is too high. codestream = self.get_codestream() - rlevel = codestream.segment[2].spcod[4] + max_rlevel = codestream.segment[2].spcod[4] + if rlevel == -1: + # -1 is shorthand for the largest rlevel + rlevel = max_rlevel + if rlevel < -1 or rlevel > max_rlevel: + msg = "rlevel must be in the range [-1, {0}] for this image." + msg = msg.format(max_rlevel) + raise IOError(msg) with ExitStack() as stack: # Set decoding parameters. diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 2ca5d9b..ea19199 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -817,7 +817,7 @@ class TestJp2k15(unittest.TestCase): def test_rlevel_too_high(self): """Should error out appropriately if reduce level too high""" j = Jp2k(self.jp2file) - with self.assertRaises(ValueError): + with self.assertRaises(IOError): j.read(rlevel=6) def test_not_jpeg2000(self): From b53a838056c1f236b9d86424a7ba86a5c178b350 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 21 Aug 2013 10:18:06 -0400 Subject: [PATCH 055/122] Prepping for 0.4.1 release. --- CHANGES.txt | 2 ++ docs/source/conf.py | 2 +- setup.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 8a4fe86..9a71f81 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,5 @@ +Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1 + Aug 18, 2013 - v0.4.0 Added append method. Aug 15, 2013 - v0.3.2 Fixed test bug where missing Pillow package caused test diff --git a/docs/source/conf.py b/docs/source/conf.py index fb2a685..c5dccb4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.4' # The full version, including alpha/beta/rc tags. -release = '0.4.0' +release = '0.4.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index 6249662..575eca6 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.4.0', + 'version': '0.4.1rc1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From d0b63435151f7e5357aa1d1126440ac7ab4601c7 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 21 Aug 2013 10:33:36 -0400 Subject: [PATCH 056/122] minor wording changes --- docs/source/detailed_installation.rst | 5 +++-- docs/source/how_do_i.rst | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 126efaa..dab4c3f 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -137,13 +137,14 @@ In addition, you must install contextlib2 and Pillow via pip. :: Windows ------- -32-bit WinPython 2.7.5 seems to work with OpenJPEG 1.X, 2.0, and the -development version, but still requires contextlib2 and mock to be +32-bit WinPython 2.7.5 seemed to work with OpenJPEG 1.X, 2.0, and the +development version, but still required contextlib2 and mock to be installed via pip. WinPython 3.3.2, however, seems to have trouble with OpenJPEG 2.0, so I would suggest using the development version there (I'm unwilling to spend ANY more time trying to figure out what the problem is there). +At the moment I do not have access to a win32 machine, and 64-bit windows is completely untested. diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 110ca81..cc0b227 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -55,8 +55,7 @@ Consider the following XML file `data.xml` : :: -The **append** method can add an XML box (only XML boxes are currently -allowed):: +The **append** method can add an XML box as shown below:: >>> import shutil >>> import glymur @@ -108,8 +107,8 @@ two additional boxes (image header and color specification) contained in the JP2 header superbox. XML boxes are not in the minimal set of box requirements for the JP2 format, so -in order to add an XML box into the mix, we'll need to specify all of the -boxes. If you already have a JP2 jacket in place, you can just reuse it, +in order to add an XML box into the mix before the codestream box, we'll need to +re-specify all of the boxes. If you already have a JP2 jacket in place, you can just reuse that, though. Take the following example content in an XML file `favorites.xml` : :: @@ -117,7 +116,8 @@ though. Take the following example content in an XML file `favorites.xml` : :: Light Ale -and add it after the JP2 header box, but before the codestream box :: +In order to add the XML after the JP2 header box, but before the codestream box, +the following will work. :: >>> boxes = jp2.box # The box attribute is the list of JP2 boxes >>> xmlbox = glymur.jp2box.XMLBox(filename='favorites.xml') From 1dce49121fcd039b44e431f603cfd609274441a4 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 21 Aug 2013 11:07:29 -0400 Subject: [PATCH 057/122] Finalizing for 0.4.1 release. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 575eca6..ff533a7 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.4.1rc1', + 'version': '0.4.1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', From 3efcf0b46a1ebe98b77b1bf5603bc85cbfd1816a Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 21 Aug 2013 12:13:26 -0400 Subject: [PATCH 058/122] restrict email notifications, closes #107 --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 30dd864..a8a0d1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,11 @@ before_install: # command to install dependencies install: - pip install . --use-mirrors + # command to run tests script: - "python -m unittest discover" + +notifications: + email: + - john.g.evans.ne@gmail.com From 8a8cccb8abd5abc3496d6bfec57ad81a08727c55 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 28 Aug 2013 21:35:22 -0400 Subject: [PATCH 059/122] Refactored OPJ_DATA_ROOT handling into a fixture. Closes #108 --- glymur/test/fixtures.py | 14 + glymur/test/test_icc.py | 15 +- glymur/test/test_jp2k.py | 24 +- glymur/test/test_opj_suite.py | 925 +++++++++++++--------------- glymur/test/test_opj_suite_neg.py | 22 +- glymur/test/test_opj_suite_write.py | 36 +- glymur/test/test_printing.py | 84 ++- 7 files changed, 501 insertions(+), 619 deletions(-) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index eec9e22..4c99ade 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -1,6 +1,7 @@ """ Test fixtures common to more than one test point. """ +import os import re import sys import warnings @@ -27,6 +28,19 @@ if glymur.lib.openjp2.OPENJP2 is not None: NO_READ_BACKEND_MSG = "Matplotlib with the PIL backend must be available in " NO_READ_BACKEND_MSG += "order to run the tests in this suite." +try: + OPJ_DATA_ROOT = os.environ['OPJ_DATA_ROOT'] +except KeyError: + OPJ_DATA_ROOT = None +except: + raise + + +def opj_data_file(relative_file_name): + """Compact way of forming a full filename from OpenJPEG's test suite.""" + jfile = os.path.join(OPJ_DATA_ROOT, relative_file_name) + return jfile + try: from matplotlib.pyplot import imread diff --git a/glymur/test/test_icc.py b/glymur/test/test_icc.py index bf589a5..8668999 100644 --- a/glymur/test/test_icc.py +++ b/glymur/test/test_icc.py @@ -20,16 +20,10 @@ else: import numpy as np from glymur import Jp2k - -try: - DATA_ROOT = os.environ['OPJ_DATA_ROOT'] -except KeyError: - DATA_ROOT = None -except: - raise +from .fixtures import OPJ_DATA_ROOT, opj_data_file -@unittest.skipIf(DATA_ROOT is None, +@unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestICC(unittest.TestCase): """ICC profile tests""" @@ -42,7 +36,7 @@ class TestICC(unittest.TestCase): def test_file5(self): """basic ICC profile""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file5.jp2') + filename = opj_data_file('input/conformance/file5.jp2') j = Jp2k(filename) profile = j.box[3].box[1].icc_profile self.assertEqual(profile['Size'], 546) @@ -75,8 +69,7 @@ class TestICC(unittest.TestCase): "Uses features introduced in 3.2.") def test_invalid_profile_header(self): """invalid ICC header data should cause UserWarning""" - jfile = os.path.join(DATA_ROOT, - 'input/nonregression/orb-blue10-lin-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') # assertWarns in Python 3.3 (python2.7/pylint issue) # pylint: disable=E1101 diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index ea19199..699fef7 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -25,10 +25,6 @@ if sys.hexversion < 0x02070000: else: import unittest -if sys.hexversion <= 0x03030000: - from mock import patch -else: - from unittest.mock import patch import warnings import numpy as np @@ -39,13 +35,7 @@ from glymur import Jp2k from .fixtures import OPENJP2_IS_V2_OFFICIAL from .fixtures import OPENJPEG_VERSION - -try: - DATA_ROOT = os.environ['OPJ_DATA_ROOT'] -except KeyError: - DATA_ROOT = None -except: - raise +from .fixtures import OPJ_DATA_ROOT, opj_data_file # Doc tests should be run as well. @@ -380,7 +370,7 @@ class TestJp2k(unittest.TestCase): j2k = Jp2k(self.j2kfile) j2k.read() - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_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""" @@ -388,7 +378,7 @@ class TestJp2k(unittest.TestCase): # on an image with differing subsamples # # Issue 86. - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k') + filename = opj_data_file('input/conformance/p0_05.j2k') j = Jp2k(filename) with self.assertRaises(RuntimeError): j.read() @@ -1039,7 +1029,7 @@ class TestJp2k15(unittest.TestCase): j2k = Jp2k(self.j2kfile) j2k.read() - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_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""" @@ -1047,7 +1037,7 @@ class TestJp2k15(unittest.TestCase): # on an image with differing subsamples # # Issue 86. - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k') + filename = opj_data_file('input/conformance/p0_05.j2k') j = Jp2k(filename) with self.assertRaises(RuntimeError): j.read() @@ -1347,7 +1337,8 @@ class TestJp2k15(unittest.TestCase): self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(re.match('1\.[345]\.\d', OPENJPEG_VERSION) is not None, + @unittest.skipIf(re.match(r"""1\.[345]\.\d""", + OPENJPEG_VERSION) is not None, "Segfault on official v1.x series.") def test_openjpeg_library_message(self): """Verify the error message produced by the openjpeg library""" @@ -1426,6 +1417,5 @@ class TestJp2k15(unittest.TestCase): self.assertFalse('Make' in exif['Image'].keys()) - if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index c622f44..93e9745 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -30,7 +30,6 @@ suite. # unittest2 is python2.6 only (pylint/python-2.7) # pylint: disable=F0401 -import os import re import sys @@ -46,22 +45,13 @@ import numpy as np from glymur import Jp2k import glymur -from .fixtures import OPENJPEG_VERSION -from .fixtures import OPENJP2_IS_V2_OFFICIAL -from .fixtures import mse, peak_tolerance, read_pgx - - -try: - data_root = os.environ['OPJ_DATA_ROOT'] -except KeyError: - data_root = None -except: - raise +from .fixtures import OPENJPEG_VERSION, OPENJP2_IS_V2_OFFICIAL, OPJ_DATA_ROOT +from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, "Missing openjp2 library.") -@unittest.skipIf(data_root is None, +@unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite(unittest.TestCase): @@ -72,78 +62,74 @@ class TestSuite(unittest.TestCase): pass def test_ETS_C0P0_p0_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') + jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_01.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_01.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jfile = opj_data_file('input/conformance/p0_02.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): # Invalid marker ID. warnings.simplefilter("ignore") jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_02.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_02.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_03_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k') + jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_03r0.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_03r0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_03_j2k_r1(self): - jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k') + jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=1) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_03r1.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_03r1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_04.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_04.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 33) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 55.8) def test_ETS_C0P0_p0_05_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_05.j2k') + jfile = opj_data_file('input/conformance/p0_05.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_05.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_05.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54) self.assertTrue(mse(jpdata[0], pgxdata) < 68) @unittest.skip("8-bit pgx data vs 12-bit j2k data") def test_ETS_C0P0_p0_06_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_06.j2k') + jfile = opj_data_file('input/conformance/p0_06.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_06.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_06.pgx') pgxdata = read_pgx(pgxfile) tol = peak_tolerance(jpdata[0], pgxdata) self.assertTrue(tol < 109) @@ -152,12 +138,11 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_07_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_07.j2k') + jfile = opj_data_file('input/conformance/p0_07.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_07.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_07.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10) @@ -165,24 +150,22 @@ class TestSuite(unittest.TestCase): @unittest.skip("8-bit pgx data vs 12-bit j2k data") def test_ETS_C0P0_p0_08_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k') + jfile = opj_data_file('input/conformance/p0_08.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=5) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_08.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_08.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 7) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 6.72) def test_ETS_C0P0_p0_09_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k') + jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=2) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_09.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_09.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata, pgxdata) < 4) @@ -190,129 +173,118 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_10_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k') + jfile = opj_data_file('input/conformance/p0_10.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_10.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_10.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 10) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 2.84) def test_ETS_C0P0_p0_11_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k') + jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_11.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_11.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C0P0_p0_12_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k') + jfile = opj_data_file('input/conformance/p0_12.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_12.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_12.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_13_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k') + jfile = opj_data_file('input/conformance/p0_13.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_13.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_13.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_14_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_14.j2k') + jfile = opj_data_file('input/conformance/p0_14.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=2) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_14.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_14.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_15_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k') + jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_15r0.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_15r0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_15_j2k_r1(self): - jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k') + jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=1) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_15r1.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_15r1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_16_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k') + jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_16.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_16.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P1_p1_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k') + jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_01.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_01.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C0P1_p1_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_02.j2k') + jfile = opj_data_file('input/conformance/p1_02.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_02.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_02.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 35) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 74) def test_ETS_C0P1_p1_03_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_03.j2k') + jfile = opj_data_file('input/conformance/p1_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_03.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_03.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 28) @@ -320,12 +292,11 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C0P1_p1_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_04r0.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_04r0.pgx') pgxdata = read_pgx(pgxfile) print(peak_tolerance(jpdata, pgxdata)) @@ -334,12 +305,11 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite, precision issue.") def test_ETS_C0P1_p1_04_j2k_r3(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=3) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_04r3.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_04r3.pgx') pgxdata = read_pgx(pgxfile) print(peak_tolerance(jpdata, pgxdata)) @@ -348,12 +318,11 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C0P1_p1_05_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k') + jfile = opj_data_file('input/conformance/p1_05.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=4) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_05.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_05.pgx') pgxdata = read_pgx(pgxfile) print(peak_tolerance(jpdata[:, :, 0], pgxdata)) @@ -363,12 +332,11 @@ class TestSuite(unittest.TestCase): @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C0P1_p1_06_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=1) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_06.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_06.pgx') pgxdata = read_pgx(pgxfile) print(peak_tolerance(jpdata[:, :, 0], pgxdata)) @@ -378,388 +346,387 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2345.") def test_ETS_C0P1_p1_07_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k') + jfile = opj_data_file('input/conformance/p1_07.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_07.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_07.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[0], pgxdata) def test_ETS_C1P0_p0_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') + jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_01_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jfile = opj_data_file('input/conformance/p0_02.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_02_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_02_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_03_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k') + jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_03_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.776) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.626) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07) def test_ETS_C1P0_p0_05_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_05.j2k') + jfile = opj_data_file('input/conformance/p0_05.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_05_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_05_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) self.assertTrue(mse(jpdata[0], pgxdata) < 0.302) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_05_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_05_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) self.assertTrue(mse(jpdata[1], pgxdata) < 0.307) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_05_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_05_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 2) self.assertTrue(mse(jpdata[2], pgxdata) < 0.269) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_05_3.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_05_3.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) self.assertTrue(mse(jpdata[3], pgxdata) == 0) def test_ETS_C1P0_p0_06_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_06.j2k') + jfile = opj_data_file('input/conformance/p0_06.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_06_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_06_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 635) self.assertTrue(mse(jpdata[0], pgxdata) < 11287) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_06_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_06_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 403) self.assertTrue(mse(jpdata[1], pgxdata) < 6124) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_06_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_06_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 378) self.assertTrue(mse(jpdata[2], pgxdata) < 3968) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_06_3.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_06_3.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) self.assertTrue(mse(jpdata[3], pgxdata) == 0) @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C1P0_p0_07_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_07.j2k') + jfile = opj_data_file('input/conformance/p0_07.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_07_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_07_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_07_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_07_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, : 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_07_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_07_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, : 2], pgxdata) def test_ETS_C1P0_p0_08_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k') + jfile = opj_data_file('input/conformance/p0_08.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=1) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_09_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k') + jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_09_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_10_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k') + jfile = opj_data_file('input/conformance/p0_10.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_11_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k') + jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_11_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P0_p0_12_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k') + jfile = opj_data_file('input/conformance/p0_12.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_12_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_12_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P0_p0_13_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k') + jfile = opj_data_file('input/conformance/p0_13.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_3.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_3.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 3], pgxdata) def test_ETS_C1P0_p0_14_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_14.j2k') + jfile = opj_data_file('input/conformance/p0_14.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_15_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k') + jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_15_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_16_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k') + jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_16_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P1_p1_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k') + jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_01_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P1_p1_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_02.j2k') + jfile = opj_data_file('input/conformance/p1_02.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.765) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.616) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.051) def test_ETS_C1P1_p1_03_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_03.j2k') + jfile = opj_data_file('input/conformance/p1_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_03_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_03_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) self.assertTrue(mse(jpdata[0], pgxdata) < 0.3) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_03_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_03_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) self.assertTrue(mse(jpdata[1], pgxdata) < 0.21) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_03_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_03_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[2], pgxdata) <= 1) self.assertTrue(mse(jpdata[2], pgxdata) < 0.2) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_03_3.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_03_3.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[3], pgxdata) def test_ETS_C1P1_p1_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_04_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624) self.assertTrue(mse(jpdata, pgxdata) < 3080) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P1_p1_05_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k') + jfile = opj_data_file('input/conformance/p1_05.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 8.458) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 9.816) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 10.154) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P1_p1_06_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.6) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.6) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 0.6) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P1_p1_07_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k') + jfile = opj_data_file('input/conformance/p1_07.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_07_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_07_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[0], pgxdata) <= 0) self.assertTrue(mse(jpdata[0], pgxdata) <= 0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_07_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_07_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[1], pgxdata) <= 0) self.assertTrue(mse(jpdata[1], pgxdata) <= 0) def test_ETS_JP2_file1(self): - jfile = os.path.join(data_root, 'input/conformance/file1.jp2') + jfile = opj_data_file('input/conformance/file1.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file2(self): - jfile = os.path.join(data_root, 'input/conformance/file2.jp2') + jfile = opj_data_file('input/conformance/file2.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file3(self): - jfile = os.path.join(data_root, 'input/conformance/file3.jp2') + jfile = opj_data_file('input/conformance/file3.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read_bands() self.assertEqual(jpdata[0].shape, (640, 480)) @@ -767,59 +734,56 @@ class TestSuite(unittest.TestCase): self.assertEqual(jpdata[2].shape, (320, 240)) def test_ETS_JP2_file4(self): - jfile = os.path.join(data_root, 'input/conformance/file4.jp2') + jfile = opj_data_file('input/conformance/file4.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file5(self): - jfile = os.path.join(data_root, 'input/conformance/file5.jp2') + jfile = opj_data_file('input/conformance/file5.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): - jfile = os.path.join(data_root, 'input/conformance/file6.jp2') + jfile = opj_data_file('input/conformance/file6.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): - jfile = os.path.join(data_root, 'input/conformance/file7.jp2') + jfile = opj_data_file('input/conformance/file7.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): - jfile = os.path.join(data_root, 'input/conformance/file8.jp2') + jfile = opj_data_file('input/conformance/file8.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): - jfile = os.path.join(data_root, 'input/conformance/file9.jp2') + jfile = opj_data_file('input/conformance/file9.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_DEC_Bretagne2_j2k_1_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Bretagne2.j2k') + jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/_00042.j2k') + jfile = opj_data_file('input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_123_j2c_3_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/123.j2c') + jfile = opj_data_file('input/nonregression/123.j2c') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) @@ -827,8 +791,7 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken_jp2_4_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken.jp2') + jfile = opj_data_file('input/nonregression/broken.jp2') with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -838,7 +801,7 @@ class TestSuite(unittest.TestCase): def test_NR_DEC_broken2_jp2_5_decode(self): # Null pointer access - jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2') + jfile = opj_data_file('input/nonregression/broken2.jp2') with self.assertRaises(IOError): with warnings.catch_warnings(): # Invalid marker ID. @@ -849,7 +812,7 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2') + jfile = opj_data_file('input/nonregression/broken3.jp2') with self.assertWarns(UserWarning): # colr box has bad length. j = Jp2k(jfile) @@ -858,7 +821,7 @@ class TestSuite(unittest.TestCase): j.read() def test_NR_DEC_broken4_jp2_7_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2') + jfile = opj_data_file('input/nonregression/broken4.jp2') with self.assertRaises(IOError): with warnings.catch_warnings(): # invalid number of subbands, bad marker ID @@ -868,105 +831,97 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_bug_j2c_8_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/bug.j2c') + jfile = opj_data_file('input/nonregression/bug.j2c') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/buxI.j2k') + jfile = opj_data_file('input/nonregression/buxI.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/buxR.j2k') + jfile = opj_data_file('input/nonregression/buxR.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/cthead1.j2k') + jfile = opj_data_file('input/nonregression/cthead1.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): # Stream too short, expected SOT. - jfile = os.path.join(data_root, - 'input/nonregression/illegalcolortransform.j2k') + jfile = opj_data_file('input/nonregression/illegalcolortransform.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') + jfile = opj_data_file('input/nonregression/j2k32.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/MarkerIsNotCompliant.j2k') + jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/Marrin.jp2') + jfile = opj_data_file('input/nonregression/Marrin.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_merged_jp2_19_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/merged.jp2') + jfile = opj_data_file('input/nonregression/merged.jp2') Jp2k(jfile).read_bands() self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00000.j2k') + jfile = opj_data_file('input/nonregression/movie_00000.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/movie_00001.j2k') + jfile = opj_data_file('input/nonregression/movie_00001.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/movie_00002.j2k') + jfile = opj_data_file('input/nonregression/movie_00002.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_jp2_25_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") @@ -974,28 +929,24 @@ class TestSuite(unittest.TestCase): self.assertTrue(True) def test_NR_DEC_orb_blue_win_jp2_26_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_relax_jp2_27_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/relax.jp2') + jfile = opj_data_file('input/nonregression/relax.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_test_lossless_j2k_28_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/test_lossless.j2k') + jfile = opj_data_file('input/nonregression/test_lossless.j2k') Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test known to fail in v2.0.0 official") def test_NR_DEC_text_GBR_jp2_29_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/text_GBR.jp2') + jfile = opj_data_file('input/nonregression/text_GBR.jp2') with warnings.catch_warnings(): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") @@ -1004,38 +955,33 @@ class TestSuite(unittest.TestCase): self.assertTrue(True) def test_NR_DEC_pacs_ge_j2k_30_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/pacs.ge.j2k') + jfile = opj_data_file('input/nonregression/pacs.ge.j2k') Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test known to fail in v2.0.0 official") def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/kodak_2layers_lrcp.j2c') + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test known to fail in v2.0.0 official") def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/kodak_2layers_lrcp.j2c') + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') Jp2k(jfile).read(layer=2) self.assertTrue(True) def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue104_jpxstream.jp2') + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test known to fail in v2.0.0 official") def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2ace68c-1381.jp2') + jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') with warnings.catch_warnings(): # This file has a bad pclr box, we test for this elsewhere. warnings.simplefilter("ignore") @@ -1046,14 +992,13 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test known to fail in v2.0.0 official") def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2b86b74-2753.jp2') + jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' - jfile = os.path.join(data_root, f) + jfile = opj_data_file(f) with warnings.catch_warnings(): # Invalid number of resolutions. warnings.simplefilter("ignore") @@ -1067,7 +1012,7 @@ class TestSuite(unittest.TestCase): lst = ('input', 'nonregression', 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with warnings.catch_warnings(): # Invalid component number. warnings.simplefilter("ignore") @@ -1079,7 +1024,7 @@ class TestSuite(unittest.TestCase): "Test not in done in v2.0.0 official") def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) with warnings.catch_warnings(): # Invalid number of tiles. warnings.simplefilter("ignore") @@ -1091,7 +1036,7 @@ class TestSuite(unittest.TestCase): "Test not in done in v2.0.0 official") def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) with warnings.catch_warnings(): # Invalid subsampling value warnings.simplefilter("ignore") @@ -1099,7 +1044,7 @@ class TestSuite(unittest.TestCase): Jp2k(jfile).read() def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = os.path.join(data_root, 'input/nonregression/file409752.jp2') + jfile = opj_data_file('input/nonregression/file409752.jp2') with self.assertRaises(RuntimeError): Jp2k(jfile).read() @@ -1111,69 +1056,68 @@ class TestSuite(unittest.TestCase): # Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it # really does deserve a warning. relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) with self.assertWarns(UserWarning): Jp2k(jfile).read() @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") def test_NR_DEC_issue206_image_000_jp2_42_decode(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue206_image-000.jp2') + jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_p1_04_j2k_43_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 1024, 1024)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata) def test_NR_DEC_p1_04_j2k_44_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(640, 512, 768, 640)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[640:768, 512:640]) def test_NR_DEC_p1_04_j2k_45_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(896, 896, 1024, 1024)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024]) def test_NR_DEC_p1_04_j2k_46_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(500, 100, 800, 300)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[500:800, 100:300]) def test_NR_DEC_p1_04_j2k_47_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 260, 600, 360)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[520:600, 260:360]) def test_NR_DEC_p1_04_j2k_48_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 260, 660, 360)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[520:660, 260:360]) def test_NR_DEC_p1_04_j2k_49_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 360, 600, 400)) odata = jp2k.read() np.testing.assert_array_equal(ssdata, odata[520:600, 360:400]) def test_NR_DEC_p1_04_j2k_50_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 1024, 1024), rlevel=2) odata = jp2k.read(rlevel=2) @@ -1181,70 +1125,70 @@ class TestSuite(unittest.TestCase): np.testing.assert_array_equal(ssdata, odata[0:256, 0:256]) def test_NR_DEC_p1_04_j2k_51_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(640, 512, 768, 640), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[160:192, 128:160]) def test_NR_DEC_p1_04_j2k_52_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(896, 896, 1024, 1024), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[224:352, 224:352]) def test_NR_DEC_p1_04_j2k_53_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(500, 100, 800, 300), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[125:200, 25:75]) def test_NR_DEC_p1_04_j2k_54_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 260, 600, 360), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[130:150, 65:90]) def test_NR_DEC_p1_04_j2k_55_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 260, 660, 360), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[130:165, 65:90]) def test_NR_DEC_p1_04_j2k_56_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(520, 360, 600, 400), rlevel=2) odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(ssdata, odata[130:150, 90:100]) def test_NR_DEC_p1_04_j2k_57_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=63) # last tile odata = jp2k.read() np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) def test_NR_DEC_p1_04_j2k_58_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=63, rlevel=2) # last tile odata = jp2k.read(rlevel=2) np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) def test_NR_DEC_p1_04_j2k_59_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=12) # 2nd row, 5th column odata = jp2k.read() np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) def test_NR_DEC_p1_04_j2k_60_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column odata = jp2k.read(rlevel=1) @@ -1252,7 +1196,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_61_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 12, 12)) odata = jp2k.read() @@ -1260,7 +1204,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_62_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(1, 8, 8, 11)) odata = jp2k.read() @@ -1268,7 +1212,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_63_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(9, 9, 12, 12)) odata = jp2k.read() @@ -1276,7 +1220,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_64_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(10, 4, 12, 10)) odata = jp2k.read() @@ -1284,7 +1228,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_65_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(3, 3, 9, 9)) odata = jp2k.read() @@ -1292,7 +1236,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_66_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(4, 4, 7, 7)) odata = jp2k.read() @@ -1300,7 +1244,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_67_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(4, 4, 5, 5)) odata = jp2k.read() @@ -1308,7 +1252,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_68_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 12, 12), rlevel=1) odata = jp2k.read(rlevel=1) @@ -1316,51 +1260,51 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_69_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(1, 8, 8, 11), rlevel=1) self.assertEqual(ssdata.shape, (3, 2, 3)) def test_NR_DEC_p1_06_j2k_70_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=1) self.assertEqual(ssdata.shape, (1, 1, 3)) def test_NR_DEC_p1_06_j2k_71_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(10, 4, 12, 10), rlevel=1) self.assertEqual(ssdata.shape, (1, 3, 3)) def test_NR_DEC_p1_06_j2k_72_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(3, 3, 9, 9), rlevel=1) self.assertEqual(ssdata.shape, (3, 3, 3)) def test_NR_DEC_p1_06_j2k_73_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(4, 4, 7, 7), rlevel=1) self.assertEqual(ssdata.shape, (2, 2, 3)) def test_NR_DEC_p1_06_j2k_74_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(4, 4, 5, 5), rlevel=1) self.assertEqual(ssdata.shape, (1, 1, 3)) def test_NR_DEC_p1_06_j2k_75_decode(self): # Image size would be 0 x 0. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) with self.assertRaises((IOError, OSError)): jp2k.read(area=(9, 9, 12, 12), rlevel=2) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_76_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() tiledata = jp2k.read(tile=0) @@ -1368,7 +1312,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_77_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() tiledata = jp2k.read(tile=5) @@ -1376,7 +1320,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_78_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() with warnings.catch_warnings(): @@ -1386,7 +1330,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_79_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) fulldata = jp2k.read() with warnings.catch_warnings(): @@ -1397,7 +1341,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_80_decode(self): # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") @@ -1406,7 +1350,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_81_decode(self): # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") @@ -1415,7 +1359,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_82_decode(self): # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") @@ -1424,7 +1368,7 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_83_decode(self): # tile size is 3x3. Reducing two levels results in no data. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): warnings.simplefilter("ignore") @@ -1434,96 +1378,96 @@ class TestSuite(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_84_decode(self): # Just read the data, don't bother verifying. - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) jp2k.read(rlevel=4) def test_NR_DEC_p0_04_j2k_85_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 256, 256)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata) def test_NR_DEC_p0_04_j2k_86_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 128, 128, 256)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata) def test_NR_DEC_p0_04_j2k_87_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(10, 50, 200, 120)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata) def test_NR_DEC_p0_04_j2k_88_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(150, 10, 210, 190)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata) def test_NR_DEC_p0_04_j2k_89_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(80, 100, 150, 200)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata) def test_NR_DEC_p0_04_j2k_90_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(20, 150, 50, 200)) fulldata = jp2k.read() np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata) def test_NR_DEC_p0_04_j2k_91_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 0, 256, 256), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata) def test_NR_DEC_p0_04_j2k_92_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(0, 128, 128, 256), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata) def test_NR_DEC_p0_04_j2k_93_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(10, 50, 200, 120), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata) def test_NR_DEC_p0_04_j2k_94_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(150, 10, 210, 190), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata) def test_NR_DEC_p0_04_j2k_95_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(80, 100, 150, 200), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata) def test_NR_DEC_p0_04_j2k_96_decode(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) ssdata = jp2k.read(area=(20, 150, 50, 200), rlevel=2) fulldata = jp2k.read(rlevel=2) np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata) -@unittest.skipIf(data_root is None, +@unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuiteDump(unittest.TestCase): @@ -1534,7 +1478,7 @@ class TestSuiteDump(unittest.TestCase): pass def test_NR_p0_01_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') + jfile = opj_data_file('input/conformance/p0_01.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # Segment IDs. @@ -1601,7 +1545,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[4].tnsot, 1) def test_NR_p0_02_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jfile = opj_data_file('input/conformance/p0_02.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -1707,7 +1651,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p0_03_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k') + jfile = opj_data_file('input/conformance/p0_03.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -1824,7 +1768,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[13].marker_id, 'SOD') def test_NR_p0_04_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -1932,7 +1876,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[8].marker_id, 'SOD') def test_NR_p0_05_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_05.j2k') + jfile = opj_data_file('input/conformance/p0_05.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2076,7 +2020,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[11].marker_id, 'SOD') def test_NR_p0_06_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_06.j2k') + jfile = opj_data_file('input/conformance/p0_06.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2213,7 +2157,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[11].marker_id, 'SOD') def test_NR_p0_07_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_07.j2k') + jfile = opj_data_file('input/conformance/p0_07.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2298,7 +2242,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[8].marker_id, 'SOD') def test_NR_p0_08_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k') + jfile = opj_data_file('input/conformance/p0_08.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2451,7 +2395,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[10].tnsot, 1) # unknown def test_NR_p0_09_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k') + jfile = opj_data_file('input/conformance/p0_09.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2531,7 +2475,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[7].marker_id, 'EOC') def test_NR_p0_10_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k') + jfile = opj_data_file('input/conformance/p0_10.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2672,7 +2616,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[22].marker_id, 'EOC') def test_NR_p0_11_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k') + jfile = opj_data_file('input/conformance/p0_11.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2753,7 +2697,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p0_12_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k') + jfile = opj_data_file('input/conformance/p0_12.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2835,7 +2779,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p0_13_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k') + jfile = opj_data_file('input/conformance/p0_13.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -2961,7 +2905,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[12].marker_id, 'EOC') def test_NR_p0_14_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_14.j2k') + jfile = opj_data_file('input/conformance/p0_14.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3037,7 +2981,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[7].marker_id, 'EOC') def test_NR_p0_15_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k') + jfile = opj_data_file('input/conformance/p0_15.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3191,7 +3135,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[85].marker_id, 'EOC') def test_NR_p0_16_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k') + jfile = opj_data_file('input/conformance/p0_16.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3259,7 +3203,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[6].marker_id, 'EOC') def test_NR_p1_01_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k') + jfile = opj_data_file('input/conformance/p1_01.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3359,7 +3303,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p1_02_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_02.j2k') + jfile = opj_data_file('input/conformance/p1_02.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3473,7 +3417,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[10].marker_id, 'EOC') def test_NR_p1_03_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_03.j2k') + jfile = opj_data_file('input/conformance/p1_03.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3620,7 +3564,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[13].marker_id, 'EOC') def test_NR_p1_04_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3747,7 +3691,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p1_05_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k') + jfile = opj_data_file('input/conformance/p1_05.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3835,7 +3779,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p1_06_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -3928,7 +3872,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_p1_07_dump(self): - jfile = os.path.join(data_root, 'input/conformance/p1_07.j2k') + jfile = opj_data_file('input/conformance/p1_07.j2k') c = Jp2k(jfile).get_codestream(header_only=False) # SIZ: Image and tile size @@ -4021,7 +3965,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[-1].marker_id, 'EOC') def test_NR_file1_dump(self): - jfile = os.path.join(data_root, 'input/conformance/file1.jp2') + jfile = opj_data_file('input/conformance/file1.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4071,7 +4015,7 @@ class TestSuiteDump(unittest.TestCase): '{http://www.jpeg.org/jpx/1.0/xml}EVENT']) def test_NR_file2_dump(self): - jfile = os.path.join(data_root, 'input/conformance/file2.jp2') + jfile = opj_data_file('input/conformance/file2.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4118,7 +4062,7 @@ class TestSuiteDump(unittest.TestCase): # Cr components being subsampled 2x in both the horizontal and # vertical directions. The components are stored in the standard # order. - jfile = os.path.join(data_root, 'input/conformance/file3.jp2') + jfile = opj_data_file('input/conformance/file3.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4165,7 +4109,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_file4_dump(self): # One 8-bit component in the sRGB-grey colourspace. - jfile = os.path.join(data_root, 'input/conformance/file4.jp2') + jfile = opj_data_file('input/conformance/file4.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4207,7 +4151,7 @@ class TestSuiteDump(unittest.TestCase): # the RCT. The colourspace is specified using both a Restricted ICC # profile and using the JPX-defined enumerated code for the ROMM-RGB # colourspace. - jfile = os.path.join(data_root, 'input/conformance/file5.jp2') + jfile = opj_data_file('input/conformance/file5.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4256,7 +4200,7 @@ class TestSuiteDump(unittest.TestCase): glymur.core.ROMM_RGB) def test_NR_file6_dump(self): - jfile = os.path.join(data_root, 'input/conformance/file6.jp2') + jfile = opj_data_file('input/conformance/file6.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4300,7 +4244,7 @@ class TestSuiteDump(unittest.TestCase): # the RCT. The colourspace is specified using both a Restricted ICC # profile and using the JPX-defined enumerated code for the e-sRGB # colourspace. - jfile = os.path.join(data_root, 'input/conformance/file7.jp2') + jfile = opj_data_file('input/conformance/file7.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4356,7 +4300,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_file8_dump(self): # One 8-bit component in a gamma 1.8 space. The colourspace is # specified using a Restricted ICC profile. - jfile = os.path.join(data_root, 'input/conformance/file8.jp2') + jfile = opj_data_file('input/conformance/file8.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4410,7 +4354,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_file9_dump(self): # Colormap - jfile = os.path.join(data_root, 'input/conformance/file9.jp2') + jfile = opj_data_file('input/conformance/file9.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -4469,7 +4413,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_00042_j2k_dump(self): # Profile 3. - jfile = os.path.join(data_root, 'input/nonregression/_00042.j2k') + jfile = opj_data_file('input/nonregression/_00042.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream(header_only=False) @@ -4622,7 +4566,7 @@ class TestSuiteDump(unittest.TestCase): def test_Bretagne2_j2k_dump(self): # Profile 3. - jfile = os.path.join(data_root, 'input/nonregression/Bretagne2.j2k') + jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream(header_only=False) @@ -4679,7 +4623,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(ids, expected) def test_NR_buxI_j2k_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/buxI.j2k') + jfile = opj_data_file('input/nonregression/buxI.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream(header_only=False) @@ -4732,7 +4676,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(ids, expected) def test_NR_buxR_j2k_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/buxR.j2k') + jfile = opj_data_file('input/nonregression/buxR.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream(header_only=False) @@ -4789,7 +4733,7 @@ class TestSuiteDump(unittest.TestCase): 'Cannotreaddatawithnosizeknown.j2k'] path = '/'.join(lst) - jfile = os.path.join(data_root, path) + jfile = opj_data_file(path) jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -4850,9 +4794,8 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_CT_Phillips_JPEG2K_Decompr_Problem_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/' - + 'CT_Phillips_JPEG2K_Decompr_Problem.j2k') + jfile = opj_data_file('input/nonregression/' + + 'CT_Phillips_JPEG2K_Decompr_Problem.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -4922,8 +4865,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[4].ccme.decode('latin-1'), "Kakadu-3.2") def test_NR_cthead1_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/cthead1.j2k') + jfile = opj_data_file('input/nonregression/cthead1.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -4998,8 +4940,7 @@ class TestSuiteDump(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_illegalcolortransform_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/illegalcolortransform.j2k') + jfile = opj_data_file('input/nonregression/illegalcolortransform.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5060,7 +5001,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].exponent, [16] + [17, 17, 18] * 11) def test_NR_j2k32_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') + jfile = opj_data_file('input/nonregression/j2k32.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5127,9 +5068,8 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(len(c.segment[4].ccme), 36) def test_NR_kakadu_v4_4_openjpegv2_broken_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/' - + 'kakadu_v4-4_openjpegv2_broken.j2k') + jfile = opj_data_file('input/nonregression/' + + 'kakadu_v4-4_openjpegv2_broken.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5213,8 +5153,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[5].ccme.decode('latin-1'), expected) def test_NR_MarkerIsNotCompliant_j2k_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/MarkerIsNotCompliant.j2k') + jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5273,8 +5212,7 @@ class TestSuiteDump(unittest.TestCase): 17, 18, 17, 17, 18, 17, 17, 18]) def test_NR_movie_00000(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00000.j2k') + jfile = opj_data_file('input/nonregression/movie_00000.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5331,8 +5269,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_movie_00001(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00001.j2k') + jfile = opj_data_file('input/nonregression/movie_00001.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5389,8 +5326,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_movie_00002(self): - jfile = os.path.join(data_root, - 'input/nonregression/movie_00002.j2k') + jfile = opj_data_file('input/nonregression/movie_00002.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5447,8 +5383,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_lin_j2k_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5508,8 +5443,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_win_j2k_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5569,7 +5503,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_pacs_ge_j2k_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/pacs.ge.j2k') + jfile = opj_data_file('input/nonregression/pacs.ge.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5637,8 +5571,7 @@ class TestSuiteDump(unittest.TestCase): "Kakadu-2.0.2") def test_NR_test_lossless_j2k_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/test_lossless.j2k') + jfile = opj_data_file('input/nonregression/test_lossless.j2k') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5707,7 +5640,7 @@ class TestSuiteDump(unittest.TestCase): "ClearCanvas DICOM OpenJPEG") def test_NR_123_j2c_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/123.j2c') + jfile = opj_data_file('input/nonregression/123.j2c') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5769,7 +5702,7 @@ class TestSuiteDump(unittest.TestCase): [16] + [17, 17, 18] * 11) def test_NR_bug_j2c_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/bug.j2c') + jfile = opj_data_file('input/nonregression/bug.j2c') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5831,8 +5764,7 @@ class TestSuiteDump(unittest.TestCase): [16] + [17, 17, 18] * 11) def test_NR_kodak_2layers_lrcp_j2c_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/kodak_2layers_lrcp.j2c') + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') jp2k = Jp2k(jfile) c = jp2k.get_codestream() @@ -5905,8 +5837,7 @@ class TestSuiteDump(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_broken_jp2_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken.jp2') + jfile = opj_data_file('input/nonregression/broken.jp2') with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -6033,7 +5964,7 @@ class TestSuiteDump(unittest.TestCase): "Uses features introduced in 3.2, 'assertWarns'.") def test_NR_broken2_jp2_dump(self): # Invalid marker ID on codestream. - jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2') + jfile = opj_data_file('input/nonregression/broken2.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(jfile) @@ -6042,8 +5973,7 @@ class TestSuiteDump(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_broken3_jp2_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/broken3.jp2') + jfile = opj_data_file('input/nonregression/broken3.jp2') with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -6170,15 +6100,14 @@ class TestSuiteDump(unittest.TestCase): "Uses features introduced in 3.2, 'assertWarns'") def test_NR_broken4_jp2_dump(self): # Has an invalid marker in the main header - jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2') + jfile = opj_data_file('input/nonregression/broken4.jp2') with self.assertWarns(UserWarning): jp2 = Jp2k(jfile) self.assertEqual(jp2.box[-1].main_header.segment[-1].marker_id, 'QCC') def test_NR_file409752(self): - jfile = os.path.join(data_root, - 'input/nonregression/file409752.jp2') + jfile = opj_data_file('input/nonregression/file409752.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -6279,7 +6208,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc_patch_jp2(self): lst = ['input', 'nonregression', 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2'] - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with self.assertWarns(UserWarning): Jp2k(jfile) @@ -6287,7 +6216,7 @@ class TestSuiteDump(unittest.TestCase): "Uses features introduced in 3.2.") def test_NR_gdal_fuzzer_check_comp_dx_dy_jp2_dump(self): lst = ['input', 'nonregression', 'gdal_fuzzer_check_comp_dx_dy.jp2'] - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with self.assertWarns(UserWarning): Jp2k(jfile) @@ -6297,7 +6226,7 @@ class TestSuiteDump(unittest.TestCase): # Has an impossible tiling setup. lst = ['input', 'nonregression', 'gdal_fuzzer_check_number_of_tiles.jp2'] - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with self.assertWarns(UserWarning): Jp2k(jfile) @@ -6307,13 +6236,12 @@ class TestSuiteDump(unittest.TestCase): # Has an invalid number of resolutions. lst = ['input', 'nonregression', 'gdal_fuzzer_unchecked_numresolutions.jp2'] - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with self.assertWarns(UserWarning): Jp2k(jfile) def test_NR_issue104_jpxstream_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue104_jpxstream.jp2') + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -6427,7 +6355,7 @@ class TestSuiteDump(unittest.TestCase): def test_NR_issue188_beach_64bitsbox(self): lst = ['input', 'nonregression', 'issue188_beach_64bitsbox.jp2'] - jfile = os.path.join(data_root, '/'.join(lst)) + jfile = opj_data_file('/'.join(lst)) with warnings.catch_warnings(): # There's a warning for an unknown box. We explicitly test for # that down below. @@ -6525,8 +6453,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].guard_bits, 1) def test_NR_issue206_image_000_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/issue206_image-000.jp2') + jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -6626,8 +6553,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].exponent, [8] + [9, 9, 10] * 5) def test_NR_Marrin_jp2_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/Marrin.jp2') + jfile = opj_data_file('input/nonregression/Marrin.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -6740,8 +6666,7 @@ class TestSuiteDump(unittest.TestCase): "Kakadu-v5.2.1") def test_NR_mem_b2ace68c_1381_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2ace68c-1381.jp2') + jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') with warnings.catch_warnings(): # This file has a bad pclr box, we test for this elsewhere. warnings.simplefilter("ignore") @@ -6858,8 +6783,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].exponent, [1] + [2, 2, 3] * 5) def test_NR_mem_b2b86b74_2753_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/mem-b2b86b74-2753.jp2') + jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -6973,7 +6897,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3].exponent, [4] + [5, 5, 6] * 5) def test_NR_merged_dump(self): - jfile = os.path.join(data_root, 'input/nonregression/merged.jp2') + jfile = opj_data_file('input/nonregression/merged.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] @@ -7077,8 +7001,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[4].ppod, podvals) def test_NR_orb_blue10_lin_jp2_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") @@ -7177,8 +7100,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_orb_blue10_win_jp2_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") @@ -7277,8 +7199,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) def test_NR_text_GBR_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/text_GBR.jp2') + jfile = opj_data_file('input/nonregression/text_GBR.jp2') with warnings.catch_warnings(): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") @@ -7391,7 +7312,7 @@ class TestSuiteDump(unittest.TestCase): @unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, "Missing openjpeg library.") -@unittest.skipIf(data_root is None, +@unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite15(unittest.TestCase): """Suite of tests for libopenjpeg 1.5.1""" @@ -7414,16 +7335,16 @@ class TestSuite15(unittest.TestCase): pass def test_ETS_C0P0_p0_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') + jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_01.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_01.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jfile = opj_data_file('input/conformance/p0_02.j2k') with warnings.catch_warnings(): # There's a 0xff30 marker segment. Not illegal, but we don't # really know what to do with it. Just ignore. @@ -7431,79 +7352,74 @@ class TestSuite15(unittest.TestCase): jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c0p0_02.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_02.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_09_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k') + jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=2) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_09.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_09.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata, pgxdata) < 4) self.assertTrue(mse(jpdata, pgxdata) < 1.47) def test_ETS_C0P0_p0_11_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k') + jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_11.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_11.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C0P0_p0_12_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k') + jfile = opj_data_file('input/conformance/p0_12.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_12.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_12.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P0_p0_16_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k') + jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p0_16.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p0_16.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C0P1_p1_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k') + jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, - 'baseline/conformance/c0p1_01.pgx') + pgxfile = opj_data_file('baseline/conformance/c0p1_01.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_01.j2k') + jfile = opj_data_file('input/conformance/p0_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_01_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_02.j2k') + jfile = opj_data_file('input/conformance/p0_02.j2k') with warnings.catch_warnings(): # There's a 0xff30 marker segment. Not illegal, but we don't # really know what to do with it. Just ignore. @@ -7511,293 +7427,293 @@ class TestSuite15(unittest.TestCase): jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_02_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_02_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_03_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_03.j2k') + jfile = opj_data_file('input/conformance/p0_03.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_03_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_04.j2k') + jfile = opj_data_file('input/conformance/p0_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.776) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.626) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_04_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_04_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07) def test_ETS_C1P0_p0_08_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_08.j2k') + jfile = opj_data_file('input/conformance/p0_08.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=1) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_08_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_08_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_09_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_09.j2k') + jfile = opj_data_file('input/conformance/p0_09.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_09_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_10_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_10.j2k') + jfile = opj_data_file('input/conformance/p0_10.j2k') jp2k = Jp2k(jfile) with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_10_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_10_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_11_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_11.j2k') + jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_11_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P0_p0_12_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_12.j2k') + jfile = opj_data_file('input/conformance/p0_12.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_12_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_12_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P0_p0_13_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_13.j2k') + jfile = opj_data_file('input/conformance/p0_13.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_13_3.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_13_3.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 3], pgxdata) def test_ETS_C1P0_p0_14_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_14.j2k') + jfile = opj_data_file('input/conformance/p0_14.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_1.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_14_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_14_2.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) def test_ETS_C1P0_p0_15_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_15.j2k') + jfile = opj_data_file('input/conformance/p0_15.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_15_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P0_p0_16_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p0_16.j2k') + jfile = opj_data_file('input/conformance/p0_16.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p0_16_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P1_p1_01_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_01.j2k') + jfile = opj_data_file('input/conformance/p1_01.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_01_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx') pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) def test_ETS_C1P1_p1_02_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_02.j2k') + jfile = opj_data_file('input/conformance/p1_02.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read(rlevel=0) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.765) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.616) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_02_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_02_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.051) def test_ETS_C1P1_p1_04_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_04.j2k') + jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_04_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624) self.assertTrue(mse(jpdata, pgxdata) < 3080) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P1_p1_05_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_05.j2k') + jfile = opj_data_file('input/conformance/p1_05.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 8.458) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 9.816) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_05_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_05_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 40) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 10.154) @unittest.skip("fprintf stderr output in r2343.") def test_ETS_C1P1_p1_06_j2k(self): - jfile = os.path.join(data_root, 'input/conformance/p1_06.j2k') + jfile = opj_data_file('input/conformance/p1_06.j2k') jp2k = Jp2k(jfile) jpdata = jp2k.read() - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_0.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_0.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.6) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_1.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_1.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.6) - pgxfile = os.path.join(data_root, 'baseline/conformance/c1p1_06_2.pgx') + pgxfile = opj_data_file('baseline/conformance/c1p1_06_2.pgx') pgxdata = read_pgx(pgxfile) self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 2) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 0.6) def test_ETS_JP2_file1(self): - jfile = os.path.join(data_root, 'input/conformance/file1.jp2') + jfile = opj_data_file('input/conformance/file1.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file2(self): - jfile = os.path.join(data_root, 'input/conformance/file2.jp2') + jfile = opj_data_file('input/conformance/file2.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file4(self): - jfile = os.path.join(data_root, 'input/conformance/file4.jp2') + jfile = opj_data_file('input/conformance/file4.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file5(self): """ETS_JP2_file5""" - jfile = os.path.join(data_root, 'input/conformance/file5.jp2') + jfile = opj_data_file('input/conformance/file5.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768, 3)) def test_ETS_JP2_file6(self): """ETS_JP2_file6""" - jfile = os.path.join(data_root, 'input/conformance/file6.jp2') + jfile = opj_data_file('input/conformance/file6.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (512, 768)) def test_ETS_JP2_file7(self): """ETS_JP2_file7""" - jfile = os.path.join(data_root, 'input/conformance/file7.jp2') + jfile = opj_data_file('input/conformance/file7.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) def test_ETS_JP2_file8(self): """ETS_JP2_file8""" - jfile = os.path.join(data_root, 'input/conformance/file8.jp2') + jfile = opj_data_file('input/conformance/file8.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() self.assertEqual(jpdata.shape, (400, 700)) def test_ETS_JP2_file9(self): """ETS_JP2_file9""" - jfile = os.path.join(data_root, 'input/conformance/file9.jp2') + jfile = opj_data_file('input/conformance/file9.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() if re.match(r'[01]\.3', OPENJPEG_VERSION): @@ -7808,14 +7724,14 @@ class TestSuite15(unittest.TestCase): def test_NR_DEC_Bretagne2_j2k_1_decode(self): """test_NR_DEC_Bretagne2_j2k_1_decode""" - jfile = os.path.join(data_root, 'input/nonregression/Bretagne2.j2k') + jfile = opj_data_file('input/nonregression/Bretagne2.j2k') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) def test_NR_DEC__00042_j2k_2_decode(self): """NR_DEC__00042_j2k_2_decode""" - jfile = os.path.join(data_root, 'input/nonregression/_00042.j2k') + jfile = opj_data_file('input/nonregression/_00042.j2k') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) @@ -7823,7 +7739,7 @@ class TestSuite15(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_123_j2c_3_decode(self): """NR_DEC_123_j2c_3_decode""" - jfile = os.path.join(data_root, 'input/nonregression/123.j2c') + jfile = opj_data_file('input/nonregression/123.j2c') jp2 = Jp2k(jfile) jp2.read() self.assertTrue(True) @@ -7832,7 +7748,7 @@ class TestSuite15(unittest.TestCase): "Uses features introduced in 3.2.") def test_NR_DEC_broken_jp2_4_decode(self): """NR_DEC_broken_jp2_4_decode""" - jfile = os.path.join(data_root, 'input/nonregression/broken.jp2') + jfile = opj_data_file('input/nonregression/broken.jp2') with self.assertWarns(UserWarning): # colr box has bad length. jp2 = Jp2k(jfile) @@ -7845,7 +7761,7 @@ class TestSuite15(unittest.TestCase): def test_NR_DEC_broken2_jp2_5_decode(self): """NR_DEC_broken2_jp2_5_decode""" # Null pointer access - jfile = os.path.join(data_root, 'input/nonregression/broken2.jp2') + jfile = opj_data_file('input/nonregression/broken2.jp2') with self.assertRaises(ValueError): with warnings.catch_warnings(): # Library warning, invalid number of subbands. @@ -7857,7 +7773,7 @@ class TestSuite15(unittest.TestCase): "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): """NR_DEC_broken3_jp2_6_decode""" - jfile = os.path.join(data_root, 'input/nonregression/broken3.jp2') + jfile = opj_data_file('input/nonregression/broken3.jp2') with self.assertWarns(UserWarning): # colr box has bad length. j = Jp2k(jfile) @@ -7870,7 +7786,7 @@ class TestSuite15(unittest.TestCase): def test_NR_DEC_broken4_jp2_7_decode(self): """NR_DEC_broken4_jp2_7_decode""" # Null pointer access - jfile = os.path.join(data_root, 'input/nonregression/broken4.jp2') + jfile = opj_data_file('input/nonregression/broken4.jp2') with self.assertRaises(ValueError): with warnings.catch_warnings(): # Library warning, invalid number of subbands. @@ -7881,60 +7797,59 @@ class TestSuite15(unittest.TestCase): @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_bug_j2c_8_decode(self): """NR_DEC_bug_j2c_8_decode""" - jfile = os.path.join(data_root, 'input/nonregression/bug.j2c') + jfile = opj_data_file('input/nonregression/bug.j2c') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxI_j2k_9_decode(self): """NR_DEC_buxI_j2k_9_decode""" - jfile = os.path.join(data_root, 'input/nonregression/buxI.j2k') + jfile = opj_data_file('input/nonregression/buxI.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_buxR_j2k_10_decode(self): """NR_DEC_buxR_j2k_10_decode""" - jfile = os.path.join(data_root, 'input/nonregression/buxR.j2k') + jfile = opj_data_file('input/nonregression/buxR.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): """NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode""" relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_cthead1_j2k_12_decode(self): """NR_DEC_cthead1_j2k_12_decode""" - jfile = os.path.join(data_root, 'input/nonregression/cthead1.j2k') + jfile = opj_data_file('input/nonregression/cthead1.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): """NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode""" relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) Jp2k(jfile).read() self.assertTrue(True) @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): """Stream too short, expected SOT.""" - jfile = os.path.join(data_root, - 'input/nonregression/illegalcolortransform.j2k') + jfile = opj_data_file('input/nonregression/illegalcolortransform.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_j2k32_j2k_15_decode(self): """NR_DEC_j2k32_j2k_15_decode""" - jfile = os.path.join(data_root, 'input/nonregression/j2k32.j2k') + jfile = opj_data_file('input/nonregression/j2k32.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): """NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode""" relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' - jfile = os.path.join(data_root, relpath) + jfile = opj_data_file(relpath) with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") @@ -7943,55 +7858,49 @@ class TestSuite15(unittest.TestCase): def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): """NR_DEC_MarkerIsNotCompliant_j2k_17_decode""" - jfile = os.path.join(data_root, - 'input/nonregression/MarkerIsNotCompliant.j2k') + jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_Marrin_jp2_18_decode(self): """NR_DEC_Marrin_jp2_18_decode""" - jfile = os.path.join(data_root, 'input/nonregression/Marrin.jp2') + jfile = opj_data_file('input/nonregression/Marrin.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00000_j2k_20_decode(self): """test_NR_DEC_movie_00000_j2k_20_decode""" - jfile = os.path.join(data_root, - 'input/nonregression/movie_00000.j2k') + jfile = opj_data_file('input/nonregression/movie_00000.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00001_j2k_21_decode(self): """NR_DEC_movie_00001_j2k_21_decode""" - jfile = os.path.join(data_root, - 'input/nonregression/movie_00001.j2k') + jfile = opj_data_file('input/nonregression/movie_00001.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_movie_00002_j2k_22_decode(self): """NR_DEC_movie_00002_j2k_22_decode""" - jfile = os.path.join(data_root, 'input/nonregression/movie_00002.j2k') + jfile = opj_data_file('input/nonregression/movie_00002.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): """NR_DEC_orb_blue_lin_j2k_j2k_23_decode""" - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): """NR_DEC_orb_blue_win_j2k_j2k_24_decode""" - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-j2k.j2k') + jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_nc_dec_orb_blue_lin_jp2_25_decode(self): """NR-DEC-orb-blue-lin.jp2-25-decode""" - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-lin-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') with warnings.catch_warnings(): # This file has an invalid ICC profile warnings.simplefilter("ignore") @@ -8000,35 +7909,31 @@ class TestSuite15(unittest.TestCase): def test_nr_dec_orb_blue_win_jp2_26_decode(self): """NR-DEC-orb-blue-win.jp2-26-decode""" - jfile = os.path.join(data_root, - 'input/nonregression/orb-blue10-win-jp2.jp2') + jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_nr_dec_relax_jp2_27_decode(self): """NR-DEC-relax.jp2-27-decode""" - jfile = os.path.join(data_root, - 'input/nonregression/relax.jp2') + jfile = opj_data_file('input/nonregression/relax.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_nr_dec_test_lossless_j2k_28_decode(self): """NR-DEC-test-lossless.j2k-28-decode""" - jfile = os.path.join(data_root, - 'input/nonregression/test_lossless.j2k') + jfile = opj_data_file('input/nonregression/test_lossless.j2k') Jp2k(jfile).read() self.assertTrue(True) def test_nr_dec_issue104_jpxstream_jp2_33_decode(self): """NR-DEC-issue104-jpxstream.jp2-33-decode""" - jfile = os.path.join(data_root, - 'input/nonregression/issue104_jpxstream.jp2') + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') Jp2k(jfile).read() self.assertTrue(True) def test_nr_dec_file_409752_jp2_40_decode(self): """NR-DEC-file-409752.jp2-40-decode""" - jfile = os.path.join(data_root, 'input/nonregression/file409752.jp2') + jfile = opj_data_file('input/nonregression/file409752.jp2') j = Jp2k(jfile) with self.assertRaises(RuntimeError): j.read() diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index e8675aa..66115a2 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -23,23 +23,17 @@ else: import numpy as np from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG +from .fixtures import OPJ_DATA_ROOT, opj_data_file from glymur import Jp2k import glymur -try: - DATA_ROOT = os.environ['OPJ_DATA_ROOT'] -except KeyError: - DATA_ROOT = None -except: - raise - @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, - "OPJ_DATA_ROOT environment variable not set") +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_OPJ_DATA_ROOT environment variable not set") class TestSuiteNegative(unittest.TestCase): """Test suite for certain negative tests from openjpeg suite.""" @@ -54,7 +48,7 @@ class TestSuiteNegative(unittest.TestCase): 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 = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -64,7 +58,7 @@ class TestSuiteNegative(unittest.TestCase): 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 = opj_data_file(relpath) jp2k = Jp2k(jfile) jp2k.get_codestream(header_only=False) self.assertTrue(True) @@ -74,7 +68,7 @@ class TestSuiteNegative(unittest.TestCase): def test_nr_illegalclrtransform(self): """EOC marker is bad""" relpath = 'input/nonregression/illegalcolortransform.j2k' - jfile = os.path.join(DATA_ROOT, relpath) + jfile = opj_data_file(relpath) jp2k = Jp2k(jfile) with self.assertWarns(UserWarning): codestream = jp2k.get_codestream(header_only=False) @@ -87,7 +81,7 @@ class TestSuiteNegative(unittest.TestCase): 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 = opj_data_file(relpath) jp2k = Jp2k(jfile) jp2k.get_codestream(header_only=False) self.assertTrue(True) @@ -118,7 +112,7 @@ class TestSuiteNegative(unittest.TestCase): # 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(OPJ_DATA_ROOT, 'input/nonregression/mem-b2ace68c-1381.jp2') with self.assertWarns(UserWarning): Jp2k(infile) diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index e6f1575..479cb1f 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -19,23 +19,17 @@ else: import unittest from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG +from .fixtures import OPJ_DATA_ROOT, opj_data_file from glymur import Jp2k import glymur -try: - data_root = os.environ['OPJ_DATA_ROOT'] -except KeyError: - data_root = None -except: - raise - @unittest.skipIf(os.name == "nt", "no write support on windows, period") @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(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuiteWrite(unittest.TestCase): """Tests for writing with openjp2 backend. @@ -51,7 +45,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne1_ppm_1_encode(self): """NR-ENC-Bretagne1.ppm-1-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') + infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -115,7 +109,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne1_ppm_2_encode(self): """NR-ENC-Bretagne1.ppm-2-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') + infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -180,7 +174,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne1_ppm_3_encode(self): """NR-ENC-Bretagne1.ppm-3-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne1.ppm') + infile = opj_data_file('input/nonregression/Bretagne1.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -247,7 +241,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne2_ppm_4_encode(self): """NR-ENC-Bretagne2.ppm-4-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') + infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -316,7 +310,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne2_ppm_5_encode(self): """NR-ENC-Bretagne2.ppm-5-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') + infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -379,7 +373,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne2_ppm_6_encode(self): """NR-ENC-Bretagne2.ppm-6-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') + infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -447,7 +441,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne2_ppm_7_encode(self): """NR-ENC-Bretagne2.ppm-7-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') + infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -514,7 +508,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Bretagne2_ppm_8_encode(self): """NR-ENC-Bretagne2.ppm-8-encode""" - infile = os.path.join(data_root, 'input/nonregression/Bretagne2.ppm') + infile = opj_data_file('input/nonregression/Bretagne2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -578,7 +572,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Cevennes1_bmp_9_encode(self): """NR-ENC-Cevennes1.bmp-9-encode""" - infile = os.path.join(data_root, 'input/nonregression/Cevennes1.bmp') + infile = opj_data_file('input/nonregression/Cevennes1.bmp') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -641,7 +635,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Cevennes2_ppm_10_encode(self): """NR-ENC-Cevennes2.ppm-10-encode""" - infile = os.path.join(data_root, 'input/nonregression/Cevennes2.ppm') + infile = opj_data_file('input/nonregression/Cevennes2.ppm') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') @@ -704,8 +698,7 @@ class TestSuiteWrite(unittest.TestCase): def test_NR_ENC_Rome_bmp_11_encode(self): """NR-ENC-Rome.bmp-11-encode""" - data = read_image(os.path.join(data_root, - 'input/nonregression/Rome.bmp')) + data = read_image(opj_data_file('input/nonregression/Rome.bmp')) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: jp2 = Jp2k(tfile.name, 'wb') jp2.write(data, psnr=[30, 35, 50], prog='LRCP', numres=3) @@ -804,8 +797,7 @@ class TestSuiteWrite(unittest.TestCase): """NR-ENC-random-issue-0005.tif-12-encode""" # opj_decompress has trouble reading it, but that is not an issue here. # The nature of the image itself seems to give the compressor trouble. - infile = os.path.join(data_root, - 'input/nonregression/random-issue-0005.tif') + infile = opj_data_file('input/nonregression/random-issue-0005.tif') data = read_image(infile) with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: j = Jp2k(tfile.name, 'wb') diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index f533aa4..8591b1b 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -32,13 +32,7 @@ else: import glymur from glymur import Jp2k - -try: - DATA_ROOT = os.environ['OPJ_DATA_ROOT'] -except KeyError: - DATA_ROOT = None -except: - raise +from .fixtures import OPJ_DATA_ROOT, opj_data_file @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") @@ -287,11 +281,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_icc_profile(self): """verify printing of colr box with ICC profile""" - filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2') + filename = opj_data_file('input/nonregression/text_GBR.jp2') with warnings.catch_warnings(): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") @@ -356,11 +350,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_crg(self): """verify printing of CRG segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') + filename = opj_data_file('input/conformance/p0_03.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() with patch('sys.stdout', new=StringIO()) as fake_out: @@ -371,11 +365,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_rgn(self): """verify printing of RGN segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') + filename = opj_data_file('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: @@ -388,11 +382,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_sop(self): """verify printing of SOP segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_03.j2k') + filename = opj_data_file('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: @@ -403,11 +397,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_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') + filename = opj_data_file('input/conformance/p0_02.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() # 2nd to last segment in the main header @@ -431,11 +425,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_plt_segment(self): """verify printing of PLT segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_07.j2k') + filename = opj_data_file('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: @@ -450,11 +444,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_pod_segment(self): """verify printing of POD segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_13.j2k') + filename = opj_data_file('input/conformance/p0_13.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() with patch('sys.stdout', new=StringIO()) as fake_out: @@ -480,11 +474,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_ppm_segment(self): """verify printing of PPM segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p1_03.j2k') + filename = opj_data_file('input/conformance/p1_03.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() with patch('sys.stdout', new=StringIO()) as fake_out: @@ -498,11 +492,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_ppt_segment(self): """verify printing of ppt segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p1_06.j2k') + filename = opj_data_file('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: @@ -610,11 +604,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_tlm_segment(self): """verify printing of TLM segment""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_15.j2k') + filename = opj_data_file('input/conformance/p0_15.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() with patch('sys.stdout', new=StringIO()) as fake_out: @@ -704,11 +698,11 @@ class TestPrinting(unittest.TestCase): @unittest.skipIf(sys.hexversion < 0x02070000, "Differences in XML printing between 2.6 and 2.7") - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_xml(self): """verify printing of XML box""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file1.jp2') + filename = opj_data_file('input/conformance/file1.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2]) @@ -735,11 +729,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_channel_definition(self): """verify printing of cdef box""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file2.jp2') + filename = opj_data_file('input/conformance/file2.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2].box[2]) @@ -751,11 +745,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_component_mapping(self): """verify printing of cmap box""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2') + filename = opj_data_file('input/conformance/file9.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2].box[2]) @@ -767,11 +761,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_palette7(self): """verify printing of pclr box""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file9.jp2') + filename = opj_data_file('input/conformance/file9.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2].box[1]) @@ -781,11 +775,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_rreq(self): """verify printing of reader requirements box""" - filename = os.path.join(DATA_ROOT, 'input/conformance/file7.jp2') + filename = opj_data_file('input/conformance/file7.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2]) @@ -805,11 +799,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_differing_subsamples(self): """verify printing of SIZ with different subsampling... Issue 86.""" - filename = os.path.join(DATA_ROOT, 'input/conformance/p0_05.j2k') + filename = opj_data_file('input/conformance/p0_05.j2k') j = glymur.Jp2k(filename) codestream = j.get_codestream() with patch('sys.stdout', new=StringIO()) as fake_out: @@ -828,11 +822,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_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') + filename = opj_data_file('input/conformance/file9.jp2') j = glymur.Jp2k(filename) with patch('sys.stdout', new=StringIO()) as fake_out: print(j.box[2].box[1]) @@ -921,13 +915,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(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") 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 = opj_data_file('input/nonregression/text_GBR.jp2') with warnings.catch_warnings(): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") @@ -966,11 +960,11 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(DATA_ROOT is None, + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_uuid(self): """verify printing of UUID box""" - filename = os.path.join(DATA_ROOT, 'input/nonregression/text_GBR.jp2') + filename = opj_data_file('input/nonregression/text_GBR.jp2') with warnings.catch_warnings(): # brand is 'jp2 ', but has any icc profile. warnings.simplefilter("ignore") From 80cb2585b164add8ac5535bc4751ab1b51e43c9c Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 5 Sep 2013 21:34:52 -0400 Subject: [PATCH 060/122] OPENJPEG_VERSION is now the version of the software, not the library. For #110 --- glymur/test/fixtures.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 4c99ade..933222a 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -10,10 +10,12 @@ import numpy as np import glymur -# Need to know the openjpeg version. If openjpeg is not installed, we use -# '0.0.0' +# Need to know the version of the openjpeg software. If openjpeg is not +# installed, we use # '0.0.0' OPENJPEG_VERSION = '0.0.0' -if glymur.lib.openjpeg.OPENJPEG is not None: +if glymur.lib.openjp2.OPENJP2 is not None: + OPENJPEG_VERSION = glymur.lib.openjp2.version() +elif glymur.lib.openjpeg.OPENJPEG is not None: OPENJPEG_VERSION = glymur.lib.openjpeg.version() # Need to know of the libopenjp2 version is the official 2.0.0 release and NOT From 02c186107dea1fa6f2e5b7accb3e7c127fb31bc7 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 5 Sep 2013 21:39:05 -0400 Subject: [PATCH 061/122] Removing duplicated tests. #110 --- glymur/test/test_opj_suite.py | 639 +--------------------------------- 1 file changed, 9 insertions(+), 630 deletions(-) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 93e9745..c6dfbda 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -49,8 +49,9 @@ from .fixtures import OPENJPEG_VERSION, OPENJP2_IS_V2_OFFICIAL, OPJ_DATA_ROOT from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and + glymur.lib.openjpeg.OPENJPEG is None, + "Missing openjpeg libraries.") @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") class TestSuite(unittest.TestCase): @@ -725,6 +726,8 @@ class TestSuite(unittest.TestCase): jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) + @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), + "Functionality not implemented for 1.x") def test_ETS_JP2_file3(self): jfile = opj_data_file('input/conformance/file3.jp2') jp2k = Jp2k(jfile) @@ -1034,6 +1037,8 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") + @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), + "Segfaults 1.5") def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' jfile = opj_data_file(relpath) @@ -1050,6 +1055,8 @@ class TestSuite(unittest.TestCase): @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") + @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), + "Segfaults 1.5") @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self): @@ -7310,633 +7317,5 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) -@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, - "Missing openjpeg library.") -@unittest.skipIf(OPJ_DATA_ROOT is None, - "OPJ_DATA_ROOT environment variable not set") -class TestSuite15(unittest.TestCase): - """Suite of tests for libopenjpeg 1.5.1""" - - @classmethod - def setUpClass(cls): - # Monkey patch the package so as to use OPENJPEG instead of OPENJP2 - cls.openjp2 = glymur.lib.openjp2.OPENJP2 - glymur.lib.openjp2.OPENJP2 = None - - @classmethod - def tearDownClass(cls): - # Restore OPENJP2 - glymur.lib.openjp2.OPENJP2 = cls.openjp2 - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_ETS_C0P0_p0_01_j2k(self): - jfile = opj_data_file('input/conformance/p0_01.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p0_01.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C0P0_p0_02_j2k(self): - jfile = opj_data_file('input/conformance/p0_02.j2k') - with warnings.catch_warnings(): - # There's a 0xff30 marker segment. Not illegal, but we don't - # really know what to do with it. Just ignore. - warnings.simplefilter("ignore") - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p0_02.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C0P0_p0_09_j2k(self): - jfile = opj_data_file('input/conformance/p0_09.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=2) - - pgxfile = opj_data_file('baseline/conformance/c0p0_09.pgx') - pgxdata = read_pgx(pgxfile) - - self.assertTrue(peak_tolerance(jpdata, pgxdata) < 4) - self.assertTrue(mse(jpdata, pgxdata) < 1.47) - - def test_ETS_C0P0_p0_11_j2k(self): - jfile = opj_data_file('input/conformance/p0_11.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p0_11.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - @unittest.skip("fprintf stderr output in r2343.") - def test_ETS_C0P0_p0_12_j2k(self): - jfile = opj_data_file('input/conformance/p0_12.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p0_12.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C0P0_p0_16_j2k(self): - jfile = opj_data_file('input/conformance/p0_16.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p0_16.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C0P1_p1_01_j2k(self): - jfile = opj_data_file('input/conformance/p1_01.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c0p1_01.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_01_j2k(self): - jfile = opj_data_file('input/conformance/p0_01.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_01_0.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_02_j2k(self): - jfile = opj_data_file('input/conformance/p0_02.j2k') - with warnings.catch_warnings(): - # There's a 0xff30 marker segment. Not illegal, but we don't - # really know what to do with it. Just ignore. - warnings.simplefilter("ignore") - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_02_0.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_03_j2k(self): - jfile = opj_data_file('input/conformance/p0_03.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_03_0.pgx') - pgxdata = read_pgx(pgxfile) - - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_04_j2k(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_04_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) - self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.776) - - pgxfile = opj_data_file('baseline/conformance/c1p0_04_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) - self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.626) - - pgxfile = opj_data_file('baseline/conformance/c1p0_04_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) - self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07) - - def test_ETS_C1P0_p0_08_j2k(self): - jfile = opj_data_file('input/conformance/p0_08.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=1) - - pgxfile = opj_data_file('baseline/conformance/c1p0_08_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_08_1.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_08_2.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - - def test_ETS_C1P0_p0_09_j2k(self): - jfile = opj_data_file('input/conformance/p0_09.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_09_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_10_j2k(self): - jfile = opj_data_file('input/conformance/p0_10.j2k') - jp2k = Jp2k(jfile) - with warnings.catch_warnings(): - # This file has an invalid ICC profile - warnings.simplefilter("ignore") - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_1.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_2.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - - def test_ETS_C1P0_p0_11_j2k(self): - jfile = opj_data_file('input/conformance/p0_11.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_11_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - @unittest.skip("fprintf stderr output in r2343.") - def test_ETS_C1P0_p0_12_j2k(self): - jfile = opj_data_file('input/conformance/p0_12.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_12_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - @unittest.skip("fprintf stderr output in r2343.") - def test_ETS_C1P0_p0_13_j2k(self): - jfile = opj_data_file('input/conformance/p0_13.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_13_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_13_1.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_13_2.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_13_3.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 3], pgxdata) - - def test_ETS_C1P0_p0_14_j2k(self): - jfile = opj_data_file('input/conformance/p0_14.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_14_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_14_1.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_14_2.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - - def test_ETS_C1P0_p0_15_j2k(self): - jfile = opj_data_file('input/conformance/p0_15.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_15_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P0_p0_16_j2k(self): - jfile = opj_data_file('input/conformance/p0_16.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_16_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P1_p1_01_j2k(self): - jfile = opj_data_file('input/conformance/p1_01.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p1_01_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata, pgxdata) - - def test_ETS_C1P1_p1_02_j2k(self): - jfile = opj_data_file('input/conformance/p1_02.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p1_02_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 5) - self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.765) - - pgxfile = opj_data_file('baseline/conformance/c1p1_02_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 4) - self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.616) - - pgxfile = opj_data_file('baseline/conformance/c1p1_02_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) - self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.051) - - def test_ETS_C1P1_p1_04_j2k(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - - pgxfile = opj_data_file('baseline/conformance/c1p1_04_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata, pgxdata) < 624) - self.assertTrue(mse(jpdata, pgxdata) < 3080) - - @unittest.skip("fprintf stderr output in r2343.") - def test_ETS_C1P1_p1_05_j2k(self): - jfile = opj_data_file('input/conformance/p1_05.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - - pgxfile = opj_data_file('baseline/conformance/c1p1_05_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 40) - self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 8.458) - - pgxfile = opj_data_file('baseline/conformance/c1p1_05_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 40) - self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 9.816) - - pgxfile = opj_data_file('baseline/conformance/c1p1_05_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 40) - self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 10.154) - - @unittest.skip("fprintf stderr output in r2343.") - def test_ETS_C1P1_p1_06_j2k(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - - pgxfile = opj_data_file('baseline/conformance/c1p1_06_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 2) - self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 0.6) - - pgxfile = opj_data_file('baseline/conformance/c1p1_06_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 1], pgxdata) < 2) - self.assertTrue(mse(jpdata[:, :, 1], pgxdata) < 0.6) - - pgxfile = opj_data_file('baseline/conformance/c1p1_06_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 2) - self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 0.6) - - def test_ETS_JP2_file1(self): - jfile = opj_data_file('input/conformance/file1.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (512, 768, 3)) - - def test_ETS_JP2_file2(self): - jfile = opj_data_file('input/conformance/file2.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (640, 480, 3)) - - def test_ETS_JP2_file4(self): - jfile = opj_data_file('input/conformance/file4.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (512, 768)) - - def test_ETS_JP2_file5(self): - """ETS_JP2_file5""" - jfile = opj_data_file('input/conformance/file5.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (512, 768, 3)) - - def test_ETS_JP2_file6(self): - """ETS_JP2_file6""" - jfile = opj_data_file('input/conformance/file6.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (512, 768)) - - def test_ETS_JP2_file7(self): - """ETS_JP2_file7""" - jfile = opj_data_file('input/conformance/file7.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (640, 480, 3)) - - def test_ETS_JP2_file8(self): - """ETS_JP2_file8""" - jfile = opj_data_file('input/conformance/file8.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (400, 700)) - - def test_ETS_JP2_file9(self): - """ETS_JP2_file9""" - jfile = opj_data_file('input/conformance/file9.jp2') - jp2k = Jp2k(jfile) - jpdata = jp2k.read() - if re.match(r'[01]\.3', OPENJPEG_VERSION): - # Version 1.3 reads in the image as the palette indices. - self.assertEqual(jpdata.shape, (512, 768)) - else: - self.assertEqual(jpdata.shape, (512, 768, 3)) - - def test_NR_DEC_Bretagne2_j2k_1_decode(self): - """test_NR_DEC_Bretagne2_j2k_1_decode""" - jfile = opj_data_file('input/nonregression/Bretagne2.j2k') - jp2 = Jp2k(jfile) - jp2.read() - self.assertTrue(True) - - def test_NR_DEC__00042_j2k_2_decode(self): - """NR_DEC__00042_j2k_2_decode""" - jfile = opj_data_file('input/nonregression/_00042.j2k') - jp2 = Jp2k(jfile) - jp2.read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_123_j2c_3_decode(self): - """NR_DEC_123_j2c_3_decode""" - jfile = opj_data_file('input/nonregression/123.j2c') - jp2 = Jp2k(jfile) - jp2.read() - self.assertTrue(True) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_broken_jp2_4_decode(self): - """NR_DEC_broken_jp2_4_decode""" - jfile = opj_data_file('input/nonregression/broken.jp2') - with self.assertWarns(UserWarning): - # colr box has bad length. - jp2 = Jp2k(jfile) - with self.assertRaises(ValueError): - jp2.read() - self.assertTrue(True) - - @unittest.skipIf(re.match(r'[01]\.[34]', OPENJPEG_VERSION), - "Segfaults openjpeg 1.4 and earlier.") - def test_NR_DEC_broken2_jp2_5_decode(self): - """NR_DEC_broken2_jp2_5_decode""" - # Null pointer access - jfile = opj_data_file('input/nonregression/broken2.jp2') - with self.assertRaises(ValueError): - with warnings.catch_warnings(): - # Library warning, invalid number of subbands. - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_broken3_jp2_6_decode(self): - """NR_DEC_broken3_jp2_6_decode""" - jfile = opj_data_file('input/nonregression/broken3.jp2') - with self.assertWarns(UserWarning): - # colr box has bad length. - j = Jp2k(jfile) - - with self.assertRaises(ValueError): - j.read() - - @unittest.skipIf(re.match(r'[01]\.[34]', OPENJPEG_VERSION), - "Segfaults openjpeg 1.4 and earlier.") - def test_NR_DEC_broken4_jp2_7_decode(self): - """NR_DEC_broken4_jp2_7_decode""" - # Null pointer access - jfile = opj_data_file('input/nonregression/broken4.jp2') - with self.assertRaises(ValueError): - with warnings.catch_warnings(): - # Library warning, invalid number of subbands. - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_bug_j2c_8_decode(self): - """NR_DEC_bug_j2c_8_decode""" - jfile = opj_data_file('input/nonregression/bug.j2c') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_buxI_j2k_9_decode(self): - """NR_DEC_buxI_j2k_9_decode""" - jfile = opj_data_file('input/nonregression/buxI.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_buxR_j2k_10_decode(self): - """NR_DEC_buxR_j2k_10_decode""" - jfile = opj_data_file('input/nonregression/buxR.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode(self): - """NR_DEC_Cannotreaddatawithnosizeknown_j2k_11_decode""" - relpath = 'input/nonregression/Cannotreaddatawithnosizeknown.j2k' - jfile = opj_data_file(relpath) - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_cthead1_j2k_12_decode(self): - """NR_DEC_cthead1_j2k_12_decode""" - jfile = opj_data_file('input/nonregression/cthead1.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode(self): - """NR_DEC_CT_Phillips_JPEG2K_Decompr_Problem_j2k_13_decode""" - relpath = 'input/nonregression/CT_Phillips_JPEG2K_Decompr_Problem.j2k' - jfile = opj_data_file(relpath) - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_illegalcolortransform_j2k_14_decode(self): - """Stream too short, expected SOT.""" - jfile = opj_data_file('input/nonregression/illegalcolortransform.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_j2k32_j2k_15_decode(self): - """NR_DEC_j2k32_j2k_15_decode""" - jfile = opj_data_file('input/nonregression/j2k32.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): - """NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode""" - relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' - jfile = opj_data_file(relpath) - with warnings.catch_warnings(): - # This file has an invalid ICC profile - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): - """NR_DEC_MarkerIsNotCompliant_j2k_17_decode""" - jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_Marrin_jp2_18_decode(self): - """NR_DEC_Marrin_jp2_18_decode""" - jfile = opj_data_file('input/nonregression/Marrin.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_movie_00000_j2k_20_decode(self): - """test_NR_DEC_movie_00000_j2k_20_decode""" - jfile = opj_data_file('input/nonregression/movie_00000.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_movie_00001_j2k_21_decode(self): - """NR_DEC_movie_00001_j2k_21_decode""" - jfile = opj_data_file('input/nonregression/movie_00001.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_movie_00002_j2k_22_decode(self): - """NR_DEC_movie_00002_j2k_22_decode""" - jfile = opj_data_file('input/nonregression/movie_00002.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_lin_j2k_j2k_23_decode(self): - """NR_DEC_orb_blue_lin_j2k_j2k_23_decode""" - jfile = opj_data_file('input/nonregression/orb-blue10-lin-j2k.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_orb_blue_win_j2k_j2k_24_decode(self): - """NR_DEC_orb_blue_win_j2k_j2k_24_decode""" - jfile = opj_data_file('input/nonregression/orb-blue10-win-j2k.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nc_dec_orb_blue_lin_jp2_25_decode(self): - """NR-DEC-orb-blue-lin.jp2-25-decode""" - jfile = opj_data_file('input/nonregression/orb-blue10-lin-jp2.jp2') - with warnings.catch_warnings(): - # This file has an invalid ICC profile - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nr_dec_orb_blue_win_jp2_26_decode(self): - """NR-DEC-orb-blue-win.jp2-26-decode""" - jfile = opj_data_file('input/nonregression/orb-blue10-win-jp2.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nr_dec_relax_jp2_27_decode(self): - """NR-DEC-relax.jp2-27-decode""" - jfile = opj_data_file('input/nonregression/relax.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nr_dec_test_lossless_j2k_28_decode(self): - """NR-DEC-test-lossless.j2k-28-decode""" - jfile = opj_data_file('input/nonregression/test_lossless.j2k') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nr_dec_issue104_jpxstream_jp2_33_decode(self): - """NR-DEC-issue104-jpxstream.jp2-33-decode""" - jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_nr_dec_file_409752_jp2_40_decode(self): - """NR-DEC-file-409752.jp2-40-decode""" - jfile = opj_data_file('input/nonregression/file409752.jp2') - j = Jp2k(jfile) - with self.assertRaises(RuntimeError): - j.read() - if __name__ == "__main__": unittest.main() From 21ef942104a38719176eae4542f4492841ed46a8 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 6 Sep 2013 11:07:40 -0400 Subject: [PATCH 062/122] Can get full run with test_opj_suite refactoring. #110 test_opj_suite refactored to not repeat tests. --- glymur/test/test_jp2k.py | 2 + glymur/test/test_opj_suite.py | 1214 +++++++++++++++++---------------- 2 files changed, 619 insertions(+), 597 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 699fef7..442ae67 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -752,6 +752,8 @@ class TestJp2k(unittest.TestCase): self.assertFalse('Make' in exif['Image'].keys()) +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is not None, + "Don't bother if openjp2 is present.") @unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, "Missing openjpeg library.") class TestJp2k15(unittest.TestCase): diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index c6dfbda..3c6b5d2 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -114,29 +114,6 @@ class TestSuite(unittest.TestCase): self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 33) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 55.8) - def test_ETS_C0P0_p0_05_j2k(self): - jfile = opj_data_file('input/conformance/p0_05.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands(rlevel=3) - - pgxfile = opj_data_file('baseline/conformance/c0p0_05.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54) - self.assertTrue(mse(jpdata[0], pgxdata) < 68) - - @unittest.skip("8-bit pgx data vs 12-bit j2k data") - def test_ETS_C0P0_p0_06_j2k(self): - jfile = opj_data_file('input/conformance/p0_06.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands(rlevel=3) - - pgxfile = opj_data_file('baseline/conformance/c0p0_06.pgx') - pgxdata = read_pgx(pgxfile) - tol = peak_tolerance(jpdata[0], pgxdata) - self.assertTrue(tol < 109) - m = mse(jpdata[0], pgxdata) - self.assertTrue(m < 743) - @unittest.skip("Known failure in OPENJPEG test suite.") def test_ETS_C0P0_p0_07_j2k(self): jfile = opj_data_file('input/conformance/p0_07.j2k') @@ -280,17 +257,6 @@ class TestSuite(unittest.TestCase): self.assertTrue(peak_tolerance(jpdata[:, :, 0], pgxdata) < 35) self.assertTrue(mse(jpdata[:, :, 0], pgxdata) < 74) - def test_ETS_C0P1_p1_03_j2k(self): - jfile = opj_data_file('input/conformance/p1_03.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands(rlevel=3) - - pgxfile = opj_data_file('baseline/conformance/c0p1_03.pgx') - pgxdata = read_pgx(pgxfile) - - self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 28) - self.assertTrue(mse(jpdata[0], pgxdata) < 18.8) - @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C0P1_p1_04_j2k(self): jfile = opj_data_file('input/conformance/p1_04.j2k') @@ -406,56 +372,6 @@ class TestSuite(unittest.TestCase): self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.07) - def test_ETS_C1P0_p0_05_j2k(self): - jfile = opj_data_file('input/conformance/p0_05.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands() - - pgxfile = opj_data_file('baseline/conformance/c1p0_05_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) - self.assertTrue(mse(jpdata[0], pgxdata) < 0.302) - - pgxfile = opj_data_file('baseline/conformance/c1p0_05_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) - self.assertTrue(mse(jpdata[1], pgxdata) < 0.307) - - pgxfile = opj_data_file('baseline/conformance/c1p0_05_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 2) - self.assertTrue(mse(jpdata[2], pgxdata) < 0.269) - - pgxfile = opj_data_file('baseline/conformance/c1p0_05_3.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) - self.assertTrue(mse(jpdata[3], pgxdata) == 0) - - def test_ETS_C1P0_p0_06_j2k(self): - jfile = opj_data_file('input/conformance/p0_06.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands() - - pgxfile = opj_data_file('baseline/conformance/c1p0_06_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 635) - self.assertTrue(mse(jpdata[0], pgxdata) < 11287) - - pgxfile = opj_data_file('baseline/conformance/c1p0_06_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 403) - self.assertTrue(mse(jpdata[1], pgxdata) < 6124) - - pgxfile = opj_data_file('baseline/conformance/c1p0_06_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 378) - self.assertTrue(mse(jpdata[2], pgxdata) < 3968) - - pgxfile = opj_data_file('baseline/conformance/c1p0_06_3.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) - self.assertTrue(mse(jpdata[3], pgxdata) == 0) - @unittest.skip("Known failure in OPENJPEG test suite operation.") def test_ETS_C1P0_p0_07_j2k(self): jfile = opj_data_file('input/conformance/p0_07.j2k') @@ -500,23 +416,6 @@ class TestSuite(unittest.TestCase): pgxdata = read_pgx(pgxfile) np.testing.assert_array_equal(jpdata, pgxdata) - def test_ETS_C1P0_p0_10_j2k(self): - jfile = opj_data_file('input/conformance/p0_10.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read(rlevel=0) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_1.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) - - pgxfile = opj_data_file('baseline/conformance/c1p0_10_2.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) - def test_ETS_C1P0_p0_11_j2k(self): jfile = opj_data_file('input/conformance/p0_11.j2k') jp2k = Jp2k(jfile) @@ -622,30 +521,6 @@ class TestSuite(unittest.TestCase): self.assertTrue(peak_tolerance(jpdata[:, :, 2], pgxdata) < 6) self.assertTrue(mse(jpdata[:, :, 2], pgxdata) < 1.051) - def test_ETS_C1P1_p1_03_j2k(self): - jfile = opj_data_file('input/conformance/p1_03.j2k') - jp2k = Jp2k(jfile) - jpdata = jp2k.read_bands() - - pgxfile = opj_data_file('baseline/conformance/c1p1_03_0.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) - self.assertTrue(mse(jpdata[0], pgxdata) < 0.3) - - pgxfile = opj_data_file('baseline/conformance/c1p1_03_1.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) - self.assertTrue(mse(jpdata[1], pgxdata) < 0.21) - - pgxfile = opj_data_file('baseline/conformance/c1p1_03_2.pgx') - pgxdata = read_pgx(pgxfile) - self.assertTrue(peak_tolerance(jpdata[2], pgxdata) <= 1) - self.assertTrue(mse(jpdata[2], pgxdata) < 0.2) - - pgxfile = opj_data_file('baseline/conformance/c1p1_03_3.pgx') - pgxdata = read_pgx(pgxfile) - np.testing.assert_array_equal(jpdata[3], pgxdata) - def test_ETS_C1P1_p1_04_j2k(self): jfile = opj_data_file('input/conformance/p1_04.j2k') jp2k = Jp2k(jfile) @@ -802,16 +677,6 @@ class TestSuite(unittest.TestCase): jp2.read() self.assertTrue(True) - def test_NR_DEC_broken2_jp2_5_decode(self): - # Null pointer access - jfile = opj_data_file('input/nonregression/broken2.jp2') - with self.assertRaises(IOError): - with warnings.catch_warnings(): - # Invalid marker ID. - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - @unittest.skipIf(sys.hexversion < 0x03020000, "Uses features introduced in 3.2.") def test_NR_DEC_broken3_jp2_6_decode(self): @@ -823,15 +688,6 @@ class TestSuite(unittest.TestCase): with self.assertRaises(IOError): j.read() - def test_NR_DEC_broken4_jp2_7_decode(self): - jfile = opj_data_file('input/nonregression/broken4.jp2') - with self.assertRaises(IOError): - with warnings.catch_warnings(): - # invalid number of subbands, bad marker ID - warnings.simplefilter("ignore") - Jp2k(jfile).read() - self.assertTrue(True) - @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_bug_j2c_8_decode(self): jfile = opj_data_file('input/nonregression/bug.j2c') @@ -877,12 +733,6 @@ class TestSuite(unittest.TestCase): Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): - relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' - jfile = opj_data_file(relpath) - Jp2k(jfile).read() - self.assertTrue(True) - def test_NR_DEC_MarkerIsNotCompliant_j2k_17_decode(self): jfile = opj_data_file('input/nonregression/MarkerIsNotCompliant.j2k') Jp2k(jfile).read() @@ -893,11 +743,6 @@ class TestSuite(unittest.TestCase): Jp2k(jfile).read() self.assertTrue(True) - def test_NR_DEC_merged_jp2_19_decode(self): - jfile = opj_data_file('input/nonregression/merged.jp2') - Jp2k(jfile).read_bands() - self.assertTrue(True) - def test_NR_DEC_movie_00000_j2k_20_decode(self): jfile = opj_data_file('input/nonregression/movie_00000.j2k') Jp2k(jfile).read() @@ -946,369 +791,11 @@ class TestSuite(unittest.TestCase): Jp2k(jfile).read() self.assertTrue(True) - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test known to fail in v2.0.0 official") - def test_NR_DEC_text_GBR_jp2_29_decode(self): - jfile = opj_data_file('input/nonregression/text_GBR.jp2') - with warnings.catch_warnings(): - # brand is 'jp2 ', but has any icc profile. - warnings.simplefilter("ignore") - jp2 = Jp2k(jfile) - jp2.read() - self.assertTrue(True) - def test_NR_DEC_pacs_ge_j2k_30_decode(self): jfile = opj_data_file('input/nonregression/pacs.ge.j2k') Jp2k(jfile).read() self.assertTrue(True) - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test known to fail in v2.0.0 official") - def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test known to fail in v2.0.0 official") - def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): - jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') - Jp2k(jfile).read(layer=2) - self.assertTrue(True) - - def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): - jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test known to fail in v2.0.0 official") - def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): - jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') - with warnings.catch_warnings(): - # This file has a bad pclr box, we test for this elsewhere. - warnings.simplefilter("ignore") - j = Jp2k(jfile) - j.read() - self.assertTrue(True) - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test known to fail in v2.0.0 official") - def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): - jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): - f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' - jfile = opj_data_file(f) - with warnings.catch_warnings(): - # Invalid number of resolutions. - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test not in done in v2.0.0 official") - def test_NR_DEC_jp2_36_decode(self): - lst = ('input', - 'nonregression', - 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') - jfile = opj_data_file('/'.join(lst)) - with warnings.catch_warnings(): - # Invalid component number. - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test not in done in v2.0.0 official") - def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' - jfile = opj_data_file(relpath) - with warnings.catch_warnings(): - # Invalid number of tiles. - warnings.simplefilter("ignore") - j = Jp2k(jfile) - with self.assertRaises(IOError): - j.read() - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test not in done in v2.0.0 official") - @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), - "Segfaults 1.5") - def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): - relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' - jfile = opj_data_file(relpath) - with warnings.catch_warnings(): - # Invalid subsampling value - warnings.simplefilter("ignore") - with self.assertRaises(IOError): - Jp2k(jfile).read() - - def test_NR_DEC_file_409752_jp2_40_decode(self): - jfile = opj_data_file('input/nonregression/file409752.jp2') - with self.assertRaises(RuntimeError): - Jp2k(jfile).read() - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test not in done in v2.0.0 official") - @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), - "Segfaults 1.5") - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self): - # Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it - # really does deserve a warning. - relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' - jfile = opj_data_file(relpath) - with self.assertWarns(UserWarning): - Jp2k(jfile).read() - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Test not in done in v2.0.0 official") - def test_NR_DEC_issue206_image_000_jp2_42_decode(self): - jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') - Jp2k(jfile).read() - self.assertTrue(True) - - def test_NR_DEC_p1_04_j2k_43_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 1024, 1024)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata) - - def test_NR_DEC_p1_04_j2k_44_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(640, 512, 768, 640)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[640:768, 512:640]) - - def test_NR_DEC_p1_04_j2k_45_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(896, 896, 1024, 1024)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_46_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(500, 100, 800, 300)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[500:800, 100:300]) - - def test_NR_DEC_p1_04_j2k_47_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 600, 360)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:600, 260:360]) - - def test_NR_DEC_p1_04_j2k_48_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 660, 360)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:660, 260:360]) - - def test_NR_DEC_p1_04_j2k_49_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 360, 600, 400)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[520:600, 360:400]) - - def test_NR_DEC_p1_04_j2k_50_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 1024, 1024), rlevel=2) - odata = jp2k.read(rlevel=2) - - np.testing.assert_array_equal(ssdata, odata[0:256, 0:256]) - - def test_NR_DEC_p1_04_j2k_51_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(640, 512, 768, 640), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[160:192, 128:160]) - - def test_NR_DEC_p1_04_j2k_52_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(896, 896, 1024, 1024), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[224:352, 224:352]) - - def test_NR_DEC_p1_04_j2k_53_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(500, 100, 800, 300), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[125:200, 25:75]) - - def test_NR_DEC_p1_04_j2k_54_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 600, 360), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[130:150, 65:90]) - - def test_NR_DEC_p1_04_j2k_55_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 260, 660, 360), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[130:165, 65:90]) - - def test_NR_DEC_p1_04_j2k_56_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(520, 360, 600, 400), rlevel=2) - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(ssdata, odata[130:150, 90:100]) - - def test_NR_DEC_p1_04_j2k_57_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63) # last tile - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) - - def test_NR_DEC_p1_04_j2k_58_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=63, rlevel=2) # last tile - odata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) - - def test_NR_DEC_p1_04_j2k_59_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12) # 2nd row, 5th column - odata = jp2k.read() - np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) - - def test_NR_DEC_p1_04_j2k_60_decode(self): - jfile = opj_data_file('input/conformance/p1_04.j2k') - jp2k = Jp2k(jfile) - tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column - odata = jp2k.read(rlevel=1) - np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_61_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 12, 12)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[0:12, 0:12]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_62_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(1, 8, 8, 11)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[1:8, 8:11]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_63_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(9, 9, 12, 12)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[9:12, 9:12]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_64_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 4, 12, 10)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[10:12, 4:10]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_65_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(3, 3, 9, 9)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[3:9, 3:9]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_66_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 7, 7)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[4:7, 4:7]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_67_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 5, 5)) - odata = jp2k.read() - np.testing.assert_array_equal(ssdata, odata[4:5, 4: 5]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_68_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 12, 12), rlevel=1) - odata = jp2k.read(rlevel=1) - np.testing.assert_array_equal(ssdata, odata[0:6, 0:6]) - - @unittest.skip("fprintf stderr output in r2343.") - def test_NR_DEC_p1_06_j2k_69_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(1, 8, 8, 11), rlevel=1) - self.assertEqual(ssdata.shape, (3, 2, 3)) - - def test_NR_DEC_p1_06_j2k_70_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=1) - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_71_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 4, 12, 10), rlevel=1) - self.assertEqual(ssdata.shape, (1, 3, 3)) - - def test_NR_DEC_p1_06_j2k_72_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(3, 3, 9, 9), rlevel=1) - self.assertEqual(ssdata.shape, (3, 3, 3)) - - def test_NR_DEC_p1_06_j2k_73_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 7, 7), rlevel=1) - self.assertEqual(ssdata.shape, (2, 2, 3)) - - def test_NR_DEC_p1_06_j2k_74_decode(self): - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(4, 4, 5, 5), rlevel=1) - self.assertEqual(ssdata.shape, (1, 1, 3)) - - def test_NR_DEC_p1_06_j2k_75_decode(self): - # Image size would be 0 x 0. - jfile = opj_data_file('input/conformance/p1_06.j2k') - jp2k = Jp2k(jfile) - with self.assertRaises((IOError, OSError)): - jp2k.read(area=(9, 9, 12, 12), rlevel=2) - @unittest.skip("fprintf stderr output in r2343.") def test_NR_DEC_p1_06_j2k_76_decode(self): jfile = opj_data_file('input/conformance/p1_06.j2k') @@ -1389,90 +876,6 @@ class TestSuite(unittest.TestCase): jp2k = Jp2k(jfile) jp2k.read(rlevel=4) - def test_NR_DEC_p0_04_j2k_85_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 256, 256)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata) - - def test_NR_DEC_p0_04_j2k_86_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 128, 128, 256)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata) - - def test_NR_DEC_p0_04_j2k_87_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 50, 200, 120)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata) - - def test_NR_DEC_p0_04_j2k_88_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(150, 10, 210, 190)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata) - - def test_NR_DEC_p0_04_j2k_89_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(80, 100, 150, 200)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata) - - def test_NR_DEC_p0_04_j2k_90_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(20, 150, 50, 200)) - fulldata = jp2k.read() - np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata) - - def test_NR_DEC_p0_04_j2k_91_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 0, 256, 256), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata) - - def test_NR_DEC_p0_04_j2k_92_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(0, 128, 128, 256), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata) - - def test_NR_DEC_p0_04_j2k_93_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(10, 50, 200, 120), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata) - - def test_NR_DEC_p0_04_j2k_94_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(150, 10, 210, 190), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata) - - def test_NR_DEC_p0_04_j2k_95_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(80, 100, 150, 200), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata) - - def test_NR_DEC_p0_04_j2k_96_decode(self): - jfile = opj_data_file('input/conformance/p0_04.j2k') - jp2k = Jp2k(jfile) - ssdata = jp2k.read(area=(20, 150, 50, 200), rlevel=2) - fulldata = jp2k.read(rlevel=2) - np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata) - @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") @@ -7317,5 +6720,622 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) +@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), + "Feature not supported in glymur until openjpeg 2.0") +class TestSuite_bands(unittest.TestCase): + """Runs tests introduced in version 1.x but only pass in glymur with 2.0 + + The deal here is that the feature works with 1.x, but glymur only supports + it with version 2.0. + """ + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_ETS_C0P0_p0_05_j2k(self): + jfile = opj_data_file('input/conformance/p0_05.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands(rlevel=3) + + pgxfile = opj_data_file('baseline/conformance/c0p0_05.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 54) + self.assertTrue(mse(jpdata[0], pgxdata) < 68) + + @unittest.skip("8-bit pgx data vs 12-bit j2k data") + def test_ETS_C0P0_p0_06_j2k(self): + jfile = opj_data_file('input/conformance/p0_06.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands(rlevel=3) + + pgxfile = opj_data_file('baseline/conformance/c0p0_06.pgx') + pgxdata = read_pgx(pgxfile) + tol = peak_tolerance(jpdata[0], pgxdata) + self.assertTrue(tol < 109) + m = mse(jpdata[0], pgxdata) + self.assertTrue(m < 743) + + def test_ETS_C0P1_p1_03_j2k(self): + jfile = opj_data_file('input/conformance/p1_03.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands(rlevel=3) + + pgxfile = opj_data_file('baseline/conformance/c0p1_03.pgx') + pgxdata = read_pgx(pgxfile) + + self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 28) + self.assertTrue(mse(jpdata[0], pgxdata) < 18.8) + + def test_ETS_C1P1_p1_03_j2k(self): + jfile = opj_data_file('input/conformance/p1_03.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands() + + pgxfile = opj_data_file('baseline/conformance/c1p1_03_0.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) + self.assertTrue(mse(jpdata[0], pgxdata) < 0.3) + + pgxfile = opj_data_file('baseline/conformance/c1p1_03_1.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) + self.assertTrue(mse(jpdata[1], pgxdata) < 0.21) + + pgxfile = opj_data_file('baseline/conformance/c1p1_03_2.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[2], pgxdata) <= 1) + self.assertTrue(mse(jpdata[2], pgxdata) < 0.2) + + pgxfile = opj_data_file('baseline/conformance/c1p1_03_3.pgx') + pgxdata = read_pgx(pgxfile) + np.testing.assert_array_equal(jpdata[3], pgxdata) + + def test_ETS_C1P0_p0_05_j2k(self): + jfile = opj_data_file('input/conformance/p0_05.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands() + + pgxfile = opj_data_file('baseline/conformance/c1p0_05_0.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 2) + self.assertTrue(mse(jpdata[0], pgxdata) < 0.302) + + pgxfile = opj_data_file('baseline/conformance/c1p0_05_1.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 2) + self.assertTrue(mse(jpdata[1], pgxdata) < 0.307) + + pgxfile = opj_data_file('baseline/conformance/c1p0_05_2.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 2) + self.assertTrue(mse(jpdata[2], pgxdata) < 0.269) + + pgxfile = opj_data_file('baseline/conformance/c1p0_05_3.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) + self.assertTrue(mse(jpdata[3], pgxdata) == 0) + + def test_ETS_C1P0_p0_06_j2k(self): + jfile = opj_data_file('input/conformance/p0_06.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read_bands() + + pgxfile = opj_data_file('baseline/conformance/c1p0_06_0.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[0], pgxdata) < 635) + self.assertTrue(mse(jpdata[0], pgxdata) < 11287) + + pgxfile = opj_data_file('baseline/conformance/c1p0_06_1.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[1], pgxdata) < 403) + self.assertTrue(mse(jpdata[1], pgxdata) < 6124) + + pgxfile = opj_data_file('baseline/conformance/c1p0_06_2.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[2], pgxdata) < 378) + self.assertTrue(mse(jpdata[2], pgxdata) < 3968) + + pgxfile = opj_data_file('baseline/conformance/c1p0_06_3.pgx') + pgxdata = read_pgx(pgxfile) + self.assertTrue(peak_tolerance(jpdata[3], pgxdata) == 0) + self.assertTrue(mse(jpdata[3], pgxdata) == 0) + + def test_NR_DEC_merged_jp2_19_decode(self): + jfile = opj_data_file('input/nonregression/merged.jp2') + Jp2k(jfile).read_bands() + self.assertTrue(True) + + +@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), + "Tests not passing until 2.0") +class TestSuite2point0(unittest.TestCase): + """Runs tests introduced in version 2.0 or that pass only in 2.0""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_ETS_C1P0_p0_10_j2k(self): + jfile = opj_data_file('input/conformance/p0_10.j2k') + jp2k = Jp2k(jfile) + jpdata = jp2k.read(rlevel=0) + + pgxfile = opj_data_file('baseline/conformance/c1p0_10_0.pgx') + pgxdata = read_pgx(pgxfile) + np.testing.assert_array_equal(jpdata[:, :, 0], pgxdata) + + pgxfile = opj_data_file('baseline/conformance/c1p0_10_1.pgx') + pgxdata = read_pgx(pgxfile) + np.testing.assert_array_equal(jpdata[:, :, 1], pgxdata) + + pgxfile = opj_data_file('baseline/conformance/c1p0_10_2.pgx') + pgxdata = read_pgx(pgxfile) + np.testing.assert_array_equal(jpdata[:, :, 2], pgxdata) + + def test_NR_DEC_broken2_jp2_5_decode(self): + # Null pointer access + jfile = opj_data_file('input/nonregression/broken2.jp2') + with self.assertRaises(IOError): + with warnings.catch_warnings(): + # Invalid marker ID. + warnings.simplefilter("ignore") + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_broken4_jp2_7_decode(self): + jfile = opj_data_file('input/nonregression/broken4.jp2') + with self.assertRaises(IOError): + with warnings.catch_warnings(): + # invalid number of subbands, bad marker ID + warnings.simplefilter("ignore") + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_kakadu_v4_4_openjpegv2_broken_j2k_16_decode(self): + # This test actually passes in 1.5, but produces unpleasant warning + # messages that cannot be turned off? + relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' + jfile = opj_data_file(relpath) + Jp2k(jfile).read() + self.assertTrue(True) + + +@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, + "Test not in done in v2.0.0 official") +@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), + "Tests not introduced until 2.1") +class TestSuite2point1(unittest.TestCase): + """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_NR_DEC_text_GBR_jp2_29_decode(self): + jfile = opj_data_file('input/nonregression/text_GBR.jp2') + with warnings.catch_warnings(): + # brand is 'jp2 ', but has any icc profile. + warnings.simplefilter("ignore") + jp2 = Jp2k(jfile) + jp2.read() + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_31_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_kodak_2layers_lrcp_j2c_32_decode(self): + jfile = opj_data_file('input/nonregression/kodak_2layers_lrcp.j2c') + Jp2k(jfile).read(layer=2) + self.assertTrue(True) + + def test_NR_DEC_issue104_jpxstream_jp2_33_decode(self): + jfile = opj_data_file('input/nonregression/issue104_jpxstream.jp2') + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_mem_b2ace68c_1381_jp2_34_decode(self): + jfile = opj_data_file('input/nonregression/mem-b2ace68c-1381.jp2') + with warnings.catch_warnings(): + # This file has a bad pclr box, we test for this elsewhere. + warnings.simplefilter("ignore") + j = Jp2k(jfile) + j.read() + self.assertTrue(True) + + def test_NR_DEC_mem_b2b86b74_2753_jp2_35_decode(self): + jfile = opj_data_file('input/nonregression/mem-b2b86b74-2753.jp2') + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_gdal_fuzzer_unchecked_num_resolutions_jp2_36_decode(self): + f = 'input/nonregression/gdal_fuzzer_unchecked_numresolutions.jp2' + jfile = opj_data_file(f) + with warnings.catch_warnings(): + # Invalid number of resolutions. + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + j.read() + + def test_NR_DEC_gdal_fuzzer_check_number_of_tiles_jp2_38_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_number_of_tiles.jp2' + jfile = opj_data_file(relpath) + with warnings.catch_warnings(): + # Invalid number of tiles. + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + j.read() + + def test_NR_DEC_gdal_fuzzer_check_comp_dx_dy_jp2_39_decode(self): + relpath = 'input/nonregression/gdal_fuzzer_check_comp_dx_dy.jp2' + jfile = opj_data_file(relpath) + with warnings.catch_warnings(): + # Invalid subsampling value + warnings.simplefilter("ignore") + with self.assertRaises(IOError): + Jp2k(jfile).read() + + def test_NR_DEC_file_409752_jp2_40_decode(self): + jfile = opj_data_file('input/nonregression/file409752.jp2') + with self.assertRaises(RuntimeError): + Jp2k(jfile).read() + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_NR_DEC_issue188_beach_64bitsbox_jp2_41_decode(self): + # Has an 'XML ' box instead of 'xml '. Yes that is pedantic, but it + # really does deserve a warning. + relpath = 'input/nonregression/issue188_beach_64bitsbox.jp2' + jfile = opj_data_file(relpath) + with self.assertWarns(UserWarning): + Jp2k(jfile).read() + + def test_NR_DEC_issue206_image_000_jp2_42_decode(self): + jfile = opj_data_file('input/nonregression/issue206_image-000.jp2') + Jp2k(jfile).read() + self.assertTrue(True) + + def test_NR_DEC_p1_04_j2k_43_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 1024, 1024)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata) + + def test_NR_DEC_p1_04_j2k_44_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(640, 512, 768, 640)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[640:768, 512:640]) + + def test_NR_DEC_p1_04_j2k_45_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(896, 896, 1024, 1024)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_46_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(500, 100, 800, 300)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[500:800, 100:300]) + + def test_NR_DEC_p1_04_j2k_47_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 600, 360)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:600, 260:360]) + + def test_NR_DEC_p1_04_j2k_48_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 660, 360)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:660, 260:360]) + + def test_NR_DEC_p1_04_j2k_49_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 360, 600, 400)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[520:600, 360:400]) + + def test_NR_DEC_p1_04_j2k_50_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 1024, 1024), rlevel=2) + odata = jp2k.read(rlevel=2) + + np.testing.assert_array_equal(ssdata, odata[0:256, 0:256]) + + def test_NR_DEC_p1_04_j2k_51_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(640, 512, 768, 640), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[160:192, 128:160]) + + def test_NR_DEC_p1_04_j2k_52_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(896, 896, 1024, 1024), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[224:352, 224:352]) + + def test_NR_DEC_p1_04_j2k_53_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(500, 100, 800, 300), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[125:200, 25:75]) + + def test_NR_DEC_p1_04_j2k_54_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 600, 360), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[130:150, 65:90]) + + def test_NR_DEC_p1_04_j2k_55_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 260, 660, 360), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[130:165, 65:90]) + + def test_NR_DEC_p1_04_j2k_56_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(520, 360, 600, 400), rlevel=2) + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(ssdata, odata[130:150, 90:100]) + + def test_NR_DEC_p1_04_j2k_57_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k.read(tile=63) # last tile + odata = jp2k.read() + np.testing.assert_array_equal(tdata, odata[896:1024, 896:1024]) + + def test_NR_DEC_p1_04_j2k_58_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k.read(tile=63, rlevel=2) # last tile + odata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(tdata, odata[224:256, 224:256]) + + def test_NR_DEC_p1_04_j2k_59_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k.read(tile=12) # 2nd row, 5th column + odata = jp2k.read() + np.testing.assert_array_equal(tdata, odata[128:256, 512:640]) + + def test_NR_DEC_p1_04_j2k_60_decode(self): + jfile = opj_data_file('input/conformance/p1_04.j2k') + jp2k = Jp2k(jfile) + tdata = jp2k.read(tile=12, rlevel=1) # 2nd row, 5th column + odata = jp2k.read(rlevel=1) + np.testing.assert_array_equal(tdata, odata[64:128, 256:320]) + + def test_NR_DEC_jp2_36_decode(self): + lst = ('input', + 'nonregression', + 'gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2') + jfile = opj_data_file('/'.join(lst)) + with warnings.catch_warnings(): + # Invalid component number. + warnings.simplefilter("ignore") + j = Jp2k(jfile) + with self.assertRaises(IOError): + j.read() + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_61_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 12, 12)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[0:12, 0:12]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_62_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(1, 8, 8, 11)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[1:8, 8:11]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_63_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(9, 9, 12, 12)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[9:12, 9:12]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_64_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 4, 12, 10)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[10:12, 4:10]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_65_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(3, 3, 9, 9)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[3:9, 3:9]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_66_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 7, 7)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[4:7, 4:7]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_67_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 5, 5)) + odata = jp2k.read() + np.testing.assert_array_equal(ssdata, odata[4:5, 4: 5]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_68_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 12, 12), rlevel=1) + odata = jp2k.read(rlevel=1) + np.testing.assert_array_equal(ssdata, odata[0:6, 0:6]) + + @unittest.skip("fprintf stderr output in r2343.") + def test_NR_DEC_p1_06_j2k_69_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(1, 8, 8, 11), rlevel=1) + self.assertEqual(ssdata.shape, (3, 2, 3)) + + def test_NR_DEC_p1_06_j2k_70_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(9, 9, 12, 12), rlevel=1) + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_71_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 4, 12, 10), rlevel=1) + self.assertEqual(ssdata.shape, (1, 3, 3)) + + def test_NR_DEC_p1_06_j2k_72_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(3, 3, 9, 9), rlevel=1) + self.assertEqual(ssdata.shape, (3, 3, 3)) + + def test_NR_DEC_p1_06_j2k_73_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 7, 7), rlevel=1) + self.assertEqual(ssdata.shape, (2, 2, 3)) + + def test_NR_DEC_p1_06_j2k_74_decode(self): + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(4, 4, 5, 5), rlevel=1) + self.assertEqual(ssdata.shape, (1, 1, 3)) + + def test_NR_DEC_p1_06_j2k_75_decode(self): + # Image size would be 0 x 0. + jfile = opj_data_file('input/conformance/p1_06.j2k') + jp2k = Jp2k(jfile) + with self.assertRaises((IOError, OSError)): + jp2k.read(area=(9, 9, 12, 12), rlevel=2) + + def test_NR_DEC_p0_04_j2k_85_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 256, 256)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[0:256, 0:256], ssdata) + + def test_NR_DEC_p0_04_j2k_86_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 128, 128, 256)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[0:128, 128:256], ssdata) + + def test_NR_DEC_p0_04_j2k_87_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 50, 200, 120)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[10:200, 50:120], ssdata) + + def test_NR_DEC_p0_04_j2k_88_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(150, 10, 210, 190)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[150:210, 10:190], ssdata) + + def test_NR_DEC_p0_04_j2k_89_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(80, 100, 150, 200)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[80:150, 100:200], ssdata) + + def test_NR_DEC_p0_04_j2k_90_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(20, 150, 50, 200)) + fulldata = jp2k.read() + np.testing.assert_array_equal(fulldata[20:50, 150:200], ssdata) + + def test_NR_DEC_p0_04_j2k_91_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 0, 256, 256), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[0:64, 0:64], ssdata) + + def test_NR_DEC_p0_04_j2k_92_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(0, 128, 128, 256), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[0:32, 32:64], ssdata) + + def test_NR_DEC_p0_04_j2k_93_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(10, 50, 200, 120), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[3:50, 13:30], ssdata) + + def test_NR_DEC_p0_04_j2k_94_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(150, 10, 210, 190), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[38:53, 3:48], ssdata) + + def test_NR_DEC_p0_04_j2k_95_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(80, 100, 150, 200), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[20:38, 25:50], ssdata) + + def test_NR_DEC_p0_04_j2k_96_decode(self): + jfile = opj_data_file('input/conformance/p0_04.j2k') + jp2k = Jp2k(jfile) + ssdata = jp2k.read(area=(20, 150, 50, 200), rlevel=2) + fulldata = jp2k.read(rlevel=2) + np.testing.assert_array_equal(fulldata[5:13, 38:50], ssdata) + + if __name__ == "__main__": unittest.main() From 0bb875bfff9a166f9ac9ba0a81583285d5687ad3 Mon Sep 17 00:00:00 2001 From: jevans Date: Fri, 6 Sep 2013 12:25:56 -0400 Subject: [PATCH 063/122] test_jp2k refactored to not duplicate tests. #110 --- glymur/test/test_jp2k.py | 1499 +++++++++++++++----------------------- 1 file changed, 590 insertions(+), 909 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 442ae67..edefb7f 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -120,10 +120,164 @@ class TestJp2kBadXmlFile(unittest.TestCase): self.assertIsNone(jp2k.box[3].xml) +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and not OPENJP2_IS_V2_OFFICIAL, + "Missing openjp2 library version 2.0+.") +class TestJp2k_2_1(unittest.TestCase): + """Test suite for version 2.0+ of openjpeg software""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 2) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 4) + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_openjpeg_library_message(self): + """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 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. + tfile.write(data[0:3179]) + + # Make the DY bytes of the SIZ segment zero. That means that + # a subsampling factor is zero, which is illegal. + tfile.write(b'\x00') + tfile.write(data[3180:3182]) + tfile.write(b'\x00') + tfile.write(data[3184:3186]) + tfile.write(b'\x00') + + tfile.write(data[3186:]) + tfile.flush() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(tfile.name) + regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ + Invalid\svalues\sfor\scomp\s=\s0\s+ + :\sdx=1\sdy=0''', re.VERBOSE) + if sys.hexversion < 0x03020000: + with self.assertRaisesRegexp((IOError, OSError), regexp): + j.read(rlevel=1) + else: + with self.assertRaisesRegex((IOError, OSError), regexp): + j.read(rlevel=1) + + +@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), + "Not tested for 1.x") +class TestJp2k_2_0(unittest.TestCase): + """Test suite requiring at least version 2.0""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @unittest.skipIf(not OPENJP2_IS_V2_OFFICIAL, + "Behavior is specific to 2.0 official.") + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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(OSError): + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 4), dtype=np.uint8) + j.write(data) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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_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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data) + + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: + + # Offset of the codestream is where we start. + 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'. + write_buffer = struct.pack('>I4s', int(56), b'asoc') + tfile2.write(write_buffer) + + # Write the contained label box + 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 '. + write_buffer = struct.pack('>I4s', int(35), b'xml ') + tfile2.write(write_buffer) + + write_buffer = 'this is a test' + write_buffer = write_buffer.encode() + tfile2.write(write_buffer) + + # Now append the codestream. + tfile2.write(codestream) + tfile2.flush() + + jasoc = Jp2k(tfile2.name) + self.assertEqual(jasoc.box[3].box_id, 'asoc') + self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') + self.assertEqual(jasoc.box[3].box[0].label, 'label') + self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') + + @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""" +class TestJp2k_1_x(unittest.TestCase): + """Test suite for versions up to 1.5.1 of openjpeg but no further""" def setUp(self): self.jp2file = glymur.data.nemo() @@ -159,20 +313,6 @@ class TestJp2k(unittest.TestCase): with self.assertRaises(IOError): j.read(rlevel=6) - 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(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. - with self.assertRaises(OSError): - filename = 'this file does not actually exist on the file system.' - 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.""" @@ -358,671 +498,446 @@ class TestJp2k(unittest.TestCase): self.assertEqual(new_jp2.box[j].length, baseline_jp2.box[j].length) + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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') + + # The code block dimensions are given as rows x columns. + j.write(data, cbsize=(16, 32)) + + codestream = j.get_codestream() + + # Code block size is reported as XY in the codestream. + self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + data = np.zeros((128, 128, 2, 2), dtype=np.uint8) + j.write(data) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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""" + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + 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) + j.write(data, colorspace='rgb') + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @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) + j.write(data, colorspace='grey') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 3) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + def test_specify_ycc(self): + """Should reject YCC""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + 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_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: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, mct=False) + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + 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.""" + j2k = Jp2k(self.j2kfile) + expdata = j2k.read() + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + ofile.write(expdata[:, :, 0], mct=True) + + @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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, prog='CPRL') + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + codestream = ofile.get_codestream() + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) + + +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is not None, + "Don't bother if openjp2 is present.") +@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, + "Missing openjpeg library.") +class TestJp2k15(unittest.TestCase): + """Test suite for openjpeg 1.x, not appropriate for 2.x""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + def test_area(self): + """Area option not allowed for 1.5.1. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(area=(0, 0, 100, 100)) + + def test_tile(self): + """tile option not allowed for 1.5.1. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(tile=0) + + def test_layer(self): + """layer option not allowed for 1.5.1. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(layer=1) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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_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. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the xml box + # Length = 36, id is 'xml '. + write_buffer = struct.pack('>I4s', int(36), b'xml ') + tfile.write(write_buffer) + + write_buffer = 'this is a test' + chr(0) + write_buffer = write_buffer.encode() + tfile.write(write_buffer) + + # Get the rest of the input file. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + jp2k = Jp2k(tfile.name) + + self.assertEqual(jp2k.box[3].box_id, 'xml ') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 36) + self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), + b'this is a test') + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(re.match(r"""1\.[345]\.\d""", + OPENJPEG_VERSION) is not None, + "Segfault on official v1.x series.") + def test_openjpeg_library_message(self): + """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 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. + tfile.write(data[0:3179]) + + # Make the DY bytes of the SIZ segment zero. That means that + # a subsampling factor is zero, which is illegal. + tfile.write(b'\x00') + tfile.write(data[3180:3182]) + tfile.write(b'\x00') + tfile.write(data[3184:3186]) + tfile.write(b'\x00') + + tfile.write(data[3186:]) + tfile.flush() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(tfile.name) + regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ + Invalid\svalues\sfor\scomp\s=\s0\s+ + :\sdx=1\sdy=0''', re.VERBOSE) + if sys.hexversion < 0x03020000: + with self.assertRaisesRegexp((IOError, OSError), regexp): + j.read(rlevel=1) + else: + with self.assertRaisesRegex((IOError, OSError), regexp): + j.read(rlevel=1) + + +@unittest.skipIf(re.match(r"""1\.[012]\.\d""", OPENJPEG_VERSION), + "Unsupported version of openjpeg.") +class TestJp2k(unittest.TestCase): + """Test suite for openjpeg software starting at 1.3""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + def test_rlevel_max(self): + """Verify that rlevel=-1 gets us the lowest resolution image""" + j = Jp2k(self.j2kfile) + thumbnail1 = j.read(rlevel=-1) + thumbnail2 = j.read(rlevel=5) + np.testing.assert_array_equal(thumbnail1, thumbnail2) + self.assertEqual(thumbnail1.shape, (25, 15, 3)) + + def test_rlevel_too_high(self): + """Should error out appropriately if reduce level too high""" + j = Jp2k(self.jp2file) + with self.assertRaises(IOError): + j.read(rlevel=6) + + 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(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. + with self.assertRaises(OSError): + filename = 'this file does not actually exist on the file system.' + Jp2k(filename) + + def test_jp2_boxes(self): + """Verify the boxes of a JP2 file. Basic jp2 test.""" + jp2k = Jp2k(self.jp2file) + + # top-level boxes + self.assertEqual(len(jp2k.box), 6) + + self.assertEqual(jp2k.box[0].box_id, 'jP ') + self.assertEqual(jp2k.box[0].offset, 0) + self.assertEqual(jp2k.box[0].length, 12) + self.assertEqual(jp2k.box[0].longname, 'JPEG 2000 Signature') + + self.assertEqual(jp2k.box[1].box_id, 'ftyp') + self.assertEqual(jp2k.box[1].offset, 12) + self.assertEqual(jp2k.box[1].length, 20) + self.assertEqual(jp2k.box[1].longname, 'File Type') + + self.assertEqual(jp2k.box[2].box_id, 'jp2h') + self.assertEqual(jp2k.box[2].offset, 32) + self.assertEqual(jp2k.box[2].length, 45) + self.assertEqual(jp2k.box[2].longname, 'JP2 Header') + + self.assertEqual(jp2k.box[3].box_id, 'uuid') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 638) + + self.assertEqual(jp2k.box[4].box_id, 'uuid') + self.assertEqual(jp2k.box[4].offset, 715) + self.assertEqual(jp2k.box[4].length, 2412) + + self.assertEqual(jp2k.box[5].box_id, 'jp2c') + self.assertEqual(jp2k.box[5].offset, 3127) + self.assertEqual(jp2k.box[5].length, 1132296) + + # jp2h super box + self.assertEqual(len(jp2k.box[2].box), 2) + + self.assertEqual(jp2k.box[2].box[0].box_id, 'ihdr') + self.assertEqual(jp2k.box[2].box[0].offset, 40) + self.assertEqual(jp2k.box[2].box[0].length, 22) + self.assertEqual(jp2k.box[2].box[0].longname, 'Image Header') + self.assertEqual(jp2k.box[2].box[0].height, 1456) + self.assertEqual(jp2k.box[2].box[0].width, 2592) + self.assertEqual(jp2k.box[2].box[0].num_components, 3) + self.assertEqual(jp2k.box[2].box[0].bits_per_component, 8) + self.assertEqual(jp2k.box[2].box[0].signed, False) + self.assertEqual(jp2k.box[2].box[0].compression, 7) + self.assertEqual(jp2k.box[2].box[0].colorspace_unknown, False) + self.assertEqual(jp2k.box[2].box[0].ip_provided, False) + + self.assertEqual(jp2k.box[2].box[1].box_id, 'colr') + self.assertEqual(jp2k.box[2].box[1].offset, 62) + self.assertEqual(jp2k.box[2].box[1].length, 15) + self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification') + self.assertEqual(jp2k.box[2].box[1].precedence, 0) + self.assertEqual(jp2k.box[2].box[1].approximation, 0) + self.assertEqual(jp2k.box[2].box[1].colorspace, glymur.core.SRGB) + self.assertIsNone(jp2k.box[2].box[1].icc_profile) + + def test_j2k_box(self): + """A J2K/J2C file must not have any boxes.""" + # Verify that a J2K file has no boxes. + jp2k = Jp2k(self.j2kfile) + self.assertEqual(len(jp2k.box), 0) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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. + 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). + 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) + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + jp2k = Jp2k(tfile.name) + + self.assertEqual(jp2k.box[5].box_id, 'jp2c') + self.assertEqual(jp2k.box[5].offset, 3127) + self.assertEqual(jp2k.box[5].length, 1133427 + 8) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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. + baseline_jp2 = Jp2k(self.jp2file) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + with open(self.jp2file, 'rb') as ifile: + # Everything up until the jp2c box. + write_buffer = ifile.read(588458) + tfile.write(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) + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + new_jp2 = Jp2k(tfile.name) + + # The top level boxes in each file should match. + for j in range(len(baseline_jp2.box)): + self.assertEqual(new_jp2.box[j].box_id, + baseline_jp2.box[j].box_id) + self.assertEqual(new_jp2.box[j].offset, + baseline_jp2.box[j].offset) + self.assertEqual(new_jp2.box[j].length, + baseline_jp2.box[j].length) + def test_basic_jp2(self): """Just a very basic test that reading a JP2 file does not error out. """ j2k = Jp2k(self.jp2file) j2k.read(rlevel=1) - def test_basic_j2k(self): - """Just a very basic test that reading a J2K file does not error out. - """ - j2k = Jp2k(self.j2kfile) - j2k.read() - - @unittest.skipIf(OPJ_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 = opj_data_file('input/conformance/p0_05.j2k') - j = Jp2k(filename) - with self.assertRaises(RuntimeError): - j.read() - - def test_empty_box_with_j2k(self): - """Verify that the list of boxes in a J2C/J2K file is present, but - empty. - """ - j = Jp2k(self.j2kfile) - self.assertEqual(j.box, []) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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') - - # The code block dimensions are given as rows x columns. - j.write(data, cbsize=(16, 32)) - - codestream = j.get_codestream() - - # Code block size is reported as XY in the codestream. - self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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): - 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_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): - 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.""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - 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""" - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - 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) - j.write(data, colorspace='rgb') - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @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) - j.write(data, colorspace='grey') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 2) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 3) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 4) - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @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(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: - j = Jp2k(tfile.name, 'wb') - data = np.zeros((128, 128, 4), dtype=np.uint8) - j.write(data) - - def test_specify_ycc(self): - """Should reject YCC""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - 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. - write_buffer = ifile.read(77) - tfile.write(write_buffer) - - # Write the UINF superbox - # Length = 50, id is uinf. - 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. - 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. - 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. - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - jp2k = Jp2k(tfile.name) - - self.assertEqual(jp2k.box[3].box_id, 'uinf') - self.assertEqual(jp2k.box[3].offset, 77) - self.assertEqual(jp2k.box[3].length, 50) - - self.assertEqual(jp2k.box[3].box[0].box_id, 'ulst') - self.assertEqual(jp2k.box[3].box[0].offset, 85) - self.assertEqual(jp2k.box[3].box[0].length, 26) - ulst = [] - ulst.append(uuid.UUID('00000000-0000-0000-0000-000000000000')) - self.assertEqual(jp2k.box[3].box[0].ulst, ulst) - - self.assertEqual(jp2k.box[3].box[1].box_id, 'url ') - self.assertEqual(jp2k.box[3].box[1].offset, 111) - self.assertEqual(jp2k.box[3].box[1].length, 16) - self.assertEqual(jp2k.box[3].box[1].version, 0) - self.assertEqual(jp2k.box[3].box[1].flag, (0, 0, 0)) - self.assertEqual(jp2k.box[3].box[1].url, 'abcd') - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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. - write_buffer = ifile.read(77) - tfile.write(write_buffer) - - # Write the xml box - # Length = 36, id is 'xml '. - write_buffer = struct.pack('>I4s', int(36), b'xml ') - tfile.write(write_buffer) - - write_buffer = 'this is a test' + chr(0) - write_buffer = write_buffer.encode() - tfile.write(write_buffer) - - # Get the rest of the input file. - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - jp2k = Jp2k(tfile.name) - - self.assertEqual(jp2k.box[3].box_id, 'xml ') - self.assertEqual(jp2k.box[3].offset, 77) - self.assertEqual(jp2k.box[3].length, 36) - self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), - b'this is a test') - - @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) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) - - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - - # Offset of the codestream is where we start. - 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'. - write_buffer = struct.pack('>I4s', int(56), b'asoc') - tfile2.write(write_buffer) - - # Write the contained label box - 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 '. - write_buffer = struct.pack('>I4s', int(35), b'xml ') - tfile2.write(write_buffer) - - write_buffer = 'this is a test' - write_buffer = write_buffer.encode() - tfile2.write(write_buffer) - - # Now append the codestream. - tfile2.write(codestream) - tfile2.flush() - - jasoc = Jp2k(tfile2.name) - self.assertEqual(jasoc.box[3].box_id, 'asoc') - self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') - self.assertEqual(jasoc.box[3].box[0].label, 'label') - self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @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""" - # This will confirm that the error callback mechanism is working. - 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. - tfile.write(data[0:3179]) - - # Make the DY bytes of the SIZ segment zero. That means that - # a subsampling factor is zero, which is illegal. - tfile.write(b'\x00') - tfile.write(data[3180:3182]) - tfile.write(b'\x00') - tfile.write(data[3184:3186]) - tfile.write(b'\x00') - - tfile.write(data[3186:]) - tfile.flush() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(tfile.name) - regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ - Invalid\svalues\sfor\scomp\s=\s0\s+ - :\sdx=1\sdy=0''', re.VERBOSE) - if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) - else: - with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) - - def test_xmp_attribute(self): - """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#}' - ns1 = '{http://ns.adobe.com/xap/1.0/}' - name = '{0}RDF/{0}Description'.format(ns0) - elt = xmp.find(name) - attr_value = elt.attrib['{0}CreatorTool'.format(ns1)] - self.assertEqual(attr_value, 'glymur') - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - def test_unrecognized_exif_tag(self): - """An unrecognized exif tag should be handled gracefully.""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - shutil.copyfile(self.jp2file, tfile.name) - - # The Exif UUID starts at byte 77. There are 8 bytes for the L and - # T fields, then 16 bytes for the UUID identifier, then 6 exif - # header bytes, then 8 bytes for the TIFF header, then 2 bytes - # 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 fptr: - fptr.seek(117) - 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) - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - jp2k = Jp2k(tfile.name) - - self.assertEqual(jp2k.box[5].box_id, 'jp2c') - self.assertEqual(jp2k.box[5].offset, 3127) - self.assertEqual(jp2k.box[5].length, 1133427 + 8) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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. - baseline_jp2 = Jp2k(self.jp2file) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - with open(self.jp2file, 'rb') as ifile: - # Everything up until the jp2c box. - write_buffer = ifile.read(588458) - tfile.write(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) - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - new_jp2 = Jp2k(tfile.name) - - # The top level boxes in each file should match. - for j in range(len(baseline_jp2.box)): - self.assertEqual(new_jp2.box[j].box_id, - baseline_jp2.box[j].box_id) - self.assertEqual(new_jp2.box[j].offset, - baseline_jp2.box[j].offset) - self.assertEqual(new_jp2.box[j].length, - baseline_jp2.box[j].length) - - def test_basic_jp2(self): - """This test is only useful when openjp2 is not available - and OPJ_DATA_ROOT is not set. We need at least one - working JP2 test. - """ - j2k = Jp2k(self.jp2file) - j2k.read(rlevel=1) - def test_basic_j2k(self): """This test is only useful when openjp2 is not available and OPJ_DATA_ROOT is not set. We need at least one @@ -1051,154 +966,6 @@ class TestJp2k15(unittest.TestCase): j = Jp2k(self.j2kfile) self.assertEqual(j.box, []) - @unittest.skip("Writing requires openjp2 library at the moment.") - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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') - - # The code block dimensions are given as rows x columns. - j.write(data, cbsize=(16, 32)) - - codestream = j.get_codestream() - - # Code block size is reported as XY in the codestream. - self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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): - 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_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): - 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.""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - data = np.zeros((128, 128, 2), dtype=np.uint8) - j.write(data, colorspace='rgb') - - @unittest.skip("Writing requires openjp2 library at the moment.") - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - def test_colorspace_with_j2k(self): - """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): - data = np.zeros((128, 128, 3), dtype=np.uint8) - j.write(data, colorspace='rgb') - - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - j.write(data, colorspace='rgb') - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - j.write(data, colorspace='grey') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 2) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 3) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 4) - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @unittest.skip("Writing requires openjp2 library at the moment.") - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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: - j = Jp2k(tfile.name, 'wb') - data = np.zeros((128, 128, 4), dtype=np.uint8) - j.write(data) - - @unittest.skip("Writing requires openjp2 library at the moment.") - def test_specify_ycc(self): - """Should reject YCC""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - 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""" @@ -1289,92 +1056,6 @@ class TestJp2k15(unittest.TestCase): self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), b'this is a test') - @unittest.skip("Writing requires openjp2 library at the moment.") - @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) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) - - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - - # Offset of the codestream is where we start. - 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'. - write_buffer = struct.pack('>I4s', int(56), b'asoc') - tfile2.write(write_buffer) - - # Write the contained label box - 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 '. - write_buffer = struct.pack('>I4s', int(35), b'xml ') - tfile2.write(write_buffer) - - write_buffer = 'this is a test' - write_buffer = write_buffer.encode() - tfile2.write(write_buffer) - - # Now append the codestream. - tfile2.write(codestream) - tfile2.flush() - - jasoc = Jp2k(tfile2.name) - self.assertEqual(jasoc.box[3].box_id, 'asoc') - self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') - self.assertEqual(jasoc.box[3].box[0].label, 'label') - self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(re.match(r"""1\.[345]\.\d""", - OPENJPEG_VERSION) is not None, - "Segfault on official v1.x series.") - def test_openjpeg_library_message(self): - """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 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. - tfile.write(data[0:3179]) - - # Make the DY bytes of the SIZ segment zero. That means that - # a subsampling factor is zero, which is illegal. - tfile.write(b'\x00') - tfile.write(data[3180:3182]) - tfile.write(b'\x00') - tfile.write(data[3184:3186]) - tfile.write(b'\x00') - - tfile.write(data[3186:]) - tfile.flush() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(tfile.name) - regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ - Invalid\svalues\sfor\scomp\s=\s0\s+ - :\sdx=1\sdy=0''', re.VERBOSE) - if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) - else: - with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) - def test_xmp_attribute(self): """Verify the XMP packet in the shipping example file can be read.""" j = Jp2k(self.jp2file) From ed1ca36040a14d37eb80a0e4d30a57561c933b85 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 9 Sep 2013 21:09:33 -0400 Subject: [PATCH 064/122] Added preliminary 1.5.1 write routine. --- glymur/jp2k.py | 213 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 6 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index bd90dfe..154db4f 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -280,9 +280,6 @@ class Jp2k(Jp2kBox): Corresponds to cparameters_t type in openjp2 headers. colorspace : int Either CLRSPC_SRGB or CLRSPC_GRAY - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. """ if 'cratios' in kwargs and 'psnr' in kwargs: @@ -380,11 +377,215 @@ class Jp2k(Jp2kBox): glymur.LibraryNotFoundError If glymur is unable to load the openjp2 library. """ - if opj2.OPENJP2 is None: - raise LibraryNotFoundError("You must have the openjp2 library " - "installed before using this " + if opj2.OPENJP2 is not None: + img = self._write_openjp2(img_array, verbose=verbose, **kwargs) + elif opj.OPENJPEG is not None: + img = self._write_openjpeg(img_array, verbose=verbose, **kwargs) + else: + raise LibraryNotFoundError("You must have version 1.5 of OpenJPEG " + "or more recent before using this " "functionality.") + def _write_openjpeg(self, img_array, verbose=False, **kwargs): + """ + """ + if codeblock is not None: + if (np.prod(codeblock) > 4096) or (np.any(np.array(codeblock) < 4)) or (np.any(np.array(codeblock) > 1024)): + msg = 'Size of code block error. ' + msg += 'Restriction: width*height <= 4096, ' + msg += '4 <= width, height <= 1024' + raise(RuntimeError(msg)) + + if cratio is not None and len(cratio) >= opj.MAX_NUM_LAYERS: + msg = 'Maximum number of layers is %d.' % opj.MAX_NUM_LAYERS + raise(RuntimeError(msg)) + + if psnr is not None and len(psnr) >= opj.MAX_NUM_LAYERS: + msg = 'Maximum number of layers is %d.' % opj.MAX_NUM_LAYERS + raise(RuntimeError(msg)) + + if cratio is not None and psnr is not None: + msg = 'Psnr and cratio parameters cannot be specified together.' + raise(RuntimeError(msg)) + + + cparams = opj.cparameters_t() + + opj.set_default_encoder_parameters(ctypes.byref(cparams)) + + # Set default to lossless until we know otherwise. + cparams.tcp_rates[0] = 0 + cparams.tcp_numlayers = 1 + cparams.cp_disto_alloc = 1 + + outfile = self.jp2k_file + nelts = opj.OPJ_PATH_LEN - len(outfile) + outfile += b'0'*nelts + cparams.outfile = outfile + + numrows = data.shape[0] + numcols = data.shape[1] + numlayers = data.shape[2] + + if codeblock is not None: + cparams.cblockw_init = codeblock[0] + cparams.cblockh_init = codeblock[1] + + if comment is None: + comment = 'Created by OpenJPEG version %s' % opj.version() + cparams.cp_comment = ctypes.c_char_p(comment) + + + if cratio is not None: + cparams.tcp_numlayers = len(cratio) + for j in range(0,len(cratio)): + cparams.tcp_rates[j] = cratio[j] + cparams.cp_disto_alloc = 1 + + if eph: + cparams.csty = cparams.csty | 0x04 + + if modeswitch is not None: + cparams.mode = modeswitch + + if numres is not None: + cparams.numresolution = numres + + if origin is not None: + cparams.image_offset_x0 = origin[0] + cparams.image_offset_y0 = origin[1] + + if progorder is not None: + cparams.prog_order = opj.progression_order[progorder] + + if precinct is not None: + cparams.csty = cparams.csty | 0x01 + cparams.res_spec = len(precinct) + for j in range(0,len(precinct)): + cparams.prcw_init[j] = precinct[j][0] + cparams.prch_init[j] = precinct[j][1] + + if psnr is not None: + cparams.tcp_numlayers = len(psnr) + for j in range(0,len(psnr)): + cparams.tcp_distoratio[j] = psnr[j] + cparams.cp_fixed_quality = 1 + + if sop: + cparams.csty = cparams.csty | 0x02 + + if tile is not None: + cparams.tile_size_on = 1 + cparams.cp_tdx = tile[0] + cparams.cp_tdy = tile[1] + + # comment = what? + cmptparms = opj.image_cmptparm_t_from_np(data) + image = opj.image_create(cmptparms) + + # set image offset and reference grid + image.contents.x0 = cparams.image_offset_x0 + image.contents.y0 = cparams.image_offset_y0 + image.contents.x1 = image.contents.x0 + (numcols - 1) * cparams.subsampling_dx + 1 + image.contents.y1 = image.contents.y0 + (numrows - 1) * cparams.subsampling_dy + 1 + + # Stage the image data to the openjpeg data structure. + for k in range(0,numlayers): + layer = np.ascontiguousarray(data[:,:,k], dtype=np.int32) + dest = image.contents.comps[k].data + src = layer.ctypes.data + ctypes.memmove(dest, src, layer.nbytes) + + # set multi-component transform? + if image.contents.numcomps == 3: + cparams.tcp_mct = chr(1) + else: + cparams.tcp_mct = chr(0) + + # set encode format + #cinfo = opj.create_compress(opj.codec_format[self.file_format]) + cinfo = opj.create_compress(self.file_format) + + event_mgr = opj.event_mgr_t(None, None, None) + opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None) + + opj.setup_encoder(cinfo, ctypes.byref(cparams), image) + + # open a byte stream for writing + # allocate memory for all tiles + cio = opj.cio_open(cinfo) + + opj.encode(cinfo, cio, image) + pos = opj.cio_tell(cio) + + ss = ctypes.string_at(cio.contents.buffer, pos) + f = open(self.jp2k_file,'wb') + f.write(ss) + f.close() + opj.cio_close(cio); + + opj.destroy_compress(cinfo); + opj.image_destroy(image); + + self.parse() + + + def _write_openjp2(self, img_array, verbose=False, **kwargs): + """Write image data to a JP2/JPX/J2k file. Intended usage of the + various parameters follows that of OpenJPEG's opj_compress utility. + + This method can only be used to create JPEG 2000 images that can fit + in memory. + + Parameters + ---------- + img_array : ndarray + Image data to be written to file. + cbsize : tuple, optional + Code block size (DY, DX). + colorspace : str, optional + Either 'rgb' or 'gray'. + cratios : iterable + Compression ratios for successive layers. + eph : bool, optional + If true, write SOP marker after each header packet. + grid_offset : tuple, optional + Offset (DY, DX) of the origin of the image in the reference grid. + mct : bool, optional + Specifies usage of the multi component transform. If not + specified, defaults to True if the colorspace is RGB. + modesw : int, optional + Mode switch. + 1 = BYPASS(LAZY) + 2 = RESET + 4 = RESTART(TERMALL) + 8 = VSC + 16 = ERTERM(SEGTERM) + 32 = SEGMARK(SEGSYM) + numres : int, optional + Number of resolutions. + prog : str, optional + Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". + psnr : iterable, optional + Different PSNR for successive layers. + psizes : list, optional + List of precinct sizes. Each precinct size tuple is defined in + (height x width). + sop : bool, optional + If true, write SOP marker before each packet. + subsam : tuple, optional + Subsampling factors (dy, dx). + tilesize : tuple, optional + Numeric tuple specifying tile size in terms of (numrows, numcols), + not (X, Y). + verbose : bool, optional + Print informational messages produced by the OpenJPEG library. + + Raises + ------ + glymur.LibraryNotFoundError + If glymur is unable to load the openjp2 library. + """ cparams, colorspace = self._process_write_inputs(img_array, **kwargs) if img_array.ndim == 2: From d070cc414464ad6ff1c0894e3a936f5afec49b13 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 10 Sep 2013 20:11:32 -0400 Subject: [PATCH 065/122] Filled in more of openjpeg write definitions. #111 --- glymur/jp2k.py | 4 +- glymur/lib/openjpeg.py | 426 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 419 insertions(+), 11 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 154db4f..bb2fe43 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -409,7 +409,7 @@ class Jp2k(Jp2kBox): raise(RuntimeError(msg)) - cparams = opj.cparameters_t() + cparams = opj.CompressionParametersType() opj.set_default_encoder_parameters(ctypes.byref(cparams)) @@ -506,7 +506,7 @@ class Jp2k(Jp2kBox): #cinfo = opj.create_compress(opj.codec_format[self.file_format]) cinfo = opj.create_compress(self.file_format) - event_mgr = opj.event_mgr_t(None, None, None) + event_mgr = opj.EventMgrType(None, None, None) opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None) opj.setup_encoder(cinfo, ctypes.byref(cparams), image) diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 704cf9c..6e7b858 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -6,10 +6,16 @@ import ctypes import sys +import numpy as np + from .config import glymur_config _, OPENJPEG = glymur_config() -PATH_LEN = 4096 # maximum allowed size for filenames +# Maximum number of tile parts expected by JPWL: increase at your will +JPWL_MAX_NO_TILESPECS = 16 + +J2K_MAXRLVLS = 33 # Number of maximum resolution level authorized +PATH_LEN = 4096 # maximum allowed size for filenames def version(): @@ -52,14 +58,8 @@ class CommonStructType(ctypes.Structure): ("mj2_handle", ctypes.c_void_p)] -class DecompressionInfoType(ctypes.Structure): - """This is for decompression contexts. - - Corresponds to dinfo_t type in openjpeg headers. - """ - pass - - +STREAM_READ = 0x0001 # The stream was opened for reading. +STREAM_WRITE = 0x0002 # The stream was opened for writing. class CioType(ctypes.Structure): """Byte input-output stream (CIO) @@ -80,6 +80,266 @@ class CioType(ctypes.Structure): ("bp", ctypes.c_char_p)] +class CompressionInfoType(CommonStructType): + """Common fields between JPEG-2000 compression and decompression contexts. + This is for compression contexts. Corresponds to common_struct_t. + """ + pass + + +class PocType(ctypes.Structure): + """Progression order changes.""" + _fields_ = [("resno", ctypes.c_int), + # Resolution num start, Component num start, given by POC + ("compno0", ctypes.c_int), + + # Layer num end,Resolution num end, Component num end, given by POC + ("layno1", ctypes.c_int), + ("resno1", ctypes.c_int), + ("compno1", ctypes.c_int), + + # Layer num start,Precinct num start, Precinct num end + ("layno0", ctypes.c_int), + ("precno0", ctypes.c_int), + ("precno1", ctypes.c_int), + + # Progression order enum + # OPJ_PROG_ORDER prg1,prg; + ("prg1", ctypes.c_int), + ("prg", ctypes.c_int), + + # Progression order string + # char progorder[5]; + ("progorder", ctypes.c_char * 5), + + # Tile number + # int tile; + ("tile", ctypes.c_int), + + # /** Start and end values for Tile width and height*/ + # int tx0,tx1,ty0,ty1; + ("tx0", ctypes.c_int), + ("tx1", ctypes.c_int), + ("ty0", ctypes.c_int), + ("ty1", ctypes.c_int), + + # /** Start value, initialised in pi_initialise_encode*/ + # int layS, resS, compS, prcS; + ("layS", ctypes.c_int), + ("resS", ctypes.c_int), + ("compS", ctypes.c_int), + ("prcS", ctypes.c_int), + + # /** End value, initialised in pi_initialise_encode */ + # int layE, resE, compE, prcE; + ("layE", ctypes.c_int), + ("resE", ctypes.c_int), + ("compE", ctypes.c_int), + ("prcE", ctypes.c_int), + + # Start and end values of Tile width and height, initialised in + # pi_initialise_encode int txS,txE,tyS,tyE,dx,dy; + ("txS", ctypes.c_int), + ("txE", ctypes.c_int), + ("tyS", ctypes.c_int), + ("tyE", ctypes.c_int), + ("dx", ctypes.c_int), + ("dy", ctypes.c_int), + + # Temporary values for Tile parts, initialised in pi_create_encode + # int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t; + ("lay_t", ctypes.c_int), + ("res_t", ctypes.c_int), + ("comp_t", ctypes.c_int), + ("prc_t", ctypes.c_int), + ("tx0_t", ctypes.c_int), + ("ty0_t", ctypes.c_int)] + + +class CompressionParametersType(ctypes.Structure): + """Compression parameters. + + Corresponds to cparameters_t type in openjp2 headers. + """ + _fields_ = [ + # size of tile: + # tile_size_on = false (not in argument) or + # = true (in argument) + ("tile_size_on", ctypes.c_int), + + # XTOsiz, YTOsiz + ("cp_tx0", ctypes.c_int), + ("cp_ty0", ctypes.c_int), + + # XTsiz, YTsiz + ("cp_tdx", ctypes.c_int), + ("cp_tdy", ctypes.c_int), + + # allocation by rate/distortion + ("cp_disto_alloc", ctypes.c_int), + + # allocation by fixed layer + ("cp_fixed_alloc", ctypes.c_int), + + # add fixed_quality + ("cp_fixed_quality", ctypes.c_int), + + # fixed layer + ("cp_matrice", ctypes.c_void_p), + + # comment for coding + ("cp_comment", ctypes.c_char_p), + + # csty : coding style + ("csty", ctypes.c_int), + + # progression order (default OPJ_LRCP) + ("prog_order", ctypes.c_int), + + # progression order changes + ("poc", PocType * 32), + + # number of progression order changes (POC), default to 0 + ("numpocs", ctypes.c_uint), + + # number of layers + ("tcp_numlayers", ctypes.c_int), + + # rates of layers + ("tcp_rates", ctypes.c_float * 100), + + # different psnr for successive layers + ("tcp_distoratio", ctypes.c_float * 100), + + # number of resolutions + ("numresolution", ctypes.c_int), + + # initial code block width, default to 64 + ("cblockw_init", ctypes.c_int), + + # initial code block height, default to 64 + ("cblockh_init", ctypes.c_int), + + # mode switch (cblk_style) + ("mode", ctypes.c_int), + + # 1 : use the irreversible DWT 9-7 + # 0 : use lossless compression (default) + ("irreversible", ctypes.c_int), + + # region of interest: affected component in [0..3], -1 means no ROI + ("roi_compno", ctypes.c_int), + + # region of interest: upshift value + ("roi_shift", ctypes.c_int), + + # number of precinct size specifications + ("res_spec", ctypes.c_int), + + # initial precinct width + ("prcw_init", ctypes.c_int * J2K_MAXRLVLS), + + # initial precinct height + ("prch_init", ctypes.c_int * J2K_MAXRLVLS), + + # input file name + ("infile", ctypes.c_char * PATH_LEN), + + # output file name + ("outfile", ctypes.c_char * PATH_LEN), + + # DEPRECATED. + ("index_on", ctypes.c_int), + + # DEPRECATED. + ("index", ctypes.c_char * PATH_LEN), + + # subimage encoding: origin image offset in x direction + # subimage encoding: origin image offset in y direction + ("image_offset_x0", ctypes.c_int), + ("image_offset_y0", ctypes.c_int), + + # subsampling value for dx + # subsampling value for dy + ("subsampling_dx", ctypes.c_int), + ("subsampling_dy", ctypes.c_int), + + # input file format 0: PGX, 1: PxM, 2: BMP 3:TIF + # output file format 0: J2K, 1: JP2, 2: JPT + ("decod_format", ctypes.c_int), + ("cod_format", ctypes.c_int), + + # JPWL encoding parameters + # enables writing of EPC in MH, thus activating JPWL + ("jpwl_epc_on", ctypes.c_int), + + # error protection method for MH (0,1,16,32,37-128) + ("jpwl_hprot_mh", ctypes.c_int), + + # tile number of header protection specification (>=0) + ("jpwl_hprot_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # error protection methods for TPHs (0,1,16,32,37-128) + ("jpwl_hprot_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # tile number of packet protection specification (>=0) + ("jpwl_pprot_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # packet number of packet protection specification (>=0) + ("jpwl_pprot_packno", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # error protection methods for packets (0,1,16,32,37-128) + ("jpwl_pprot", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # enables writing of ESD, (0=no/1/2 bytes) + ("jpwl_sens_size", ctypes.c_int), + + # sensitivity addressing size (0=auto/2/4 bytes) + ("jpwl_sens_addr", ctypes.c_int), + + # sensitivity range (0-3) + ("jpwl_sens_range", ctypes.c_int), + + # sensitivity method for MH (-1=no,0-7) + ("jpwl_sens_mh", ctypes.c_int), + + # tile number of sensitivity specification (>=0) + ("jpwl_sens_tph_tileno", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # sensitivity methods for TPHs (-1=no,0-7) + ("jpwl_sens_tph", ctypes.c_int * JPWL_MAX_NO_TILESPECS), + + # Digital Cinema compliance 0-not compliant, 1-compliant + ("cp_cinema", ctypes.c_int), + + # Maximum rate for each component. + # If == 0, component size limitation is not considered + ("max_comp_size", ctypes.c_int), + + # Profile name + ("cp_rsiz", ctypes.c_int), + + # Tile part generation + ("tp_on", ctypes.c_uint8), + + # Flag for Tile part generation + ("tp_flag", ctypes.c_uint8), + + # MCT (multiple component transform) + ("tcp_mct", ctypes.c_uint8), + + # Enable JPIP indexing + ("jpip_on", ctypes.c_int)] + + +class DecompressionInfoType(ctypes.Structure): + """This is for decompression contexts. + + Corresponds to dinfo_t type in openjpeg headers. + """ + pass + + class DecompressionParametersType(ctypes.Structure): """Decompression parameters. @@ -111,6 +371,37 @@ class DecompressionParametersType(ctypes.Structure): _fields_.append(("flags", ctypes.c_uint)) +class ImageCmptparmType(ctypes.Structure): + """Component parameters structure used by the opj_image_create function. + """ + _fields_ = [ + # XRsiz: horizontal separation of a sample of ith component with + # respect to the reference grid + ("dx", ctypes.c_int), + + # YRsiz: vertical separation of a sample of ith component with + # respect to the reference grid */ + ("dy", ctypes.c_int), + + # data width, height + ("w", ctypes.c_int), + ("h", ctypes.c_int), + + # x component offset compared to the whole image + # y component offset compared to the whole image + ("x0", ctypes.c_int), + ("y0", ctypes.c_int), + + # precision + ('prec', ctypes.c_int), + + # imgae depth in bits + ('bpp', ctypes.c_int), + + # signed (1) / unsigned (0) + ('sgnd', ctypes.c_int)] + + class ImageCompType(ctypes.Structure): """Defines a single image component. @@ -166,6 +457,17 @@ def cio_close(cio): OPENJPEG.opj_cio_close(cio) +def create_compress(fmt): + """Wrapper for openjpeg library function opj_create_compress. + + Creates a J2K/JPT/JP2 compression structure. + """ + OPENJPEG.opj_create_compress.argtypes = [ctypes.c_int] + OPENJPEG.opj_create_compress.restype = ctypes.POINTER(CompressionInfoType) + cinfo = OPENJPEG.opj_create_compress(fmt) + return cinfo + + def create_decompress(fmt): """Wraps openjpeg library function opj_create_decompress. """ @@ -186,6 +488,39 @@ def decode(dinfo, cio): return image +def destroy_compress(cinfo): + """Wrapper for openjpeg library function opj_destroy_compress. + + Release resources for a compressor handle. + """ + argtypes = [ctypes.POINTER(CompressionInfoType)] + OPENJPEG.opj_destroy_compress.argtypes = argtypes + OPENJPEG.opj_destroy_compress(cinfo) + + +def encode(cinfo, cio, image): + """Wrapper for openjpeg library function opj_encode. + + Encodes an image into a JPEG-2000 codestream. + + Parameters + ---------- + cinfo : compression handle + + cio : output buffer stream + + image : image to encode + """ + argtypes = [ctypes.POINTER(CompressionInfoType), + ctypes.POINTER(CioType), + ctypes.POINTER(ImageType)] + OPENJPEG.opj_encode.argtypes = argtypes + OPENJPEG.opj_encode.restype = ctypes.c_int + status = OPENJPEG.opj_encode(cinfo, cio, image) + if not status: + raise RuntimeError("opj_encode failed") + + def destroy_decompress(dinfo): """Wraps openjpeg library function opj_destroy_decompress.""" argtypes = [ctypes.POINTER(DecompressionInfoType)] @@ -193,12 +528,76 @@ def destroy_decompress(dinfo): OPENJPEG.opj_destroy_decompress(dinfo) +def image_cmptparm_t_from_np(np_image): + """Return appropriate image_cmptparm_t based on given numpy array. + """ + try: + num_comps = np_image.shape[2] + except IndexError: + num_comps = 1 + + cmpt_parm_array_t = ImageCmptparmType * num_comps + tarr = cmpt_parm_array_t() + + if np_image.dtype == np.uint8: + prec = 8 + bpp = 8 + sgnd = 0 + elif np_image.dtype == np.int8: + prec = 8 + bpp = 8 + sgnd = 1 + elif np_image.dtype == np.uint16: + prec = 16 + bpp = 16 + sgnd = 0 + elif np_image.dtype == np.int16: + prec = 16 + bpp = 16 + sgnd = 1 + else: + raise(TypeError("unhandled")) + + for j in range(0, num_comps): + tarr[j].dx = 1 + tarr[j].dy = 1 + tarr[j].w = np_image.shape[1] + tarr[j].h = np_image.shape[0] + tarr[j].x0 = 0 + tarr[j].y0 = 0 + tarr[j].prec = prec + tarr[j].bpp = bpp + tarr[j].sgnd = sgnd + + return(tarr) + + +def image_create(cmptparms, cspace): + """Wrapper for openjpeg library function opj_image_create. + """ + OPENJPEG.opj_image_create.argtypes = [ctypes.c_int, + ctypes.POINTER(ImageCmptparmType), + ctypes.c_int] + OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType) + + image = OPENJPEG.opj_image_create(len(cmptparms), cmptparms, cspace) + return(image) + + def image_destroy(image): """Wraps openjpeg library function opj_image_destroy.""" OPENJPEG.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)] OPENJPEG.opj_image_destroy(image) +def set_default_encoder_parameters(cparams_p): + """Wrapper for openjpeg library function opj_set_default_encoder_parameters. + """ + argtypes = [ctypes.POINTER(CompressionParametersType)] + OPENJPEG.opj_set_default_encoder_parameters.argtypes = argtypes + OPENJPEG.opj_set_default_encoder_parameters(cparams_p) + + def set_default_decoder_parameters(dparams_p): """Wrapper for opj_set_default_decoder_parameters. """ @@ -219,6 +618,15 @@ def set_event_mgr(dinfo, event_mgr, context=None): event_mgr, context) +def setup_encoder(cinfo, cparameters, image): + """Wrapper for openjpeg library function opj_setup_decoder.""" + argtypes = [ctypes.POINTER(CompressionInfoType), + ctypes.POINTER(CompressionParametersType), + ctypes.POINTER(ImageType)] + OPENJPEG.opj_setup_encoder.argtypes = argtypes + OPENJPEG.opj_setup_encoder(cinfo, cparameters, image) + + def setup_decoder(dinfo, dparams): """Wrapper for openjpeg library function opj_setup_decoder.""" argtypes = [ctypes.POINTER(DecompressionInfoType), From 516d3ca55b8f2f29ed6551211c13d5c9e9380928 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 11 Sep 2013 06:43:36 -0400 Subject: [PATCH 066/122] Don't bother trying to write with versions below 1.5. #111 --- glymur/test/test_jp2k.py | 3 +++ glymur/test/test_opj_suite_write.py | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index edefb7f..8e4a74c 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -679,6 +679,9 @@ class TestJp2k15(unittest.TestCase): j2k.read(layer=1) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + @unittest.skipIf(re.match(r"""1\.[01234]\.\d""", + OPENJPEG_VERSION) is not None, + "Writing only supported with openjpeg version 1.5+.") def test_2d_rgb(self): """RGB must have at least 3 components.""" with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index 479cb1f..e187d34 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -10,6 +10,7 @@ suite. # pylint: disable=F0401 import os +import re import sys import tempfile @@ -19,15 +20,16 @@ else: import unittest from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG -from .fixtures import OPJ_DATA_ROOT, opj_data_file +from .fixtures import OPJ_DATA_ROOT, OPENJPEG_VERSION, opj_data_file from glymur import Jp2k import glymur @unittest.skipIf(os.name == "nt", "no write support on windows, period") -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") +@unittest.skipIf(re.match(r"""1\.[01234]\.\d""", + OPENJPEG_VERSION) is not None, + "Writing only supported with openjpeg version 1.5+.") @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") From 5626f3f460f990bdf6347b2f5dc3ba2ca192683d Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 11 Sep 2013 20:29:47 -0400 Subject: [PATCH 067/122] Updated for OpenSUSE 12.3. Simplified the Fedora explanations. #111 --- docs/source/detailed_installation.rst | 56 +++++++++------------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index dab4c3f..879d2a1 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -80,60 +80,42 @@ MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0. Linux ----- +For the most part, you only need python and numpy to run glymur. In order to +run as many tests as possible, however, the following Python packages may also +need to be installed. + + * setuptools + * matplotlib + * pillow + * contextlib2 (python 2.7 only) + * mock (python 2.7 only) + +OpenSUSE 12.3 +''''''''''''' +Ships with Python 3.3 and 2.7. You should use pip to install Pillow. Fedora 19 ''''''''' -Fedora 18 ships with Python 3.3 and all the necessary RPMs are available to -run the maximum number of tests. - - * python3 - * python3-numpy - * python3-setuptools - * python3-matplotlib (for running tests) - * python3-matplotlib-tk (or whichever matplotlib backend you prefer) - * python3-pillow (for running tests) +Ships with Python 3.3 and 2.7. All packages available as RPMs. Fedora 18 ''''''''' -Fedora 18 ships with Python 3.3 and the following RPMs are available to -meet the minimal set of requirements for running glymur. - - * python3 - * python3-numpy - * python3-setuptools - -For running the maximal number of tests, you also need - - * python3-matplotlib - * python3-matplotlib-tk (or whichever matplotlib backend you prefer) - -Pillow is also needed in order to run the maximum number of tests, so -go ahead and install Pillow via pip since Pillow is not available -in Fedora 18 default repositories:: +Fedora 18 ships with Python 3.3 and 2.7. Most packages are available as +standard RPMS, but you should use pip to install Pillow as it is not available +in the Fedora 18 default repositories:: $ yum install python3-devel # pip needs this in order to compile Pillow $ yum install python3-pip $ pip-python3 install Pillow --user - $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH Fedora 17 ''''''''' -Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You should have the -following RPMs installed. - - * python - * python-mock - * python-pip - * python-setuptools - * numpy - * matplotlib (optional) - -In addition, you must install contextlib2 and Pillow via pip. :: +Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You must install contextlib2 +and Pillow via pip. :: $ yum install python-devel # pip needs this in order to compile Pillow $ pip-python install Pillow --user $ pip-python install contextlib2 --user - $ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH Windows ------- From 5b401e1e2da5cb4aff6fdd39ef1af381525da152 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 11 Sep 2013 20:30:54 -0400 Subject: [PATCH 068/122] Writing works with 1.5, two failures with 3.3. #111 --- glymur/jp2k.py | 133 +++++++++-------------------------------- glymur/lib/openjpeg.py | 58 +++++++++++------- 2 files changed, 64 insertions(+), 127 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index bb2fe43..413179b 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -15,14 +15,14 @@ else: import ctypes import math import os +import re import struct import warnings import numpy as np from .codestream import Codestream -from .core import SRGB -from .core import GREYSCALE +from .core import SRGB, GREYSCALE from .core import PROGRESSION_ORDER from .core import ENUMERATED_COLORSPACE, RESTRICTED_ICC_PROFILE from .jp2box import Jp2kBox @@ -33,6 +33,13 @@ from .lib import openjpeg as opj from .lib import openjp2 as opj2 from .lib import c as libc +if opj.OPENJPEG is None and opj2.OPENJP2 is None: + OPENJPEG_VERSION = '0.0.0' +elif opj2.OPENJP2 is None: + OPENJPEG_VERSION = opj.version() +else: + OPENJPEG_VERSION = opj2.version() + class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -185,7 +192,10 @@ class Jp2k(Jp2kBox): cparams : CompressionParametersType(ctypes.Structure) Corresponds to cparameters_t type in openjp2 headers. """ - cparams = opj2.set_default_encoder_parameters() + if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION): + cparams = opj.set_default_encoder_parameters() + else: + cparams = opj2.set_default_encoder_parameters() outfile = self.filename.encode() num_pad_bytes = opj2.PATH_LEN - len(outfile) @@ -389,99 +399,18 @@ class Jp2k(Jp2kBox): def _write_openjpeg(self, img_array, verbose=False, **kwargs): """ """ - if codeblock is not None: - if (np.prod(codeblock) > 4096) or (np.any(np.array(codeblock) < 4)) or (np.any(np.array(codeblock) > 1024)): - msg = 'Size of code block error. ' - msg += 'Restriction: width*height <= 4096, ' - msg += '4 <= width, height <= 1024' - raise(RuntimeError(msg)) + cparams, colorspace = self._process_write_inputs(img_array, **kwargs) - if cratio is not None and len(cratio) >= opj.MAX_NUM_LAYERS: - msg = 'Maximum number of layers is %d.' % opj.MAX_NUM_LAYERS - raise(RuntimeError(msg)) + if img_array.ndim == 2: + # Force the image to be 3D. Just makes things easier later on. + numrows, numcols = img_array.shape + img_array = img_array.reshape(numrows, numcols, 1) - if psnr is not None and len(psnr) >= opj.MAX_NUM_LAYERS: - msg = 'Maximum number of layers is %d.' % opj.MAX_NUM_LAYERS - raise(RuntimeError(msg)) + comptparms = _populate_comptparms(img_array, cparams) - if cratio is not None and psnr is not None: - msg = 'Psnr and cratio parameters cannot be specified together.' - raise(RuntimeError(msg)) + image = opj.image_create(comptparms, colorspace) - - cparams = opj.CompressionParametersType() - - opj.set_default_encoder_parameters(ctypes.byref(cparams)) - - # Set default to lossless until we know otherwise. - cparams.tcp_rates[0] = 0 - cparams.tcp_numlayers = 1 - cparams.cp_disto_alloc = 1 - - outfile = self.jp2k_file - nelts = opj.OPJ_PATH_LEN - len(outfile) - outfile += b'0'*nelts - cparams.outfile = outfile - - numrows = data.shape[0] - numcols = data.shape[1] - numlayers = data.shape[2] - - if codeblock is not None: - cparams.cblockw_init = codeblock[0] - cparams.cblockh_init = codeblock[1] - - if comment is None: - comment = 'Created by OpenJPEG version %s' % opj.version() - cparams.cp_comment = ctypes.c_char_p(comment) - - - if cratio is not None: - cparams.tcp_numlayers = len(cratio) - for j in range(0,len(cratio)): - cparams.tcp_rates[j] = cratio[j] - cparams.cp_disto_alloc = 1 - - if eph: - cparams.csty = cparams.csty | 0x04 - - if modeswitch is not None: - cparams.mode = modeswitch - - if numres is not None: - cparams.numresolution = numres - - if origin is not None: - cparams.image_offset_x0 = origin[0] - cparams.image_offset_y0 = origin[1] - - if progorder is not None: - cparams.prog_order = opj.progression_order[progorder] - - if precinct is not None: - cparams.csty = cparams.csty | 0x01 - cparams.res_spec = len(precinct) - for j in range(0,len(precinct)): - cparams.prcw_init[j] = precinct[j][0] - cparams.prch_init[j] = precinct[j][1] - - if psnr is not None: - cparams.tcp_numlayers = len(psnr) - for j in range(0,len(psnr)): - cparams.tcp_distoratio[j] = psnr[j] - cparams.cp_fixed_quality = 1 - - if sop: - cparams.csty = cparams.csty | 0x02 - - if tile is not None: - cparams.tile_size_on = 1 - cparams.cp_tdx = tile[0] - cparams.cp_tdy = tile[1] - - # comment = what? - cmptparms = opj.image_cmptparm_t_from_np(data) - image = opj.image_create(cmptparms) + numrows, numcols, numlayers = img_array.shape # set image offset and reference grid image.contents.x0 = cparams.image_offset_x0 @@ -491,23 +420,16 @@ class Jp2k(Jp2kBox): # Stage the image data to the openjpeg data structure. for k in range(0,numlayers): - layer = np.ascontiguousarray(data[:,:,k], dtype=np.int32) + layer = np.ascontiguousarray(img_array[:,:,k], dtype=np.int32) dest = image.contents.comps[k].data src = layer.ctypes.data ctypes.memmove(dest, src, layer.nbytes) - # set multi-component transform? - if image.contents.numcomps == 3: - cparams.tcp_mct = chr(1) - else: - cparams.tcp_mct = chr(0) - # set encode format - #cinfo = opj.create_compress(opj.codec_format[self.file_format]) - cinfo = opj.create_compress(self.file_format) + cinfo = opj.create_compress(cparams.codec_fmt) event_mgr = opj.EventMgrType(None, None, None) - opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None) + #opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None) opj.setup_encoder(cinfo, ctypes.byref(cparams), image) @@ -519,7 +441,7 @@ class Jp2k(Jp2kBox): pos = opj.cio_tell(cio) ss = ctypes.string_at(cio.contents.buffer, pos) - f = open(self.jp2k_file,'wb') + f = open(self.filename,'wb') f.write(ss) f.close() opj.cio_close(cio); @@ -1408,7 +1330,10 @@ def _populate_comptparms(img_array, cparams): comp_prec = 16 numrows, numcols, num_comps = img_array.shape - comptparms = (opj2.ImageComptParmType * num_comps)() + if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION): + comptparms = (opj.ImageComptParmType * num_comps)() + else: + comptparms = (opj2.ImageComptParmType * num_comps)() for j in range(num_comps): comptparms[j].dx = cparams.subsampling_dx comptparms[j].dy = cparams.subsampling_dy diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 6e7b858..3ea424a 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -371,7 +371,7 @@ class DecompressionParametersType(ctypes.Structure): _fields_.append(("flags", ctypes.c_uint)) -class ImageCmptparmType(ctypes.Structure): +class ImageComptParmType(ctypes.Structure): """Component parameters structure used by the opj_image_create function. """ _fields_ = [ @@ -395,7 +395,7 @@ class ImageCmptparmType(ctypes.Structure): # precision ('prec', ctypes.c_int), - # imgae depth in bits + # image depth in bits ('bpp', ctypes.c_int), # signed (1) / unsigned (0) @@ -403,22 +403,19 @@ class ImageCmptparmType(ctypes.Structure): class ImageCompType(ctypes.Structure): - """Defines a single image component. - - Corresponds to image_comp_t type in openjpeg. - """ - _fields_ = [("dx", ctypes.c_int), - ("dy", ctypes.c_int), - ("w", ctypes.c_int), - ("h", ctypes.c_int), - ("x0", ctypes.c_int), - ("y0", ctypes.c_int), - ("prec", ctypes.c_int), - ("bpp", ctypes.c_int), - ("sgnd", ctypes.c_int), - ("resno_decoded", ctypes.c_int), - ("factor", ctypes.c_int), - ("data", ctypes.POINTER(ctypes.c_int))] + """Defines a single image component. """ + _fields_ = [("dx", ctypes.c_int), + ("dy", ctypes.c_int), + ("w", ctypes.c_int), + ("h", ctypes.c_int), + ("x0", ctypes.c_int), + ("y0", ctypes.c_int), + ("prec", ctypes.c_int), + ("bpp", ctypes.c_int), + ("sgnd", ctypes.c_int), + ("resno_decoded", ctypes.c_int), + ("factor", ctypes.c_int), + ("data", ctypes.POINTER(ctypes.c_int))] class ImageType(ctypes.Structure): @@ -437,16 +434,22 @@ class ImageType(ctypes.Structure): ("icc_profile_len", ctypes.c_int)] -def cio_open(cinfo, src): +def cio_open(cinfo, src=None): """Wrapper for openjpeg library function opj_cio_open.""" argtypes = [ctypes.POINTER(CommonStructType), ctypes.c_char_p, ctypes.c_int] OPENJPEG.opj_cio_open.argtypes = argtypes OPENJPEG.opj_cio_open.restype = ctypes.POINTER(CioType) + if src is None: + length = 0 + else: + length = len(src) + cio = OPENJPEG.opj_cio_open(ctypes.cast(cinfo, ctypes.POINTER(CommonStructType)), - src, len(src)) + src, + length) return cio @@ -457,6 +460,13 @@ def cio_close(cio): OPENJPEG.opj_cio_close(cio) +def cio_tell(cio): + """Get position in byte stream.""" + OPENJPEG.cio_tell.argtypes = [ctypes.POINTER(CioType)] + OPENJPEG.cio_tell.restype = ctypes.c_int + pos = OPENJPEG.cio_tell(cio) + return pos + def create_compress(fmt): """Wrapper for openjpeg library function opj_create_compress. @@ -576,7 +586,7 @@ def image_create(cmptparms, cspace): """Wrapper for openjpeg library function opj_image_create. """ OPENJPEG.opj_image_create.argtypes = [ctypes.c_int, - ctypes.POINTER(ImageCmptparmType), + ctypes.POINTER(ImageComptParmType), ctypes.c_int] OPENJPEG.opj_image_create.restype = ctypes.POINTER(ImageType) @@ -590,12 +600,14 @@ def image_destroy(image): OPENJPEG.opj_image_destroy(image) -def set_default_encoder_parameters(cparams_p): +def set_default_encoder_parameters(): """Wrapper for openjpeg library function opj_set_default_encoder_parameters. """ + cparams = CompressionParametersType() argtypes = [ctypes.POINTER(CompressionParametersType)] OPENJPEG.opj_set_default_encoder_parameters.argtypes = argtypes - OPENJPEG.opj_set_default_encoder_parameters(cparams_p) + OPENJPEG.opj_set_default_encoder_parameters(ctypes.byref(cparams)) + return cparams def set_default_decoder_parameters(dparams_p): From d132a98a80976b7d64289f02aaa32a63d59af0d3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 12 Sep 2013 06:40:13 -0400 Subject: [PATCH 069/122] Updated changelog for 1.5 write support. --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 9a71f81..96b8173 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,5 @@ +Sep 12, 2013 - v0.4.2r Added write support for 1.5.x. + Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1 Aug 18, 2013 - v0.4.0 Added append method. From cc10537c14412c322496cfb22fce3538fc436c70 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 12 Sep 2013 21:07:58 -0400 Subject: [PATCH 070/122] Using existing openjp2 handlers for now. #112 Seems a little greasy, but it works. Probably should think about a separate error handler, though. --- glymur/jp2k.py | 91 +++++++++++++++++++++++------------------- glymur/lib/openjp2.py | 2 +- glymur/lib/openjpeg.py | 3 +- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 413179b..72fc4ff 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -428,8 +428,13 @@ class Jp2k(Jp2kBox): # set encode format cinfo = opj.create_compress(cparams.codec_fmt) - event_mgr = opj.EventMgrType(None, None, None) - #opj.set_event_mgr(cparams, ctypes.byref(event_mgr), None) + event_mgr = opj.EventMgrType() + _info_handler = _INFO_CALLBACK if verbose else None + event_mgr.info_handler = _info_handler + event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, + ctypes.c_void_p) + event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, + ctypes.c_void_p) opj.setup_encoder(cinfo, ctypes.byref(cparams), image) @@ -437,7 +442,9 @@ class Jp2k(Jp2kBox): # allocate memory for all tiles cio = opj.cio_open(cinfo) - opj.encode(cinfo, cio, image) + if not opj.encode(cinfo, cio, image): + raise IOError("Encode error.") + pos = opj.cio_tell(cio) ss = ctypes.string_at(cio.contents.buffer, pos) @@ -773,41 +780,45 @@ class Jp2k(Jp2kBox): raise IOError(msg) with ExitStack() as stack: - # Set decoding parameters. - dparameters = opj.DecompressionParametersType() - opj.set_default_decoder_parameters(ctypes.byref(dparameters)) - dparameters.cp_reduce = rlevel - dparameters.decod_format = self._codec_format + try: + # Set decoding parameters. + dparameters = opj.DecompressionParametersType() + opj.set_default_decoder_parameters(ctypes.byref(dparameters)) + dparameters.cp_reduce = rlevel + dparameters.decod_format = self._codec_format + + infile = self.filename.encode() + nelts = opj.PATH_LEN - len(infile) + infile += b'0' * nelts + dparameters.infile = infile + + dinfo = opj.create_decompress(dparameters.decod_format) + + event_mgr = opj.EventMgrType() + info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) + event_mgr.info_handler = info_handler if verbose else None + event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, + ctypes.c_void_p) + event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, + ctypes.c_void_p) + opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) + + opj.setup_decoder(dinfo, dparameters) + + with open(self.filename, 'rb') as fptr: + src = fptr.read() + cio = opj.cio_open(dinfo, src) + + image = opj.decode(dinfo, cio) + + stack.callback(opj.image_destroy, image) + stack.callback(opj.destroy_decompress, dinfo) + stack.callback(opj.cio_close, cio) + + data = extract_image_cube(image) - infile = self.filename.encode() - nelts = opj.PATH_LEN - len(infile) - infile += b'0' * nelts - dparameters.infile = infile - - dinfo = opj.create_decompress(dparameters.decod_format) - - event_mgr = opj.EventMgrType() - info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) - event_mgr.info_handler = info_handler if verbose else None - event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, - ctypes.c_void_p) - event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, - ctypes.c_void_p) - opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) - - opj.setup_decoder(dinfo, dparameters) - - with open(self.filename, 'rb') as fptr: - src = fptr.read() - cio = opj.cio_open(dinfo, src) - - image = opj.decode(dinfo, cio) - - stack.callback(opj.image_destroy, image) - stack.callback(opj.destroy_decompress, dinfo) - stack.callback(opj.cio_close, cio) - - data = extract_image_cube(image) + except ValueError: + opj2.check_error(0) if data.shape[2] == 1: # The third dimension has just a single layer. Make the image @@ -1465,18 +1476,18 @@ _CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) def _default_error_handler(msg, _): - """Default error handler callback for openjpeg library.""" + """Default error handler callback for libopenjp2.""" msg = "OpenJPEG library error: {0}".format(msg.decode('utf-8').rstrip()) opj2.set_error_message(msg) def _default_info_handler(msg, _): - """Default info handler callback for openjpeg library.""" + """Default info handler callback.""" print("[INFO] {0}".format(msg.decode('utf-8').rstrip())) def _default_warning_handler(library_msg, _): - """Default warning handler callback for openjpeg library.""" + """Default warning handler callback.""" library_msg = library_msg.decode('utf-8').rstrip() msg = "OpenJPEG library warning: {0}".format(library_msg) warnings.warn(msg) diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index f0f72c0..8c0ae32 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -685,7 +685,7 @@ def check_error(status): raise IOError("OpenJPEG function failure.") # These library functions all return an error status. Circumvent that and -# force # them to raise an exception. +# force them to raise an exception. FCNS = ['opj_decode', 'opj_decode_tile_data', 'opj_end_compress', 'opj_encode', 'opj_end_decompress', 'opj_get_decoded_tile', 'opj_read_header', 'opj_read_tile_header', 'opj_set_decode_area', diff --git a/glymur/lib/openjpeg.py b/glymur/lib/openjpeg.py index 3ea424a..5b1183f 100644 --- a/glymur/lib/openjpeg.py +++ b/glymur/lib/openjpeg.py @@ -527,8 +527,7 @@ def encode(cinfo, cio, image): OPENJPEG.opj_encode.argtypes = argtypes OPENJPEG.opj_encode.restype = ctypes.c_int status = OPENJPEG.opj_encode(cinfo, cio, image) - if not status: - raise RuntimeError("opj_encode failed") + return status def destroy_decompress(dinfo): From cc729dd579b828eb05e3f3a1c9e25bc301fa0373 Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 14 Sep 2013 21:46:58 -0400 Subject: [PATCH 071/122] Added version module. Closes #113 --- glymur/__init__.py | 3 ++ glymur/jp2k.py | 22 ++++++------ glymur/test/fixtures.py | 7 ---- glymur/test/test_config.py | 6 ++-- glymur/test/test_jp2k.py | 11 ++---- glymur/test/test_opj_suite.py | 18 ++++++---- glymur/test/test_opj_suite_write.py | 4 +-- glymur/version.py | 53 +++++++++++++++++++++++++++++ setup.py | 3 +- 9 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 glymur/version.py diff --git a/glymur/__init__.py b/glymur/__init__.py index cc80a72..bf2f625 100644 --- a/glymur/__init__.py +++ b/glymur/__init__.py @@ -2,6 +2,9 @@ """ import sys +from glymur import version +__version__ = version.version + from .jp2k import Jp2k from .jp2dump import jp2dump diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 72fc4ff..f3127bc 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -1,4 +1,8 @@ -"""Access to JPEG2000 files. +"""This file is part of glymur, a Python interface for accessing JPEG 2000. + +http://glymur.readthedocs.org + +Copyright 2013 John Evans License: MIT """ @@ -31,15 +35,9 @@ from .jp2box import ColourSpecificationBox, ContiguousCodestreamBox from .jp2box import ImageHeaderBox from .lib import openjpeg as opj from .lib import openjp2 as opj2 +from . import version from .lib import c as libc -if opj.OPENJPEG is None and opj2.OPENJP2 is None: - OPENJPEG_VERSION = '0.0.0' -elif opj2.OPENJP2 is None: - OPENJPEG_VERSION = opj.version() -else: - OPENJPEG_VERSION = opj2.version() - class Jp2k(Jp2kBox): """JPEG 2000 file. @@ -192,7 +190,7 @@ class Jp2k(Jp2kBox): cparams : CompressionParametersType(ctypes.Structure) Corresponds to cparameters_t type in openjp2 headers. """ - if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION): + if version.openjpeg_version_tuple[0] == 1: cparams = opj.set_default_encoder_parameters() else: cparams = opj2.set_default_encoder_parameters() @@ -998,8 +996,8 @@ class Jp2k(Jp2kBox): glymur.LibraryNotFoundError If glymur is unable to load the openjp2 library. """ - if opj2.OPENJP2 is None: - raise LibraryNotFoundError("You must have the development version " + if version.openjpeg_version_tuple[0] < 2: + raise LibraryNotFoundError("You must have at least version 2.0.0" "of OpenJP2 installed before using " "this functionality.") @@ -1341,7 +1339,7 @@ def _populate_comptparms(img_array, cparams): comp_prec = 16 numrows, numcols, num_comps = img_array.shape - if re.match(r"""1\.\d\.\d""", OPENJPEG_VERSION): + if version.openjpeg_version_tuple[0] == 1: comptparms = (opj.ImageComptParmType * num_comps)() else: comptparms = (opj2.ImageComptParmType * num_comps)() diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index 933222a..b872f1d 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -10,13 +10,6 @@ import numpy as np import glymur -# Need to know the version of the openjpeg software. If openjpeg is not -# installed, we use # '0.0.0' -OPENJPEG_VERSION = '0.0.0' -if glymur.lib.openjp2.OPENJP2 is not None: - OPENJPEG_VERSION = glymur.lib.openjp2.version() -elif glymur.lib.openjpeg.OPENJPEG is not None: - OPENJPEG_VERSION = glymur.lib.openjpeg.version() # Need to know of the libopenjp2 version is the official 2.0.0 release and NOT # the 2.0+ development version. diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index af95bd3..16af663 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -117,8 +117,10 @@ class TestConfig(unittest.TestCase): """ with patch('glymur.lib.openjp2.OPENJP2', new=None): with patch('glymur.lib.openjpeg.OPENJPEG', new=None): - with self.assertRaises(glymur.jp2k.LibraryNotFoundError): - glymur.Jp2k(self.jp2file).read_bands() + with patch('glymur.version.openjpeg_version_tuple', + new=(0, 0, 0)): + with self.assertRaises(glymur.jp2k.LibraryNotFoundError): + glymur.Jp2k(self.jp2file).read_bands() @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") def test_write_without_library(self): diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 8e4a74c..bbf551b 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -34,7 +34,6 @@ import glymur from glymur import Jp2k from .fixtures import OPENJP2_IS_V2_OFFICIAL -from .fixtures import OPENJPEG_VERSION from .fixtures import OPJ_DATA_ROOT, opj_data_file @@ -192,7 +191,7 @@ class TestJp2k_2_1(unittest.TestCase): j.read(rlevel=1) -@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, "Not tested for 1.x") class TestJp2k_2_0(unittest.TestCase): """Test suite requiring at least version 2.0""" @@ -679,8 +678,7 @@ class TestJp2k15(unittest.TestCase): j2k.read(layer=1) @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(re.match(r"""1\.[01234]\.\d""", - OPENJPEG_VERSION) is not None, + @unittest.skipIf(glymur.version.openjpeg_version_tuple[1] < 5, "Writing only supported with openjpeg version 1.5+.") def test_2d_rgb(self): """RGB must have at least 3 components.""" @@ -723,8 +721,7 @@ class TestJp2k15(unittest.TestCase): b'this is a test') @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(re.match(r"""1\.[345]\.\d""", - OPENJPEG_VERSION) is not None, + @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, "Segfault on official v1.x series.") def test_openjpeg_library_message(self): """Verify the error message produced by the openjpeg library""" @@ -760,8 +757,6 @@ class TestJp2k15(unittest.TestCase): j.read(rlevel=1) -@unittest.skipIf(re.match(r"""1\.[012]\.\d""", OPENJPEG_VERSION), - "Unsupported version of openjpeg.") class TestJp2k(unittest.TestCase): """Test suite for openjpeg software starting at 1.3""" diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 3c6b5d2..36f0a7b 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -45,7 +45,7 @@ import numpy as np from glymur import Jp2k import glymur -from .fixtures import OPENJPEG_VERSION, OPENJP2_IS_V2_OFFICIAL, OPJ_DATA_ROOT +from .fixtures import OPENJP2_IS_V2_OFFICIAL, OPJ_DATA_ROOT from .fixtures import mse, peak_tolerance, read_pgx, opj_data_file @@ -601,7 +601,7 @@ class TestSuite(unittest.TestCase): jpdata = jp2k.read() self.assertEqual(jpdata.shape, (640, 480, 3)) - @unittest.skipIf(re.match(r"""1\.[0125]\.\d""", OPENJPEG_VERSION), + @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, "Functionality not implemented for 1.x") def test_ETS_JP2_file3(self): jfile = opj_data_file('input/conformance/file3.jp2') @@ -6720,7 +6720,7 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) -@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Feature not supported in glymur until openjpeg 2.0") class TestSuite_bands(unittest.TestCase): """Runs tests introduced in version 1.x but only pass in glymur with 2.0 @@ -6849,7 +6849,7 @@ class TestSuite_bands(unittest.TestCase): self.assertTrue(True) -@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Tests not passing until 2.0") class TestSuite2point0(unittest.TestCase): """Runs tests introduced in version 2.0 or that pass only in 2.0""" @@ -6901,13 +6901,19 @@ class TestSuite2point0(unittest.TestCase): # messages that cannot be turned off? relpath = 'input/nonregression/kakadu_v4-4_openjpegv2_broken.j2k' jfile = opj_data_file(relpath) - Jp2k(jfile).read() + if glymur.version.openjpeg_version_tuple[0] < 2: + with warnings.catch_warnings(): + # Incorrect warning issued about tile parts. + warnings.simplefilter("ignore") + Jp2k(jfile).read() + else: + Jp2k(jfile).read() self.assertTrue(True) @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") -@unittest.skipIf(re.match(r"""1\.\d.\d""", OPENJPEG_VERSION), +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Tests not introduced until 2.1") class TestSuite2point1(unittest.TestCase): """Runs tests introduced in version 2.0+ or that pass only in 2.0+""" diff --git a/glymur/test/test_opj_suite_write.py b/glymur/test/test_opj_suite_write.py index e187d34..2f699e6 100644 --- a/glymur/test/test_opj_suite_write.py +++ b/glymur/test/test_opj_suite_write.py @@ -20,7 +20,7 @@ else: import unittest from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG -from .fixtures import OPJ_DATA_ROOT, OPENJPEG_VERSION, opj_data_file +from .fixtures import OPJ_DATA_ROOT, opj_data_file from glymur import Jp2k import glymur @@ -28,7 +28,7 @@ import glymur @unittest.skipIf(os.name == "nt", "no write support on windows, period") @unittest.skipIf(re.match(r"""1\.[01234]\.\d""", - OPENJPEG_VERSION) is not None, + glymur.version.openjpeg_version) is not None, "Writing only supported with openjpeg version 1.5+.") @unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) @unittest.skipIf(OPJ_DATA_ROOT is None, diff --git a/glymur/version.py b/glymur/version.py new file mode 100644 index 0000000..256ed4e --- /dev/null +++ b/glymur/version.py @@ -0,0 +1,53 @@ +# This file is part of glymur, a Python interface for accessing JPEG 2000. +# +# http://glymur.readthedocs.org +# +# Copyright 2013 John Evans +# +# License: MIT + +import sys +import numpy as np +from distutils.version import StrictVersion + +from .lib import openjpeg as opj +from .lib import openjp2 as opj2 + +version = "0.4.1" +_sv = StrictVersion(version) +version_tuple = _sv.version + + +if opj.OPENJPEG is None and opj2.OPENJP2 is None: + openjpeg_version = '0.0.0' +elif opj2.OPENJP2 is None: + openjpeg_version = opj.version() +else: + openjpeg_version = opj2.version() + +_sv = StrictVersion(openjpeg_version) +openjpeg_version_tuple = _sv.version + +__doc__ = """\ +This is glymur **{glymur_version}** + +* OPENJPEG version: **{openjpeg}** +""".format(glymur_version=version, + openjpeg=openjpeg_version) + +info = """\ +Summary of glymur configuration +------------------------------- + +glymur {glymur} +OPENJPEG {openjpeg} +Python {python} +sys.platform {platform} +sys.maxsize {maxsize} +numpy {numpy} +""".format(glymur=version, + openjpeg=openjpeg_version, + python=sys.version, + platform=sys.platform, + maxsize=sys.maxsize, + numpy=np.__version__) diff --git a/setup.py b/setup.py index ff533a7..8e6233c 100644 --- a/setup.py +++ b/setup.py @@ -13,8 +13,7 @@ kwargs = {'name': 'Glymur', 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'scripts': ['bin/jp2dump'], 'license': 'MIT', - 'test_suite': 'glymur.test', - 'platforms': ['darwin']} + 'test_suite': 'glymur.test'} instllrqrs = ['numpy>=1.4.1'] if sys.hexversion < 0x03030000: From 427a4946b7654b83532bec759f8aacf7361aae87 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 15 Sep 2013 11:15:02 -0400 Subject: [PATCH 072/122] Added ExitStack to write/1.5 workflow. Closes #114 Some pylint work. --- glymur/jp2k.py | 164 +++++++++++++++++-------------------------------- 1 file changed, 58 insertions(+), 106 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index f3127bc..03ffc71 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -19,7 +19,6 @@ else: import ctypes import math import os -import re import struct import warnings @@ -386,132 +385,85 @@ class Jp2k(Jp2kBox): If glymur is unable to load the openjp2 library. """ if opj2.OPENJP2 is not None: - img = self._write_openjp2(img_array, verbose=verbose, **kwargs) + self._write_openjp2(img_array, verbose=verbose, **kwargs) elif opj.OPENJPEG is not None: - img = self._write_openjpeg(img_array, verbose=verbose, **kwargs) + self._write_openjpeg(img_array, verbose=verbose, **kwargs) else: - raise LibraryNotFoundError("You must have version 1.5 of OpenJPEG " - "or more recent before using this " + raise LibraryNotFoundError("You must have at least version 1.5 of " + "OpenJPEG before using this " "functionality.") def _write_openjpeg(self, img_array, verbose=False, **kwargs): """ + Write JPEG 2000 file using OpenJPEG 1.5 interface. """ cparams, colorspace = self._process_write_inputs(img_array, **kwargs) if img_array.ndim == 2: # Force the image to be 3D. Just makes things easier later on. - numrows, numcols = img_array.shape - img_array = img_array.reshape(numrows, numcols, 1) + img_array = img_array.reshape(img_array.shape[0], + img_array.shape[1], + 1) comptparms = _populate_comptparms(img_array, cparams) - image = opj.image_create(comptparms, colorspace) + with ExitStack() as stack: + image = opj.image_create(comptparms, colorspace) + stack.callback(opj.image_destroy, image) - numrows, numcols, numlayers = img_array.shape + numrows, numcols, numlayers = img_array.shape - # set image offset and reference grid - image.contents.x0 = cparams.image_offset_x0 - image.contents.y0 = cparams.image_offset_y0 - image.contents.x1 = image.contents.x0 + (numcols - 1) * cparams.subsampling_dx + 1 - image.contents.y1 = image.contents.y0 + (numrows - 1) * cparams.subsampling_dy + 1 + # set image offset and reference grid + image.contents.x0 = cparams.image_offset_x0 + image.contents.y0 = cparams.image_offset_y0 + image.contents.x1 = image.contents.x0 \ + + (numcols - 1) * cparams.subsampling_dx + 1 + image.contents.y1 = image.contents.y0 \ + + (numrows - 1) * cparams.subsampling_dy + 1 - # Stage the image data to the openjpeg data structure. - for k in range(0,numlayers): - layer = np.ascontiguousarray(img_array[:,:,k], dtype=np.int32) - dest = image.contents.comps[k].data - src = layer.ctypes.data - ctypes.memmove(dest, src, layer.nbytes) + # Stage the image data to the openjpeg data structure. + for k in range(0, numlayers): + layer = np.ascontiguousarray(img_array[:, :, k], + dtype=np.int32) + dest = image.contents.comps[k].data + src = layer.ctypes.data + ctypes.memmove(dest, src, layer.nbytes) - # set encode format - cinfo = opj.create_compress(cparams.codec_fmt) + cinfo = opj.create_compress(cparams.codec_fmt) + stack.callback(opj.destroy_compress, cinfo) - event_mgr = opj.EventMgrType() - _info_handler = _INFO_CALLBACK if verbose else None - event_mgr.info_handler = _info_handler - event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, - ctypes.c_void_p) - event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, - ctypes.c_void_p) + # Setup the info, warning, and error handlers. + # Always use the warning and error handler. Use of an info + # handler is optional. + event_mgr = opj.EventMgrType() + _info_handler = _INFO_CALLBACK if verbose else None + event_mgr.info_handler = _info_handler + event_mgr.warning_handler = ctypes.cast(_WARNING_CALLBACK, + ctypes.c_void_p) + event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, + ctypes.c_void_p) - opj.setup_encoder(cinfo, ctypes.byref(cparams), image) + opj.setup_encoder(cinfo, ctypes.byref(cparams), image) - # open a byte stream for writing - # allocate memory for all tiles - cio = opj.cio_open(cinfo) - - if not opj.encode(cinfo, cio, image): - raise IOError("Encode error.") + cio = opj.cio_open(cinfo) + stack.callback(opj.cio_close, cio) - pos = opj.cio_tell(cio) + if not opj.encode(cinfo, cio, image): + raise IOError("Encode error.") - ss = ctypes.string_at(cio.contents.buffer, pos) - f = open(self.filename,'wb') - f.write(ss) - f.close() - opj.cio_close(cio); + pos = opj.cio_tell(cio) - opj.destroy_compress(cinfo); - opj.image_destroy(image); + blob = ctypes.string_at(cio.contents.buffer, pos) + fptr = open(self.filename, 'wb') + stack.callback(fptr.close) + fptr.write(blob) self.parse() def _write_openjp2(self, img_array, verbose=False, **kwargs): - """Write image data to a JP2/JPX/J2k file. Intended usage of the - various parameters follows that of OpenJPEG's opj_compress utility. - - This method can only be used to create JPEG 2000 images that can fit - in memory. - - Parameters - ---------- - img_array : ndarray - Image data to be written to file. - cbsize : tuple, optional - Code block size (DY, DX). - colorspace : str, optional - Either 'rgb' or 'gray'. - cratios : iterable - Compression ratios for successive layers. - eph : bool, optional - If true, write SOP marker after each header packet. - grid_offset : tuple, optional - Offset (DY, DX) of the origin of the image in the reference grid. - mct : bool, optional - Specifies usage of the multi component transform. If not - specified, defaults to True if the colorspace is RGB. - modesw : int, optional - Mode switch. - 1 = BYPASS(LAZY) - 2 = RESET - 4 = RESTART(TERMALL) - 8 = VSC - 16 = ERTERM(SEGTERM) - 32 = SEGMARK(SEGSYM) - numres : int, optional - Number of resolutions. - prog : str, optional - Progression order, one of "LRCP" "RLCP", "RPCL", "PCRL", "CPRL". - psnr : iterable, optional - Different PSNR for successive layers. - psizes : list, optional - List of precinct sizes. Each precinct size tuple is defined in - (height x width). - sop : bool, optional - If true, write SOP marker before each packet. - subsam : tuple, optional - Subsampling factors (dy, dx). - tilesize : tuple, optional - Numeric tuple specifying tile size in terms of (numrows, numcols), - not (X, Y). - verbose : bool, optional - Print informational messages produced by the OpenJPEG library. - - Raises - ------ - glymur.LibraryNotFoundError - If glymur is unable to load the openjp2 library. + """ + Write JPEG 2000 file using OpenJPEG 1.5 interface. """ cparams, colorspace = self._process_write_inputs(img_array, **kwargs) @@ -784,14 +736,14 @@ class Jp2k(Jp2kBox): opj.set_default_decoder_parameters(ctypes.byref(dparameters)) dparameters.cp_reduce = rlevel dparameters.decod_format = self._codec_format - + infile = self.filename.encode() nelts = opj.PATH_LEN - len(infile) infile += b'0' * nelts dparameters.infile = infile - + dinfo = opj.create_decompress(dparameters.decod_format) - + event_mgr = opj.EventMgrType() info_handler = ctypes.cast(_INFO_CALLBACK, ctypes.c_void_p) event_mgr.info_handler = info_handler if verbose else None @@ -800,19 +752,19 @@ class Jp2k(Jp2kBox): event_mgr.error_handler = ctypes.cast(_ERROR_CALLBACK, ctypes.c_void_p) opj.set_event_mgr(dinfo, ctypes.byref(event_mgr)) - + opj.setup_decoder(dinfo, dparameters) - + with open(self.filename, 'rb') as fptr: src = fptr.read() cio = opj.cio_open(dinfo, src) - + image = opj.decode(dinfo, cio) - + stack.callback(opj.image_destroy, image) stack.callback(opj.destroy_decompress, dinfo) stack.callback(opj.cio_close, cio) - + data = extract_image_cube(image) except ValueError: From 293d796b916f753e7a758b1c3fea27c18b1764af Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 15 Sep 2013 11:57:04 -0400 Subject: [PATCH 073/122] Streamlined the advanced installation instructions a bit. Closes #115 Linux users don't need as much hand-holding. --- docs/source/detailed_installation.rst | 106 +++++++++++--------------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 879d2a1..7fb5b3b 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -1,31 +1,33 @@ ---------------------------------- Advanced Installation Instructions ---------------------------------- +Most users won't need to read this! You've been warned... '''''''''''''''''''''' Glymur Configuration '''''''''''''''''''''' The default glymur installation process relies upon OpenJPEG version -1.X being properly installed on your system. This will, however, only -give you you basic read capabilities, so if you wish to take advantage -of more of glymur's features, you should install version 2.0 or -compile OpenJPEG as a shared library (named *openjp2* instead of -*openjpeg*) from the developmental source that you can retrieve via -subversion. As of this time of writing, svn revision 2345 works. +1.X being properly installed on your system. If you have version 1.5 you can +both read and write JPEG 2000 files, but you may wish to install version 2.0 +or the 2.0+ version from OpenJPEG's development trunk for better performance. +If you do that, you should compile it as a shared library (named *openjp2* +instead of *openjpeg*) from the developmental source that you can retrieve +via subversion. As of this time of writing, svn revision 2345 works. You should also download the test data for the purpose of configuring -and running OpenJPEG's test suite, check their instructions for all -this. You should set the **OPJ_DATA_ROOT** environment variable -for the purpose of running Glymur's test suite. :: +and running OpenJPEG's test suite, check their instructions for all this. +You should set the **OPJ_DATA_ROOT** environment variable for the purpose +of running Glymur's test suite. :: $ svn co http://openjpeg.googlecode.com/svn/data $ export OPJ_DATA_ROOT=`pwd`/data -Glymur uses ctypes (for the moment) to access the openjp2 library, and -because ctypes access libraries in a platform-dependent manner, it is +Glymur uses ctypes to access the openjp2/openjpeg libraries, +and because ctypes accesses libraries in a platform-dependent manner, it is recommended that you create a configuration file to help Glymur properly find -the openjp2 library. The configuration format is the same as used by Python's -configparser module, i.e. :: +the openjpeg or openjp2 libraries (linux users don't need to bother if you are +using OpenJPEG as provided by your package manager). The configuration +format is the same as used by Python's configparser module, i.e. :: [library] openjp2: /opt/openjp2-svn/lib/libopenjp2.so @@ -37,7 +39,8 @@ to the configuration file would normally be :: $HOME/.config/glymur/glymurrc -but if you have **$XDG_CONFIG_HOME** defined, the path will be :: +but if you have the **XDG_CONFIG_HOME** environment variable defined, +the path will be :: $XDG_CONFIG_HOME/glymur/glymurrc @@ -52,12 +55,11 @@ You may also include a line for the version 1.x openjpeg library if you have it installed in a non-standard place, i.e. :: [library] - openjp2: /opt/openjp2-svn/lib/libopenjp2.so openjpeg: /not/the/usual/location/lib/libopenjpeg.so -''''''''''''''''''''''''''''''''''''''''''' -Package Management Suggestions for Testing -''''''''''''''''''''''''''''''''''''''''''' +'''''''''''''''''''''''''''''' +Package Management Suggestions +'''''''''''''''''''''''''''''' You only need to read this section if you want detailed platform-specific instructions on running as many tests as possible or wish to @@ -67,8 +69,8 @@ packages/RPMs/ports/whatever without going through pip. Mac OS X -------- -All the necessary packages are available to use glymur with Python 3.3 via -MacPorts. You should install the following set of ports: +All the necessary packages are available to use glymur with Python 2.6, 2.7, +and 3.3 via MacPorts. You should install the following set of ports: * python33 * py33-numpy @@ -80,54 +82,38 @@ MacPorts supplies both OpenJPEG 1.5.0 and OpenJPEG 2.0.0. Linux ----- -For the most part, you only need python and numpy to run glymur. In order to -run as many tests as possible, however, the following Python packages may also -need to be installed. +For the most part, you only need python and numpy to run glymur, so on +just about all distributions you are already set to go (and you don't +need to mess around with a configuration file, as the openjpeg shared +libraries are found in the usual places thanks to your package manager). +In order to run as many tests as possible, however, the following Python +packages may also need to be installed. Consult your package manager +documentation or use pip. * setuptools * matplotlib * pillow - * contextlib2 (python 2.7 only) - * mock (python 2.7 only) + * contextlib2 (python 2.6, 2.7 only) + * mock (python 2.6, 2.7 only) + * ordereddict (python 2.6 only) -OpenSUSE 12.3 -''''''''''''' -Ships with Python 3.3 and 2.7. You should use pip to install Pillow. - -Fedora 19 -''''''''' -Ships with Python 3.3 and 2.7. All packages available as RPMs. - -Fedora 18 -''''''''' -Fedora 18 ships with Python 3.3 and 2.7. Most packages are available as -standard RPMS, but you should use pip to install Pillow as it is not available -in the Fedora 18 default repositories:: - - $ yum install python3-devel # pip needs this in order to compile Pillow - $ yum install python3-pip - $ pip-python3 install Pillow --user - -Fedora 17 -''''''''' -Fedora 17 ships with Python 2.7 and OpenJPEG 1.4. You must install contextlib2 -and Pillow via pip. :: - - $ yum install python-devel # pip needs this in order to compile Pillow - $ pip-python install Pillow --user - $ pip-python install contextlib2 --user +Glymur's been tested on the following linux platforms without any unexpected +difficulties: + + * OpenSUSE 12.3 + * Fedora 17, 18, 19 + * Raspian + * Travis CI (currently Ubuntu 12.04?) + * CentOS 6.4 Windows ------- 32-bit WinPython 2.7.5 seemed to work with OpenJPEG 1.X, 2.0, and the development version, but still required contextlib2 and mock to be installed via pip. WinPython 3.3.2, however, seems to have trouble -with OpenJPEG 2.0, so I would suggest using the development version -there (I'm unwilling to spend ANY more time trying to figure out what -the problem is there). - -At the moment I do not have access to a win32 machine, and -64-bit windows is completely untested. +with OpenJPEG 2.0, so I would suggest using the development version with +that configuration. I no longer have any access to a windows machine, +so I cannot currently offer much guidance here. ''''''' @@ -137,8 +123,8 @@ Testing There are two environment variables you may wish to set before running the tests. - * **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data - * **FORMAT_CORPUS_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this) + * **OPJ_DATA_ROOT** - points to directory for OpenJPEG test data (see above) + * **FORMAT_CORPUS_DATA_ROOT** - points to directory for format-corpus repository (see https://github.com/openplanets/format-corpus if you wish, but you really don't need to bother with this) Setting these two environment variables is not required, as any tests using either of them will be skipped. @@ -157,7 +143,7 @@ or from the command line. :: Quite a few tests are currently skipped. These include tests whose OpenJPEG counterparts are already failing, and others which do pass but still produce heaps of output on stderr. Rather than let this swamp -the signal (that most of the tests are actually passing), they've been +the signal (that most of those tests are actually passing), they've been filtered out for now. There are also more skipped tests on Python 2.7 than on Python 3.3. The important part is whether or not any test errors are reported at the end. From fe6c607e67e1b532619462576b89b8ed2d058680 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 15 Sep 2013 12:33:29 -0400 Subject: [PATCH 074/122] Openjpeg 1.3 reads this image as indices, not RGB. #116 --- glymur/test/test_opj_suite.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index 36f0a7b..a5daf3e 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -645,7 +645,11 @@ class TestSuite(unittest.TestCase): jfile = opj_data_file('input/conformance/file9.jp2') jp2k = Jp2k(jfile) jpdata = jp2k.read() - self.assertEqual(jpdata.shape, (512, 768, 3)) + if re.match(r"""1\.3""", glymur.version.openjpeg_version): + # Version 1.3 reads the indexed image as indices, not as RGB. + self.assertEqual(jpdata.shape, (512, 768)) + else: + self.assertEqual(jpdata.shape, (512, 768, 3)) def test_NR_DEC_Bretagne2_j2k_1_decode(self): jfile = opj_data_file('input/nonregression/Bretagne2.j2k') From 7622b940739e4b1dd049603a5d7915ea27e41123 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 15 Sep 2013 12:34:00 -0400 Subject: [PATCH 075/122] Fixed typo in error message. #116 --- glymur/jp2k.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 03ffc71..00b71c2 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -949,7 +949,7 @@ class Jp2k(Jp2kBox): If glymur is unable to load the openjp2 library. """ if version.openjpeg_version_tuple[0] < 2: - raise LibraryNotFoundError("You must have at least version 2.0.0" + raise LibraryNotFoundError("You must have at least version 2.0.0 " "of OpenJP2 installed before using " "this functionality.") From bc1421bb19473845f6c7bf382aec51deb4388c18 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 16 Sep 2013 06:33:23 -0400 Subject: [PATCH 076/122] Qualified on 1.3, 1.4. Closes #116 --- glymur/test/test_conformance.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/glymur/test/test_conformance.py b/glymur/test/test_conformance.py index 3c7c9c4..5f53b5f 100644 --- a/glymur/test/test_conformance.py +++ b/glymur/test/test_conformance.py @@ -12,6 +12,7 @@ These tests deal with JPX/JP2/J2K images in the format-corpus repository. import os from os.path import join +import re import sys if sys.hexversion < 0x02070000: @@ -19,6 +20,7 @@ if sys.hexversion < 0x02070000: else: import unittest +import glymur from glymur import Jp2k try: @@ -39,6 +41,9 @@ except KeyError: class TestSuiteFormatCorpus(unittest.TestCase): """Test suite for files in format corpus repository.""" + @unittest.skipIf(re.match(r"""1\.[0123]""", + glymur.version.openjpeg_version) is not None, + "Needs 1.3+ to catch this.") def test_balloon_trunc1(self): """Has one byte shaved off of EOC marker.""" jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, @@ -54,6 +59,9 @@ class TestSuiteFormatCorpus(unittest.TestCase): with self.assertRaises(OSError): j2k.read(rlevel=-1) + @unittest.skipIf(re.match(r"""1\.[01234]""", + glymur.version.openjpeg_version) is not None, + "Needs 1.4+ to catch this.") def test_balloon_trunc2(self): """Shortened by 5000 bytes.""" jfile = os.path.join(FORMAT_CORPUS_DATA_ROOT, From 8e29ab955868eaae0c67736ba2773da9376fdbeb Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 16 Sep 2013 19:14:55 -0400 Subject: [PATCH 077/122] Minor doc fixes. --- docs/source/introduction.rst | 5 ++--- docs/source/roadmap.rst | 6 ------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 0a59ebd..37dcb5a 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -20,7 +20,7 @@ OpenJPEG Installation ===================== Glymur will read JPEG 2000 images with versions 1.3, 1.4, 1.5, 2.0, and the trunk/development version of OpenJPEG. Writing images is -only supported with the 2.0 series, however, and the trunk/development +only supported with the 1.5 or better, however, and the trunk/development version is strongly recommended. For more information about OpenJPEG, please consult http://www.openjpeg.org. @@ -55,6 +55,5 @@ You can run the tests from within python as follows:: >>> import glymur >>> glymur.runtests() -Many tests are currently skipped; in fact most of them are skipped if you -are relying on OpenJPEG 1.X. The important thing, though, is whether or +Many tests are currently skipped, but the The important thing is whether or not any tests fail. diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst index 7f50a87..f9216a3 100644 --- a/docs/source/roadmap.rst +++ b/docs/source/roadmap.rst @@ -1,9 +1,3 @@ ------------- -Known Issues ------------- - - * WinPython 3.3.2 and OpenJPEG 2.0 don't seem to want to play well together. If you do not need write support, just use OpenJPEG 1.5 instead. If you do need write support, try the development version of OpenJPEG. - ------- Roadmap ------- From 52ef9cb8ed212215abc8da3f0e9d789c33f743a3 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 16 Sep 2013 19:43:37 -0400 Subject: [PATCH 078/122] Releasing 0.5.0. --- CHANGES.txt | 2 +- docs/source/conf.py | 4 ++-- glymur/version.py | 8 ++++---- setup.py | 5 ++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 96b8173..35b355e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -Sep 12, 2013 - v0.4.2r Added write support for 1.5.x. +Sep 16, 2013 - v0.5.0 Added write support for 1.5.x. Added version module. Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1 diff --git a/docs/source/conf.py b/docs/source/conf.py index c5dccb4..6b9eb18 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -76,9 +76,9 @@ copyright = u'2013, John Evans' # built documents. # # The short X.Y version. -version = '0.4' +version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.4.1' +release = '0.5.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 256ed4e..9b6499d 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -8,13 +8,13 @@ import sys import numpy as np -from distutils.version import StrictVersion +from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.4.1" -_sv = StrictVersion(version) +version = "0.5.0rc2" +_sv = LooseVersion(version) version_tuple = _sv.version @@ -25,7 +25,7 @@ elif opj2.OPENJP2 is None: else: openjpeg_version = opj2.version() -_sv = StrictVersion(openjpeg_version) +_sv = LooseVersion(openjpeg_version) openjpeg_version_tuple = _sv.version __doc__ = """\ diff --git a/setup.py b/setup.py index 8e6233c..8d62705 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,6 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.4.1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans', @@ -38,4 +37,8 @@ clssfrs = ["Programming Language :: Python", "Intended Audience :: Information Technology", "Topic :: Software Development :: Libraries :: Python Modules"] kwargs['classifiers'] = clssfrs + +import glymur +kwargs['version'] = glymur.version.version + setup(**kwargs) From cb523e56542815e296eb563c8bc01da6e85b5d0e Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 16 Sep 2013 19:44:37 -0400 Subject: [PATCH 079/122] Releasing 0.5.0 --- glymur/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/version.py b/glymur/version.py index 9b6499d..740d610 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.0rc2" +version = "0.5.0" _sv = LooseVersion(version) version_tuple = _sv.version From 047f9192de92f08613d773492834c488bf6d3549 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 19 Sep 2013 14:09:28 -0400 Subject: [PATCH 080/122] Tests failed when OPJ_DATA_ROOT not set. --- glymur/test/test_opj_suite.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a5daf3e..456ff9b 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -6724,6 +6724,8 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Feature not supported in glymur until openjpeg 2.0") class TestSuite_bands(unittest.TestCase): @@ -6853,6 +6855,8 @@ class TestSuite_bands(unittest.TestCase): self.assertTrue(True) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Tests not passing until 2.0") class TestSuite2point0(unittest.TestCase): @@ -6915,6 +6919,8 @@ class TestSuite2point0(unittest.TestCase): self.assertTrue(True) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Test not in done in v2.0.0 official") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, From 47ec633ff873936508beaa08982823885445e6bc Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 19 Sep 2013 14:09:52 -0400 Subject: [PATCH 081/122] Being more resilient when faced with seemingly unparseable xml. If the XML content starts out with bad bytes, scan ahead to try to find the " -1: + text = read_buffer[decl_start:].decode('utf-8') + else: + raise + + # Let the user know that the XML box was problematic. + msg = 'A UnicodeDecodeError was encountered parsing an XML box at ' + msg += 'byte position {0} ({1}), but the XML was still recovered.' + msg = msg.format(offset, ude.reason) + warnings.warn(msg, UserWarning) + # Strip out any trailing nulls, as they can foul up XML parsing. text = text.rstrip(chr(0)) + # Scan for the start of the xml declaration. + try: elt = ET.fromstring(text) xml = ET.ElementTree(elt) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index bbf551b..1ab5b29 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -71,7 +71,7 @@ class TestJp2kBadXmlFile(unittest.TestCase): 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. + # Everything up until the UUID box. write_buffer = ifile.read(77) tfile.write(write_buffer) @@ -119,7 +119,68 @@ class TestJp2kBadXmlFile(unittest.TestCase): self.assertIsNone(jp2k.box[3].xml) -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and not OPENJP2_IS_V2_OFFICIAL, +@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +class TestBadButRecoverableXmlFile(unittest.TestCase): + """Test suite for XML box that is bad, but we can still recover the XML.""" + + @classmethod + def setUpClass(cls): + """Setup a JP2 file with bad bytes preceding the XML. We only need + to do this once per class rather than once per test. + """ + jp2file = glymur.data.nemo() + 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 UUID box. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the xml box with bad xml + # Length = 64, id is 'xml '. + write_buffer = struct.pack('>I4s', int(64), b'xml ') + tfile.write(write_buffer) + + # Write out 8 bad bytes. + write_buffer = b'\x00\x00\x07\x90xml ' + tfile.write(write_buffer) + + # Write out 48 good bytes constituting the XML payload. + write_buffer = b'this is a test' + write_buffer = write_buffer.encode() + tfile.write(write_buffer) + + # Get the rest of the input file. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + @classmethod + def tearDownClass(cls): + os.unlink(cls._bad_xml_file) + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_bad_xml_box_warning(self): + """Should warn in case of bad XML""" + with self.assertWarns(UserWarning): + Jp2k(self._bad_xml_file) + + def test_recover_from_bad_xml(self): + """Should be able to recover info from xml box with bad xml.""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + jp2 = Jp2k(self._bad_xml_file) + + self.assertEqual(jp2.box[3].box_id, 'xml ') + self.assertEqual(jp2.box[3].offset, 77) + self.assertEqual(jp2.box[3].length, 64) + self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), + b'this is a test') + + +@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and + not OPENJP2_IS_V2_OFFICIAL, "Missing openjp2 library version 2.0+.") class TestJp2k_2_1(unittest.TestCase): """Test suite for version 2.0+ of openjpeg software""" @@ -312,56 +373,6 @@ class TestJp2k_1_x(unittest.TestCase): with self.assertRaises(IOError): j.read(rlevel=6) - @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: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, mct=False) - actdata = ofile.read() - np.testing.assert_array_equal(actdata, expdata) - - 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.""" - j2k = Jp2k(self.j2kfile) - expdata = j2k.read() - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - ofile.write(expdata[:, :, 0], mct=True) - - @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) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, prog='CPRL') - actdata = ofile.read() - np.testing.assert_array_equal(actdata, expdata) - - 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. Basic jp2 test.""" jp2k = Jp2k(self.jp2file) From 5fb827c61e7c14113f0b21453d225ba2d6705842 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 19 Sep 2013 16:27:19 -0400 Subject: [PATCH 082/122] Attempt to fix travis build. #120 --- .travis.yml | 9 +++------ requirements.txt | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml index a8a0d1b..f4fc733 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,10 @@ before_install: - sudo apt-get install -qq python3-numpy # command to install dependencies -install: - - pip install . --use-mirrors +install: "pip install -r requirements.txt --use-mirrors" # command to run tests -script: - - "python -m unittest discover" +script: "python -m unittest discover" notifications: - email: - - john.g.evans.ne@gmail.com + email: "john.g.evans.ne@gmail.com" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9dd042a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +numpy +contextlib2>=0.4.0 +mock>=1.0.1 From e6ffa0e271b0dde9f66395ed521e58848ab5eb8a Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 19 Sep 2013 16:38:53 -0400 Subject: [PATCH 083/122] Renamed to travis-requirements so as to not be confused with readthedocs. #120 --- .travis.yml | 2 +- requirements.txt => travis-requirements.txt | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename requirements.txt => travis-requirements.txt (100%) diff --git a/.travis.yml b/.travis.yml index f4fc733..4898e65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - sudo apt-get install -qq python3-numpy # command to install dependencies -install: "pip install -r requirements.txt --use-mirrors" +install: "pip install -r travis-requirements.txt --use-mirrors" # command to run tests script: "python -m unittest discover" diff --git a/requirements.txt b/travis-requirements.txt similarity index 100% rename from requirements.txt rename to travis-requirements.txt From 28dc0265e453b6b86237f0176a73d634680382be Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 19 Sep 2013 20:56:33 -0400 Subject: [PATCH 084/122] Updated fix for python3. #118 --- glymur/jp2box.py | 2 +- glymur/test/test_jp2k.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 81d8e6c..f05e9de 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1854,7 +1854,7 @@ class XMLBox(Jp2kBox): except UnicodeDecodeError as ude: # Possibly bad string of bytes to begin with. # Try to search for -1: text = read_buffer[decl_start:].decode('utf-8') else: diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 1ab5b29..4f06745 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -147,7 +147,6 @@ class TestBadButRecoverableXmlFile(unittest.TestCase): # Write out 48 good bytes constituting the XML payload. write_buffer = b'this is a test' - write_buffer = write_buffer.encode() tfile.write(write_buffer) # Get the rest of the input file. From 4ff3a94bb12fbc218e07a156f9efbbb86a180859 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 19 Sep 2013 21:39:31 -0400 Subject: [PATCH 085/122] Basic refactoring, pylint work. #118 --- glymur/test/test_jp2box.py | 366 +++++++++++++++++++++++---------- glymur/test/test_jp2box_xml.py | 266 ++++++++++++++++++++++++ glymur/test/test_jp2k.py | 123 ----------- 3 files changed, 525 insertions(+), 230 deletions(-) create mode 100644 glymur/test/test_jp2box_xml.py diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 71dbd72..72b9f9d 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -320,113 +320,6 @@ class TestChannelDefinition(unittest.TestCase): 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() - self.j2kfile = glymur.data.goodstuff() - - raw_xml = b""" - - - 1 - 2008 - 141100 - - - - - 4 - 2011 - 59900 - - - - 68 - 2011 - 13600 - - - - """ - with tempfile.NamedTemporaryFile(suffix=".xml", delete=False) as tfile: - tfile.write(raw_xml) - tfile.flush() - self.xmlfile = tfile.name - - j2k = Jp2k(self.j2kfile) - codestream = j2k.get_codestream() - height = codestream.segment[1].ysiz - width = codestream.segment[1].xsiz - num_components = len(codestream.segment[1].xrsiz) - - self.jp2b = JPEG2000SignatureBox() - self.ftyp = FileTypeBox() - self.jp2h = JP2HeaderBox() - self.jp2c = ContiguousCodestreamBox() - self.ihdr = ImageHeaderBox(height=height, width=width, - num_components=num_components) - self.colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) - - def tearDown(self): - os.unlink(self.xmlfile) - - def test_negative_file_and_xml(self): - """The XML should come from only one source.""" - xml_object = ET.parse(self.xmlfile) - 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 a basic XMLBox""" - j2k = Jp2k(self.j2kfile) - - self.jp2h.box = [self.ihdr, self.colr] - - the_xml = ET.fromstring('0') - xmlb = glymur.jp2box.XMLBox(xml=the_xml) - self.assertEqual(ET.tostring(xmlb.xml), - b'0') - - 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) - self.assertEqual(jp2.box[3].box_id, 'xml ') - self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), - b'0') - - @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.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) - - output_boxes = [box.box_id for box in jp2.box] - self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ', - 'jp2c']) - - elts = jp2.box[3].xml.findall('country') - self.assertEqual(len(elts), 3) - - neighbor = elts[1].find('neighbor') - self.assertEqual(neighbor.attrib['name'], 'Malaysia') - self.assertEqual(neighbor.attrib['direction'], 'N') - - class TestColourSpecificationBox(unittest.TestCase): """Test suite for colr box instantiation.""" @@ -856,5 +749,264 @@ class TestJpxBoxes(unittest.TestCase): self.assertEqual(len(jpx.box[5].box), 0) +@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +class TestChannelDefinition(unittest.TestCase): + """Test suite for channel definition boxes.""" + + @classmethod + def setUpClass(cls): + """Need a one_plane plane image for greyscale testing.""" + j2k = Jp2k(glymur.data.goodstuff()) + data = j2k.read() + # Write the first component back out to file. + with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: + grey_j2k = Jp2k(tfile.name, 'wb') + grey_j2k.write(data[:, :, 0]) + cls.one_plane = tfile.name + # Write the first two components back out to file. + with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: + grey_j2k = Jp2k(tfile.name, 'wb') + grey_j2k.write(data[:, :, 0:1]) + cls.two_planes = tfile.name + # Write four components back out to file. + with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: + rgba_jp2 = Jp2k(tfile.name, 'wb') + shape = (data.shape[0], data.shape[1], 1) + alpha = np.zeros((shape), dtype=data.dtype) + data4 = np.concatenate((data, alpha), axis=2) + rgba_jp2.write(data4) + cls.four_planes = tfile.name + + @classmethod + def tearDownClass(cls): + os.unlink(cls.one_plane) + os.unlink(cls.two_planes) + os.unlink(cls.four_planes) + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + j2k = Jp2k(self.j2kfile) + codestream = j2k.get_codestream() + height = codestream.segment[1].ysiz + width = codestream.segment[1].xsiz + num_components = len(codestream.segment[1].xrsiz) + + self.jp2b = JPEG2000SignatureBox() + self.ftyp = FileTypeBox() + self.jp2h = JP2HeaderBox() + self.jp2c = ContiguousCodestreamBox() + self.ihdr = ImageHeaderBox(height=height, width=width, + num_components=num_components) + self.colr_rgb = ColourSpecificationBox(colorspace=glymur.core.SRGB) + self.colr_gr = ColourSpecificationBox(colorspace=glymur.core.GREYSCALE) + + def tearDown(self): + pass + + def test_cdef_no_inputs(self): + """channel_type and association are required inputs.""" + with self.assertRaises(IOError): + glymur.jp2box.ChannelDefinitionBox() + + def test_rgb_with_index(self): + """Just regular RGB.""" + j2k = Jp2k(self.j2kfile) + channel_type = [COLOR, COLOR, COLOR] + association = [RED, GREEN, BLUE] + cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], + channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_rgb, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + + jp2 = Jp2k(tfile.name) + jp2h = jp2.box[2] + boxes = [box.box_id for box in jp2h.box] + self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) + self.assertEqual(jp2h.box[2].index, (0, 1, 2)) + self.assertEqual(jp2h.box[2].channel_type, + (COLOR, COLOR, COLOR)) + self.assertEqual(jp2h.box[2].association, + (RED, GREEN, BLUE)) + + def test_rgb(self): + """Just regular RGB, but don't supply the optional index.""" + j2k = Jp2k(self.j2kfile) + channel_type = [COLOR, COLOR, COLOR] + association = [RED, GREEN, BLUE] + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_rgb, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + + jp2 = Jp2k(tfile.name) + jp2h = jp2.box[2] + boxes = [box.box_id for box in jp2h.box] + self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) + self.assertEqual(jp2h.box[2].index, (0, 1, 2)) + self.assertEqual(jp2h.box[2].channel_type, + (COLOR, COLOR, COLOR)) + self.assertEqual(jp2h.box[2].association, + (RED, GREEN, BLUE)) + + def test_rgba(self): + """Just regular RGBA.""" + j2k = Jp2k(self.four_planes) + channel_type = (COLOR, COLOR, COLOR, OPACITY) + association = (RED, GREEN, BLUE, WHOLE_IMAGE) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_rgb, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + + jp2 = Jp2k(tfile.name) + jp2h = jp2.box[2] + boxes = [box.box_id for box in jp2h.box] + self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) + self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3)) + self.assertEqual(jp2h.box[2].channel_type, channel_type) + self.assertEqual(jp2h.box[2].association, association) + + def test_bad_rgba(self): + """R, G, and B must be specified.""" + j2k = Jp2k(self.four_planes) + channel_type = (COLOR, COLOR, OPACITY, OPACITY) + association = (RED, GREEN, BLUE, WHOLE_IMAGE) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_rgb, cdef] + self.jp2h.box = boxes + 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_grey(self): + """Just regular greyscale.""" + j2k = Jp2k(self.one_plane) + channel_type = (COLOR,) + association = (GREY,) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_gr, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + + jp2 = Jp2k(tfile.name) + jp2h = jp2.box[2] + boxes = [box.box_id for box in jp2h.box] + self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) + self.assertEqual(jp2h.box[2].index, (0,)) + self.assertEqual(jp2h.box[2].channel_type, channel_type) + self.assertEqual(jp2h.box[2].association, association) + + def test_grey_alpha(self): + """Just regular greyscale plus alpha.""" + j2k = Jp2k(self.two_planes) + channel_type = (COLOR, OPACITY) + association = (GREY, WHOLE_IMAGE) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_gr, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + j2k.wrap(tfile.name, boxes=boxes) + + jp2 = Jp2k(tfile.name) + jp2h = jp2.box[2] + boxes = [box.box_id for box in jp2h.box] + self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) + self.assertEqual(jp2h.box[2].index, (0, 1)) + self.assertEqual(jp2h.box[2].channel_type, channel_type) + self.assertEqual(jp2h.box[2].association, association) + + def test_bad_grey_alpha(self): + """A greyscale image with alpha layer must specify a color channel""" + j2k = Jp2k(self.two_planes) + + channel_type = (OPACITY, OPACITY) + association = (GREY, WHOLE_IMAGE) + + # This cdef box + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + boxes = [self.ihdr, self.colr_gr, cdef] + self.jp2h.box = boxes + boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] + with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: + with self.assertRaises((OSError, IOError)): + j2k.wrap(tfile.name, boxes=boxes) + + def test_only_one_cdef_in_jp2h(self): + """There can only be one channel definition box in the jp2 header.""" + j2k = Jp2k(self.j2kfile) + + channel_type = (COLOR, COLOR, COLOR) + association = (RED, GREEN, BLUE) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + + boxes = [self.ihdr, cdef, self.colr_rgb, cdef] + self.jp2h.box = boxes + + 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_jp2h(self): + """need cdef in jp2h""" + j2k = Jp2k(self.j2kfile) + boxes = [self.ihdr, self.colr_rgb] + self.jp2h.box = boxes + + channel_type = (COLOR, COLOR, COLOR) + association = (RED, GREEN, BLUE) + cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + + 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_type = (COLOR, COLOR, 3) + association = (RED, GREEN, BLUE) + with self.assertRaises(IOError): + 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. + """ + channel_type = (COLOR, COLOR) + association = (RED, GREEN, BLUE) + with self.assertRaises(IOError): + glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, + association=association) + + if __name__ == "__main__": unittest.main() diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py new file mode 100644 index 0000000..ba1ff15 --- /dev/null +++ b/glymur/test/test_jp2box_xml.py @@ -0,0 +1,266 @@ +""" +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 os +import struct +import sys +import tempfile +import warnings +import xml.etree.cElementTree as ET + +if sys.hexversion < 0x02070000: + import unittest2 as unittest +else: + import unittest + +import glymur +from glymur import Jp2k +from glymur.jp2box import ColourSpecificationBox, ContiguousCodestreamBox +from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox +from glymur.jp2box import JPEG2000SignatureBox + + +@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() + self.j2kfile = glymur.data.goodstuff() + + raw_xml = b""" + + + 1 + 2008 + 141100 + + + + + 4 + 2011 + 59900 + + + + 68 + 2011 + 13600 + + + + """ + with tempfile.NamedTemporaryFile(suffix=".xml", delete=False) as tfile: + tfile.write(raw_xml) + tfile.flush() + self.xmlfile = tfile.name + + j2k = Jp2k(self.j2kfile) + codestream = j2k.get_codestream() + height = codestream.segment[1].ysiz + width = codestream.segment[1].xsiz + num_components = len(codestream.segment[1].xrsiz) + + self.jp2b = JPEG2000SignatureBox() + self.ftyp = FileTypeBox() + self.jp2h = JP2HeaderBox() + self.jp2c = ContiguousCodestreamBox() + self.ihdr = ImageHeaderBox(height=height, width=width, + num_components=num_components) + self.colr = ColourSpecificationBox(colorspace=glymur.core.SRGB) + + def tearDown(self): + os.unlink(self.xmlfile) + + def test_negative_file_and_xml(self): + """The XML should come from only one source.""" + xml_object = ET.parse(self.xmlfile) + 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 a basic XMLBox""" + j2k = Jp2k(self.j2kfile) + + self.jp2h.box = [self.ihdr, self.colr] + + the_xml = ET.fromstring('0') + xmlb = glymur.jp2box.XMLBox(xml=the_xml) + self.assertEqual(ET.tostring(xmlb.xml), + b'0') + + 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) + self.assertEqual(jp2.box[3].box_id, 'xml ') + self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), + b'0') + + @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.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) + + output_boxes = [box.box_id for box in jp2.box] + self.assertEqual(output_boxes, ['jP ', 'ftyp', 'jp2h', 'xml ', + 'jp2c']) + + elts = jp2.box[3].xml.findall('country') + self.assertEqual(len(elts), 3) + + neighbor = elts[1].find('neighbor') + self.assertEqual(neighbor.attrib['name'], 'Malaysia') + self.assertEqual(neighbor.attrib['direction'], 'N') + + +@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +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. + """ + jp2file = glymur.data.nemo() + 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 UUID box. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the xml box with bad xml + # Length = 28, id is 'xml '. + write_buffer = struct.pack('>I4s', int(28), b'xml ') + tfile.write(write_buffer) + + write_buffer = 'this is a test' + write_buffer = write_buffer.encode() + tfile.write(write_buffer) + + # Get the rest of the input file. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + @classmethod + def tearDownClass(cls): + os.unlink(cls._bad_xml_file) + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_invalid_xml_box_warning(self): + """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 info from xml box with bad xml.""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + jp2k = Jp2k(self._bad_xml_file) + + self.assertEqual(jp2k.box[3].box_id, 'xml ') + self.assertEqual(jp2k.box[3].offset, 77) + self.assertEqual(jp2k.box[3].length, 28) + self.assertIsNone(jp2k.box[3].xml) + + +@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") +class TestBadButRecoverableXmlFile(unittest.TestCase): + """Test suite for XML box that is bad, but we can still recover the XML.""" + + @classmethod + def setUpClass(cls): + """Setup a JP2 file with bad bytes preceding the XML. We only need + to do this once per class rather than once per test. + """ + jp2file = glymur.data.nemo() + 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 UUID box. + write_buffer = ifile.read(77) + tfile.write(write_buffer) + + # Write the xml box with bad xml + # Length = 64, id is 'xml '. + write_buffer = struct.pack('>I4s', int(64), b'xml ') + tfile.write(write_buffer) + + # Write out 8 bad bytes. + write_buffer = b'\x00\x00\x07\x90xml ' + tfile.write(write_buffer) + + # Write out 48 good bytes constituting the XML payload. + write_buffer = b'' + tfile.write(write_buffer) + write_buffer = b'this is a test' + tfile.write(write_buffer) + + # Get the rest of the input file. + write_buffer = ifile.read() + tfile.write(write_buffer) + tfile.flush() + + @classmethod + def tearDownClass(cls): + os.unlink(cls._bad_xml_file) + + @unittest.skipIf(sys.hexversion < 0x03020000, + "Uses features introduced in 3.2.") + def test_bad_xml_box_warning(self): + """Should warn in case of bad XML""" + with self.assertWarns(UserWarning): + Jp2k(self._bad_xml_file) + + def test_recover_from_bad_xml(self): + """Should be able to recover info from xml box with bad xml.""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + jp2 = Jp2k(self._bad_xml_file) + + self.assertEqual(jp2.box[3].box_id, 'xml ') + self.assertEqual(jp2.box[3].offset, 77) + self.assertEqual(jp2.box[3].length, 64) + self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), + b'this is a test') + + diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 4f06745..0a7f509 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -55,129 +55,6 @@ def load_tests(loader, tests, ignore): return tests -@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") -@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. - """ - 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 UUID box. - write_buffer = ifile.read(77) - tfile.write(write_buffer) - - # Write the xml box with bad xml - # Length = 28, id is 'xml '. - write_buffer = struct.pack('>I4s', int(28), b'xml ') - tfile.write(write_buffer) - - write_buffer = 'this is a test' - write_buffer = write_buffer.encode() - tfile.write(write_buffer) - - # Get the rest of the input file. - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - @classmethod - def tearDownClass(cls): - os.unlink(cls._bad_xml_file) - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_invalid_xml_box_warning(self): - """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 info from xml box with bad xml.""" - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - jp2k = Jp2k(self._bad_xml_file) - - self.assertEqual(jp2k.box[3].box_id, 'xml ') - self.assertEqual(jp2k.box[3].offset, 77) - self.assertEqual(jp2k.box[3].length, 28) - self.assertIsNone(jp2k.box[3].xml) - - -@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") -class TestBadButRecoverableXmlFile(unittest.TestCase): - """Test suite for XML box that is bad, but we can still recover the XML.""" - - @classmethod - def setUpClass(cls): - """Setup a JP2 file with bad bytes preceding the XML. We only need - to do this once per class rather than once per test. - """ - jp2file = glymur.data.nemo() - 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 UUID box. - write_buffer = ifile.read(77) - tfile.write(write_buffer) - - # Write the xml box with bad xml - # Length = 64, id is 'xml '. - write_buffer = struct.pack('>I4s', int(64), b'xml ') - tfile.write(write_buffer) - - # Write out 8 bad bytes. - write_buffer = b'\x00\x00\x07\x90xml ' - tfile.write(write_buffer) - - # Write out 48 good bytes constituting the XML payload. - write_buffer = b'this is a test' - tfile.write(write_buffer) - - # Get the rest of the input file. - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - @classmethod - def tearDownClass(cls): - os.unlink(cls._bad_xml_file) - - @unittest.skipIf(sys.hexversion < 0x03020000, - "Uses features introduced in 3.2.") - def test_bad_xml_box_warning(self): - """Should warn in case of bad XML""" - with self.assertWarns(UserWarning): - Jp2k(self._bad_xml_file) - - def test_recover_from_bad_xml(self): - """Should be able to recover info from xml box with bad xml.""" - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - jp2 = Jp2k(self._bad_xml_file) - - self.assertEqual(jp2.box[3].box_id, 'xml ') - self.assertEqual(jp2.box[3].offset, 77) - self.assertEqual(jp2.box[3].length, 64) - self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), - b'this is a test') - - @unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and not OPENJP2_IS_V2_OFFICIAL, "Missing openjp2 library version 2.0+.") From d124549df1221fcabd73ef2219714b40e2538e6a Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 19 Sep 2013 21:43:31 -0400 Subject: [PATCH 086/122] Prepping for 0.5.1 release. --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 35b355e..03d3b94 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Sep 19, 2013 - v0.5.1 Added more resiliency to XML box parsing. Fixed tests + that failed if OPJ_DATA_ROOT not set. + Sep 16, 2013 - v0.5.0 Added write support for 1.5.x. Added version module. Aug 21, 2013 - v0.4.1 Fixed segfault with openjpeg 1.x when rlevel=-1 diff --git a/docs/source/conf.py b/docs/source/conf.py index 6b9eb18..25d944f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.0' +release = '0.5.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 740d610..274a222 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.0" +version = "0.5.1rc1" _sv = LooseVersion(version) version_tuple = _sv.version From ce23560062423abfedd0c153f71202f1bab800a1 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 19 Sep 2013 21:45:59 -0400 Subject: [PATCH 087/122] Finalizing 0.5.1 release. --- glymur/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/version.py b/glymur/version.py index 274a222..8b1eb50 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.1rc1" +version = "0.5.1" _sv = LooseVersion(version) version_tuple = _sv.version From 008048b25ecaa0c42b1fe51b958a43bee3bc18ae Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 23 Sep 2013 12:33:05 -0400 Subject: [PATCH 088/122] Removed some "skipIf" conditions that no loger seem relevant. #121 --- glymur/test/test_jp2box.py | 8 -------- glymur/test/test_jp2k.py | 2 -- glymur/test/test_opj_suite_neg.py | 7 +++---- glymur/test/test_printing.py | 4 ++-- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 71dbd72..0d265b0 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -57,11 +57,7 @@ def load_tests(loader, tests, ignore): return tests -@unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, - "Requires v2.0.0+ in order to run.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") class TestChannelDefinition(unittest.TestCase): """Test suite for channel definition boxes.""" @@ -505,8 +501,6 @@ class TestColourSpecificationBox(unittest.TestCase): approximation=approx) -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") class TestAppend(unittest.TestCase): """Tests for append method.""" @@ -599,8 +593,6 @@ class TestAppend(unittest.TestCase): jp2.append(uuidbox) -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") class TestWrap(unittest.TestCase): """Tests for wrap method.""" diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index bbf551b..b6390c4 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -56,8 +56,6 @@ def load_tests(loader, tests, ignore): @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") class TestJp2kBadXmlFile(unittest.TestCase): """Test suite for bad XML box situations""" diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index 66115a2..2e7e3b2 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -12,6 +12,7 @@ seem like logical negative tests to add. # pylint: disable=F0401 import os +import re import sys import tempfile @@ -22,16 +23,14 @@ else: import numpy as np -from .fixtures import read_image, NO_READ_BACKEND, NO_READ_BACKEND_MSG from .fixtures import OPJ_DATA_ROOT, opj_data_file from glymur import Jp2k import glymur -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") -@unittest.skipIf(NO_READ_BACKEND, NO_READ_BACKEND_MSG) +@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), + "Functionality not implemented for 1.3, 1.4") @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_OPJ_DATA_ROOT environment variable not set") class TestSuiteNegative(unittest.TestCase): diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 8591b1b..81f998e 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -36,8 +36,8 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 0, + "Missing library.") class TestPrintingNeedsLib(unittest.TestCase): """These tests require the library, mostly in order to just setup the test. """ From bf9833550452b29b3e29e5ee3b91d4df95c4b3e3 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 23 Sep 2013 16:09:01 -0400 Subject: [PATCH 089/122] Fixed some tests failing in 2.0 official. --- glymur/test/test_jp2box.py | 3 +++ glymur/test/test_jp2k.py | 5 +++-- glymur/test/test_opj_suite.py | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 0d265b0..15aed61 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -57,6 +57,9 @@ def load_tests(loader, tests, ignore): return tests +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] > 1 and + OPENJP2_IS_V2_OFFICIAL, + "Not supported until 2.0+.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") class TestChannelDefinition(unittest.TestCase): """Test suite for channel definition boxes.""" diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index b6390c4..394f9e5 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -117,7 +117,8 @@ class TestJp2kBadXmlFile(unittest.TestCase): self.assertIsNone(jp2k.box[3].xml) -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None and not OPENJP2_IS_V2_OFFICIAL, +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] > 1 and + OPENJP2_IS_V2_OFFICIAL, "Missing openjp2 library version 2.0+.") class TestJp2k_2_1(unittest.TestCase): """Test suite for version 2.0+ of openjpeg software""" @@ -201,7 +202,7 @@ class TestJp2k_2_0(unittest.TestCase): def tearDown(self): pass - @unittest.skipIf(not OPENJP2_IS_V2_OFFICIAL, + @unittest.skipIf(OPENJP2_IS_V2_OFFICIAL, "Behavior is specific to 2.0 official.") @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") def test_extra_components_on_v2(self): diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index a5daf3e..3543e01 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -6724,6 +6724,8 @@ class TestSuiteDump(unittest.TestCase): [8, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 10]) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Feature not supported in glymur until openjpeg 2.0") class TestSuite_bands(unittest.TestCase): @@ -6853,6 +6855,8 @@ class TestSuite_bands(unittest.TestCase): self.assertTrue(True) +@unittest.skipIf(OPJ_DATA_ROOT is None, + "OPJ_DATA_ROOT environment variable not set") @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 1, "Tests not passing until 2.0") class TestSuite2point0(unittest.TestCase): From e20cf07a8a6f50c325f2ca60e81f28e5db43e2db Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 23 Sep 2013 16:22:49 -0400 Subject: [PATCH 090/122] Requalified on 1.3. #121 --- glymur/test/test_jp2box.py | 2 +- glymur/test/test_jp2k.py | 2 +- glymur/test/test_printing.py | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 15aed61..ff69f75 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -57,7 +57,7 @@ def load_tests(loader, tests, ignore): return tests -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] > 1 and +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or OPENJP2_IS_V2_OFFICIAL, "Not supported until 2.0+.") @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 394f9e5..ed78870 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -117,7 +117,7 @@ class TestJp2kBadXmlFile(unittest.TestCase): self.assertIsNone(jp2k.box[3].xml) -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] > 1 and +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or OPENJP2_IS_V2_OFFICIAL, "Missing openjp2 library version 2.0+.") class TestJp2k_2_1(unittest.TestCase): diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 81f998e..2694aa2 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -10,6 +10,7 @@ # pylint: disable=R0904 import os +import re import struct import sys import tempfile @@ -36,8 +37,8 @@ from .fixtures import OPJ_DATA_ROOT, opj_data_file @unittest.skipIf(os.name == "nt", "Temporary file issue on window.") -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] == 0, - "Missing library.") +@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), + "Need at least 1.5 in order to write jp2 files.") class TestPrintingNeedsLib(unittest.TestCase): """These tests require the library, mostly in order to just setup the test. """ From c7372552721454f101a7fefc0a55307f18d190e9 Mon Sep 17 00:00:00 2001 From: jevans Date: Mon, 23 Sep 2013 20:17:15 -0400 Subject: [PATCH 091/122] Releasing 0.5.2 --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 03d3b94..7d437d3 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Sep 23, 2013 - v0.5.2 Fixed some teests that have been failing since 0.5. + under various edge cases. + Sep 19, 2013 - v0.5.1 Added more resiliency to XML box parsing. Fixed tests that failed if OPJ_DATA_ROOT not set. diff --git a/docs/source/conf.py b/docs/source/conf.py index 25d944f..75404f9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.1' +release = '0.5.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 8b1eb50..4386ba6 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.1" +version = "0.5.2" _sv = LooseVersion(version) version_tuple = _sv.version From 275e0fbd6bc166d61a7e6d2a7a79c2a509a672e4 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 24 Sep 2013 10:00:17 -0400 Subject: [PATCH 092/122] Bad test suite removed. Closes #122 The channel definition test suite looks like it was mistakenly pasted into another part of the file but not correctly skipped when the library version was 1.3. --- glymur/test/test_jp2box.py | 260 ------------------------------------- 1 file changed, 260 deletions(-) diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index bbdbb30..ef62460 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -56,7 +56,6 @@ def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite('glymur.jp2box')) return tests - @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or OPENJP2_IS_V2_OFFICIAL, "Not supported until 2.0+.") @@ -744,264 +743,5 @@ class TestJpxBoxes(unittest.TestCase): self.assertEqual(len(jpx.box[5].box), 0) -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") -class TestChannelDefinition(unittest.TestCase): - """Test suite for channel definition boxes.""" - - @classmethod - def setUpClass(cls): - """Need a one_plane plane image for greyscale testing.""" - j2k = Jp2k(glymur.data.goodstuff()) - data = j2k.read() - # Write the first component back out to file. - with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - grey_j2k = Jp2k(tfile.name, 'wb') - grey_j2k.write(data[:, :, 0]) - cls.one_plane = tfile.name - # Write the first two components back out to file. - with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - grey_j2k = Jp2k(tfile.name, 'wb') - grey_j2k.write(data[:, :, 0:1]) - cls.two_planes = tfile.name - # Write four components back out to file. - with tempfile.NamedTemporaryFile(suffix=".j2k", delete=False) as tfile: - rgba_jp2 = Jp2k(tfile.name, 'wb') - shape = (data.shape[0], data.shape[1], 1) - alpha = np.zeros((shape), dtype=data.dtype) - data4 = np.concatenate((data, alpha), axis=2) - rgba_jp2.write(data4) - cls.four_planes = tfile.name - - @classmethod - def tearDownClass(cls): - os.unlink(cls.one_plane) - os.unlink(cls.two_planes) - os.unlink(cls.four_planes) - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - j2k = Jp2k(self.j2kfile) - codestream = j2k.get_codestream() - height = codestream.segment[1].ysiz - width = codestream.segment[1].xsiz - num_components = len(codestream.segment[1].xrsiz) - - self.jp2b = JPEG2000SignatureBox() - self.ftyp = FileTypeBox() - self.jp2h = JP2HeaderBox() - self.jp2c = ContiguousCodestreamBox() - self.ihdr = ImageHeaderBox(height=height, width=width, - num_components=num_components) - self.colr_rgb = ColourSpecificationBox(colorspace=glymur.core.SRGB) - self.colr_gr = ColourSpecificationBox(colorspace=glymur.core.GREYSCALE) - - def tearDown(self): - pass - - def test_cdef_no_inputs(self): - """channel_type and association are required inputs.""" - with self.assertRaises(IOError): - glymur.jp2box.ChannelDefinitionBox() - - def test_rgb_with_index(self): - """Just regular RGB.""" - j2k = Jp2k(self.j2kfile) - channel_type = [COLOR, COLOR, COLOR] - association = [RED, GREEN, BLUE] - cdef = glymur.jp2box.ChannelDefinitionBox(index=[0, 1, 2], - channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_rgb, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - - jp2 = Jp2k(tfile.name) - jp2h = jp2.box[2] - boxes = [box.box_id for box in jp2h.box] - self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) - self.assertEqual(jp2h.box[2].index, (0, 1, 2)) - self.assertEqual(jp2h.box[2].channel_type, - (COLOR, COLOR, COLOR)) - self.assertEqual(jp2h.box[2].association, - (RED, GREEN, BLUE)) - - def test_rgb(self): - """Just regular RGB, but don't supply the optional index.""" - j2k = Jp2k(self.j2kfile) - channel_type = [COLOR, COLOR, COLOR] - association = [RED, GREEN, BLUE] - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_rgb, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - - jp2 = Jp2k(tfile.name) - jp2h = jp2.box[2] - boxes = [box.box_id for box in jp2h.box] - self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) - self.assertEqual(jp2h.box[2].index, (0, 1, 2)) - self.assertEqual(jp2h.box[2].channel_type, - (COLOR, COLOR, COLOR)) - self.assertEqual(jp2h.box[2].association, - (RED, GREEN, BLUE)) - - def test_rgba(self): - """Just regular RGBA.""" - j2k = Jp2k(self.four_planes) - channel_type = (COLOR, COLOR, COLOR, OPACITY) - association = (RED, GREEN, BLUE, WHOLE_IMAGE) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_rgb, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - - jp2 = Jp2k(tfile.name) - jp2h = jp2.box[2] - boxes = [box.box_id for box in jp2h.box] - self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) - self.assertEqual(jp2h.box[2].index, (0, 1, 2, 3)) - self.assertEqual(jp2h.box[2].channel_type, channel_type) - self.assertEqual(jp2h.box[2].association, association) - - def test_bad_rgba(self): - """R, G, and B must be specified.""" - j2k = Jp2k(self.four_planes) - channel_type = (COLOR, COLOR, OPACITY, OPACITY) - association = (RED, GREEN, BLUE, WHOLE_IMAGE) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_rgb, cdef] - self.jp2h.box = boxes - 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_grey(self): - """Just regular greyscale.""" - j2k = Jp2k(self.one_plane) - channel_type = (COLOR,) - association = (GREY,) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_gr, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - - jp2 = Jp2k(tfile.name) - jp2h = jp2.box[2] - boxes = [box.box_id for box in jp2h.box] - self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) - self.assertEqual(jp2h.box[2].index, (0,)) - self.assertEqual(jp2h.box[2].channel_type, channel_type) - self.assertEqual(jp2h.box[2].association, association) - - def test_grey_alpha(self): - """Just regular greyscale plus alpha.""" - j2k = Jp2k(self.two_planes) - channel_type = (COLOR, OPACITY) - association = (GREY, WHOLE_IMAGE) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_gr, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - j2k.wrap(tfile.name, boxes=boxes) - - jp2 = Jp2k(tfile.name) - jp2h = jp2.box[2] - boxes = [box.box_id for box in jp2h.box] - self.assertEqual(boxes, ['ihdr', 'colr', 'cdef']) - self.assertEqual(jp2h.box[2].index, (0, 1)) - self.assertEqual(jp2h.box[2].channel_type, channel_type) - self.assertEqual(jp2h.box[2].association, association) - - def test_bad_grey_alpha(self): - """A greyscale image with alpha layer must specify a color channel""" - j2k = Jp2k(self.two_planes) - - channel_type = (OPACITY, OPACITY) - association = (GREY, WHOLE_IMAGE) - - # This cdef box - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - boxes = [self.ihdr, self.colr_gr, cdef] - self.jp2h.box = boxes - boxes = [self.jp2b, self.ftyp, self.jp2h, self.jp2c] - with tempfile.NamedTemporaryFile(suffix=".jp2") as tfile: - with self.assertRaises((OSError, IOError)): - j2k.wrap(tfile.name, boxes=boxes) - - def test_only_one_cdef_in_jp2h(self): - """There can only be one channel definition box in the jp2 header.""" - j2k = Jp2k(self.j2kfile) - - channel_type = (COLOR, COLOR, COLOR) - association = (RED, GREEN, BLUE) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - - boxes = [self.ihdr, cdef, self.colr_rgb, cdef] - self.jp2h.box = boxes - - 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_jp2h(self): - """need cdef in jp2h""" - j2k = Jp2k(self.j2kfile) - boxes = [self.ihdr, self.colr_rgb] - self.jp2h.box = boxes - - channel_type = (COLOR, COLOR, COLOR) - association = (RED, GREEN, BLUE) - cdef = glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - - 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_type = (COLOR, COLOR, 3) - association = (RED, GREEN, BLUE) - with self.assertRaises(IOError): - 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. - """ - channel_type = (COLOR, COLOR) - association = (RED, GREEN, BLUE) - with self.assertRaises(IOError): - glymur.jp2box.ChannelDefinitionBox(channel_type=channel_type, - association=association) - - if __name__ == "__main__": unittest.main() From 6eba0a579463fbb1fb12a3880728f8aef07c6fc4 Mon Sep 17 00:00:00 2001 From: jevans Date: Tue, 24 Sep 2013 18:24:55 -0400 Subject: [PATCH 093/122] Prepping 0.5.3 release. --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 7d437d3..838f4a3 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Sep 24, 2013 - v0.5.3 Removed a duplicated channel definition test in + test_jp2box that could cause a segfault in 1.3 if not properly skipped. + Sep 23, 2013 - v0.5.2 Fixed some teests that have been failing since 0.5. under various edge cases. diff --git a/docs/source/conf.py b/docs/source/conf.py index 75404f9..78eb705 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.2' +release = '0.5.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 4386ba6..5a2fe1e 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.2" +version = "0.5.3" _sv = LooseVersion(version) version_tuple = _sv.version From b1edfbe29621cf9cfd9ac0e92f1e6fe4d9390c27 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 25 Sep 2013 10:34:16 -0400 Subject: [PATCH 094/122] When working with 3.3, really should catch both IOError and OSError. On 2.7, the mac seems to issue an IOError, other platforms an OSError. Just catch both. #123 --- glymur/test/test_jp2k.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 2519246..ec174bf 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -146,7 +146,7 @@ class TestJp2k_2_0(unittest.TestCase): 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(OSError): + with self.assertRaises((IOError, OSError)): with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: j = Jp2k(tfile.name, 'wb') data = np.zeros((128, 128, 4), dtype=np.uint8) From b50f19bed32c467d64a2701c6d941d8df2452c4c Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 25 Sep 2013 20:55:40 -0400 Subject: [PATCH 095/122] Prepping 0.5.4 release. --- CHANGES.txt | 2 ++ docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 838f4a3..d0e2bce 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,5 @@ +Sep 24, 2013 - v0.5.4 Fixed test error restricted to v2.0. + Sep 24, 2013 - v0.5.3 Removed a duplicated channel definition test in test_jp2box that could cause a segfault in 1.3 if not properly skipped. diff --git a/docs/source/conf.py b/docs/source/conf.py index 78eb705..e01cc91 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.3' +release = '0.5.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 5a2fe1e..5e4122b 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,7 +13,7 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 -version = "0.5.3" +version = "0.5.4" _sv = LooseVersion(version) version_tuple = _sv.version From 8cc04b2651439bf13934bebc1cd4f58b06f5db63 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 28 Sep 2013 11:50:27 -0400 Subject: [PATCH 096/122] Updated docs for openjpeg r2347. --- docs/source/detailed_installation.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 7fb5b3b..3f42275 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -13,7 +13,7 @@ both read and write JPEG 2000 files, but you may wish to install version 2.0 or the 2.0+ version from OpenJPEG's development trunk for better performance. If you do that, you should compile it as a shared library (named *openjp2* instead of *openjpeg*) from the developmental source that you can retrieve -via subversion. As of this time of writing, svn revision 2345 works. +via subversion. As of this time of writing, svn revision 2347 works. You should also download the test data for the purpose of configuring and running OpenJPEG's test suite, check their instructions for all this. You should set the **OPJ_DATA_ROOT** environment variable for the purpose @@ -25,9 +25,10 @@ of running Glymur's test suite. :: Glymur uses ctypes to access the openjp2/openjpeg libraries, and because ctypes accesses libraries in a platform-dependent manner, it is recommended that you create a configuration file to help Glymur properly find -the openjpeg or openjp2 libraries (linux users don't need to bother if you are -using OpenJPEG as provided by your package manager). The configuration -format is the same as used by Python's configparser module, i.e. :: +the openjpeg or openjp2 libraries (linux users don't need to bother with this +if you are using OpenJPEG as provided by your package manager). The +configuration format is the same as used by Python's configparser module, +i.e. :: [library] openjp2: /opt/openjp2-svn/lib/libopenjp2.so From 813f5f3a03ac6a108c0e5781b5c1e43a4e11940a Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 30 Sep 2013 14:30:45 -0400 Subject: [PATCH 097/122] Moved argtypes and restype into each respective function. #125 --- glymur/lib/openjp2.py | 251 +++++++++++++++++++++--------------------- 1 file changed, 125 insertions(+), 126 deletions(-) diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 8c0ae32..43e4e61 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -553,119 +553,6 @@ class CodestreamInfoV2(ctypes.Structure): # information regarding tiles inside of image ("tile_info", ctypes.POINTER(TileInfoV2))] -# Restrict the input and output argument types for each function used in the -# API. -if OPENJP2 is not None: - OPENJP2.opj_create_compress.restype = CODEC_TYPE - OPENJP2.opj_create_compress.argtypes = [CODEC_FORMAT_TYPE] - - OPENJP2.opj_create_decompress.argtypes = [CODEC_FORMAT_TYPE] - OPENJP2.opj_create_decompress.restype = CODEC_TYPE - - ARGTYPES = [CODEC_TYPE, STREAM_TYPE_P, ctypes.POINTER(ImageType)] - OPENJP2.opj_decode.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, ctypes.c_uint32, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_uint32, - STREAM_TYPE_P] - OPENJP2.opj_decode_tile_data.argtypes = ARGTYPES - - ARGTYPES = [ctypes.POINTER(ctypes.POINTER(CodestreamInfoV2))] - OPENJP2.opj_destroy_cstr_info.argtypes = ARGTYPES - OPENJP2.opj_destroy_cstr_info.restype = ctypes.c_void_p - - ARGTYPES = [CODEC_TYPE, STREAM_TYPE_P] - OPENJP2.opj_encode.argtypes = ARGTYPES - - OPENJP2.opj_get_cstr_info.argtypes = [CODEC_TYPE] - OPENJP2.opj_get_cstr_info.restype = ctypes.POINTER(CodestreamInfoV2) - - ARGTYPES = [CODEC_TYPE, - STREAM_TYPE_P, - ctypes.POINTER(ImageType), - ctypes.c_uint32] - OPENJP2.opj_get_decoded_tile.argtypes = ARGTYPES - - ARGTYPES = [ctypes.c_uint32, - ctypes.POINTER(ImageComptParmType), - COLOR_SPACE_TYPE] - OPENJP2.opj_image_create.argtypes = ARGTYPES - OPENJP2.opj_image_create.restype = ctypes.POINTER(ImageType) - - ARGTYPES = [ctypes.c_uint32, - ctypes.POINTER(ImageComptParmType), - COLOR_SPACE_TYPE] - OPENJP2.opj_image_tile_create.argtypes = ARGTYPES - OPENJP2.opj_image_tile_create.restype = ctypes.POINTER(ImageType) - - OPENJP2.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)] - - ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE, - ctypes.POINTER(ctypes.POINTER(ImageType))] - OPENJP2.opj_read_header.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, - STREAM_TYPE_P, - ctypes.POINTER(ctypes.c_uint32), - ctypes.POINTER(ctypes.c_uint32), - ctypes.POINTER(ctypes.c_int32), - ctypes.POINTER(ctypes.c_int32), - ctypes.POINTER(ctypes.c_int32), - ctypes.POINTER(ctypes.c_int32), - ctypes.POINTER(ctypes.c_uint32), - ctypes.POINTER(BOOL_TYPE)] - OPENJP2.opj_read_tile_header.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, ctypes.POINTER(ImageType), ctypes.c_int32, - ctypes.c_int32, ctypes.c_int32, ctypes.c_int32] - OPENJP2.opj_set_decode_area.argtypes = ARGTYPES - - ARGTYPES = [ctypes.POINTER(CompressionParametersType)] - OPENJP2.opj_set_default_encoder_parameters.argtypes = ARGTYPES - - ARGTYPES = [ctypes.POINTER(DecompressionParametersType)] - OPENJP2.opj_set_default_decoder_parameters.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, ctypes.c_void_p, ctypes.c_void_p] - OPENJP2.opj_set_error_handler.argtypes = ARGTYPES - OPENJP2.opj_set_info_handler.argtypes = ARGTYPES - OPENJP2.opj_set_warning_handler.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, ctypes.POINTER(DecompressionParametersType)] - OPENJP2.opj_setup_decoder.argtypes = ARGTYPES - - ARGTYPES = [CODEC_TYPE, - ctypes.POINTER(CompressionParametersType), - ctypes.POINTER(ImageType)] - OPENJP2.opj_setup_encoder.argtypes = ARGTYPES - - if hasattr(OPENJP2, 'opj_stream_create_default_file_stream_v3'): - ARGTYPES = [ctypes.c_char_p, ctypes.c_int32] - OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = ARGTYPES - OPENJP2.opj_stream_create_default_file_stream_v3.restype = STREAM_TYPE_P - OPENJP2.opj_stream_destroy_v3.argtypes = [STREAM_TYPE_P] - else: - ARGTYPES = [ctypes.c_void_p, ctypes.c_int32] - OPENJP2.opj_stream_create_default_file_stream.argtypes = ARGTYPES - OPENJP2.opj_stream_create_default_file_stream.restype = STREAM_TYPE_P - OPENJP2.opj_stream_destroy.argtypes = [STREAM_TYPE_P] - - ARGTYPES = [CODEC_TYPE, ctypes.POINTER(ImageType), STREAM_TYPE_P] - OPENJP2.opj_start_compress.argtypes = ARGTYPES - - OPENJP2.opj_end_compress.argtypes = [CODEC_TYPE, STREAM_TYPE_P] - OPENJP2.opj_end_decompress.argtypes = [CODEC_TYPE, STREAM_TYPE_P] - - OPENJP2.opj_destroy_codec.argtypes = [CODEC_TYPE] - - ARGTYPES = [CODEC_TYPE, - ctypes.c_uint32, - ctypes.POINTER(ctypes.c_uint8), - ctypes.c_uint32, - STREAM_TYPE_P] - OPENJP2.opj_write_tile.argtypes = ARGTYPES - def check_error(status): """Set a generic function as the restype attribute of all OpenJPEG @@ -684,19 +571,6 @@ def check_error(status): else: raise IOError("OpenJPEG function failure.") -# These library functions all return an error status. Circumvent that and -# force them to raise an exception. -FCNS = ['opj_decode', 'opj_decode_tile_data', 'opj_end_compress', - 'opj_encode', 'opj_end_decompress', 'opj_get_decoded_tile', - 'opj_read_header', 'opj_read_tile_header', 'opj_set_decode_area', - 'opj_set_error_handler', 'opj_set_info_handler', - 'opj_set_warning_handler', - 'opj_setup_decoder', 'opj_setup_encoder', 'opj_start_compress', - 'opj_write_tile'] -if OPENJP2 is not None: - for fcn in FCNS: - setattr(getattr(OPENJP2, fcn), 'restype', check_error) - def create_compress(codec_format): """Creates a J2K/JP2 compress structure. @@ -712,6 +586,9 @@ def create_compress(codec_format): ------- codec : Reference to CODEC_TYPE instance. """ + OPENJP2.opj_create_compress.restype = CODEC_TYPE + OPENJP2.opj_create_compress.argtypes = [CODEC_FORMAT_TYPE] + codec = OPENJP2.opj_create_compress(codec_format) return codec @@ -735,6 +612,10 @@ def decode(codec, stream, image): RuntimeError If the OpenJPEG library routine opj_decode fails. """ + OPENJP2.opj_decode.argtypes = [CODEC_TYPE, STREAM_TYPE_P, + ctypes.POINTER(ImageType)] + OPENJP2.opj_decode.restype = check_error + OPENJP2.opj_decode(codec, stream, image) @@ -761,6 +642,13 @@ def decode_tile_data(codec, tidx, data, data_size, stream): RuntimeError If the OpenJPEG library routine opj_decode fails. """ + OPENJP2.opj_decode_tile_data.argtypes = [CODEC_TYPE, + ctypes.c_uint32, + ctypes.POINTER(ctypes.c_uint8), + ctypes.c_uint32, + STREAM_TYPE_P] + OPENJP2.opj_decode_tile_data.restype = check_error + datap = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)) OPENJP2.opj_decode_tile_data(codec, ctypes.c_uint32(tidx), @@ -784,6 +672,9 @@ def create_decompress(codec_format): ------- codec : Reference to CODEC_TYPE instance. """ + OPENJP2.opj_create_decompress.argtypes = [CODEC_FORMAT_TYPE] + OPENJP2.opj_create_decompress.restype = CODEC_TYPE + codec = OPENJP2.opj_create_decompress(codec_format) return codec @@ -798,6 +689,7 @@ def destroy_codec(codec): codec : CODEC_TYPE Decompressor handle to destroy. """ + OPENJP2.opj_destroy_codec.argtypes = [CODEC_TYPE] OPENJP2.opj_destroy_codec(codec) @@ -818,6 +710,9 @@ def encode(codec, stream): RuntimeError If the OpenJPEG library routine opj_encode fails. """ + OPENJP2.opj_encode.argtypes = [CODEC_TYPE, STREAM_TYPE_P] + OPENJP2.opj_encode.restype = check_error + OPENJP2.opj_encode(codec, stream) @@ -836,6 +731,9 @@ def get_cstr_info(codec): cstr_info_p : CodestreamInfoV2 Reference to codestream information. """ + OPENJP2.opj_get_cstr_info.argtypes = [CODEC_TYPE] + OPENJP2.opj_get_cstr_info.restype = ctypes.POINTER(CodestreamInfoV2) + cstr_info_p = OPENJP2.opj_get_cstr_info(codec) return cstr_info_p @@ -861,6 +759,12 @@ def get_decoded_tile(codec, stream, imagep, tile_index): RuntimeError If the OpenJPEG library routine opj_get_decoded_tile fails. """ + OPENJP2.opj_get_decoded_tile.argtypes = [CODEC_TYPE, + STREAM_TYPE_P, + ctypes.POINTER(ImageType), + ctypes.c_uint32] + OPENJP2.opj_get_decoded_tile.restype = check_error + OPENJP2.opj_get_decoded_tile(codec, stream, imagep, tile_index) @@ -874,6 +778,10 @@ def destroy_cstr_info(cstr_info_p): cstr_info_p : CodestreamInfoV2 pointer Pointer to codestream info structure. """ + ARGTYPES = [ctypes.POINTER(ctypes.POINTER(CodestreamInfoV2))] + OPENJP2.opj_destroy_cstr_info.argtypes = ARGTYPES + OPENJP2.opj_destroy_cstr_info.restype = ctypes.c_void_p + OPENJP2.opj_destroy_cstr_info(ctypes.byref(cstr_info_p)) @@ -894,6 +802,8 @@ def end_compress(codec, stream): RuntimeError If the OpenJPEG library routine opj_end_compress fails. """ + OPENJP2.opj_end_compress.argtypes = [CODEC_TYPE, STREAM_TYPE_P] + OPENJP2.opj_end_compress.restype = check_error OPENJP2.opj_end_compress(codec, stream) @@ -914,6 +824,8 @@ def end_decompress(codec, stream): RuntimeError If the OpenJPEG library routine opj_end_decompress fails. """ + OPENJP2.opj_end_decompress.argtypes = [CODEC_TYPE, STREAM_TYPE_P] + OPENJP2.opj_end_decompress.restype = check_error OPENJP2.opj_end_decompress(codec, stream) @@ -927,6 +839,8 @@ def image_destroy(image): image : ImageType pointer Image resource to be disposed. """ + OPENJP2.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)] + OPENJP2.opj_image_destroy(image) @@ -947,6 +861,11 @@ def image_create(comptparms, clrspc): image : ImageType Reference to ImageType instance. """ + OPENJP2.opj_image_create.argtypes = [ctypes.c_uint32, + ctypes.POINTER(ImageComptParmType), + COLOR_SPACE_TYPE] + OPENJP2.opj_image_create.restype = ctypes.POINTER(ImageType) + image = OPENJP2.opj_image_create(len(comptparms), comptparms, clrspc) @@ -970,6 +889,12 @@ def image_tile_create(comptparms, clrspc): image : ImageType Reference to ImageType instance. """ + ARGTYPES = [ctypes.c_uint32, + ctypes.POINTER(ImageComptParmType), + COLOR_SPACE_TYPE] + OPENJP2.opj_image_tile_create.argtypes = ARGTYPES + OPENJP2.opj_image_tile_create.restype = ctypes.POINTER(ImageType) + image = OPENJP2.opj_image_tile_create(len(comptparms), comptparms, clrspc) @@ -998,6 +923,11 @@ def read_header(stream, codec): RuntimeError If the OpenJPEG library routine opj_read_header fails. """ + ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE, + ctypes.POINTER(ctypes.POINTER(ImageType))] + OPENJP2.opj_read_header.argtypes + OPENJP2.opj_read_header.restype = check_error + imagep = ctypes.POINTER(ImageType)() OPENJP2.opj_read_header(stream, codec, ctypes.byref(imagep)) return imagep @@ -1035,6 +965,19 @@ def read_tile_header(codec, stream): RuntimeError If the OpenJPEG library routine opj_read_tile_header fails. """ + ARGTYPES = [CODEC_TYPE, + STREAM_TYPE_P, + ctypes.POINTER(ctypes.c_uint32), + ctypes.POINTER(ctypes.c_uint32), + ctypes.POINTER(ctypes.c_int32), + ctypes.POINTER(ctypes.c_int32), + ctypes.POINTER(ctypes.c_int32), + ctypes.POINTER(ctypes.c_int32), + ctypes.POINTER(ctypes.c_uint32), + ctypes.POINTER(BOOL_TYPE)] + OPENJP2.opj_read_tile_header.argtypes = ARGTYPES + OPENJP2.opj_read_tile_header.restype = check_error + tile_index = ctypes.c_uint32() data_size = ctypes.c_uint32() col0 = ctypes.c_int32() @@ -1086,6 +1029,14 @@ def set_decode_area(codec, image, start_x=0, start_y=0, end_x=0, end_y=0): RuntimeError If the OpenJPEG library routine opj_set_decode_area fails. """ + OPENJP2.opj_set_decode_area.argtypes = [CODEC_TYPE, + ctypes.POINTER(ImageType), + ctypes.c_int32, + ctypes.c_int32, + ctypes.c_int32, + ctypes.c_int32] + OPENJP2.opj_set_decode_area.restype = check_error + OPENJP2.opj_set_decode_area(codec, image, ctypes.c_int32(start_x), ctypes.c_int32(start_y), @@ -1103,6 +1054,9 @@ def set_default_decoder_parameters(): dparam : DecompressionParametersType Decompression parameters. """ + ARGTYPES = [ctypes.POINTER(DecompressionParametersType)] + OPENJP2.opj_set_default_decoder_parameters.argtypes = ARGTYPES + dparams = DecompressionParametersType() OPENJP2.opj_set_default_decoder_parameters(ctypes.byref(dparams)) return dparams @@ -1138,6 +1092,9 @@ def set_default_encoder_parameters(): cparameters : CompressionParametersType Compression parameters. """ + ARGTYPES = [ctypes.POINTER(CompressionParametersType)] + OPENJP2.opj_set_default_encoder_parameters.argtypes = ARGTYPES + cparams = CompressionParametersType() OPENJP2.opj_set_default_encoder_parameters(ctypes.byref(cparams)) return cparams @@ -1162,6 +1119,10 @@ def set_error_handler(codec, handler, data=None): RuntimeError If the OpenJPEG library routine opj_set_error_handler fails. """ + OPENJP2.opj_set_error_handler.argtypes = [CODEC_TYPE, + ctypes.c_void_p, + ctypes.c_void_p] + OPENJP2.opj_set_error_handler.restype = check_error OPENJP2.opj_set_error_handler(codec, handler, data) @@ -1184,6 +1145,10 @@ def set_info_handler(codec, handler, data=None): RuntimeError If the OpenJPEG library routine opj_set_info_handler fails. """ + OPENJP2.opj_set_info_handler.argtypes = [CODEC_TYPE, + ctypes.c_void_p, + ctypes.c_void_p] + OPENJP2.opj_set_info_handler.restype = check_error OPENJP2.opj_set_info_handler(codec, handler, data) @@ -1206,6 +1171,11 @@ def set_warning_handler(codec, handler, data=None): RuntimeError If the OpenJPEG library routine opj_set_warning_handler fails. """ + OPENJP2.opj_set_warning_handler.argtypes = [CODEC_TYPE, + ctypes.c_void_p, + ctypes.c_void_p] + OPENJP2.opj_set_warning_handler.restype = check_error + OPENJP2.opj_set_warning_handler(codec, handler, data) @@ -1226,6 +1196,10 @@ def setup_decoder(codec, dparams): RuntimeError If the OpenJPEG library routine opj_setup_decoder fails. """ + ARGTYPES = [CODEC_TYPE, ctypes.POINTER(DecompressionParametersType)] + OPENJP2.opj_setup_decoder.argtypes = ARGTYPES + OPENJP2.opj_setup_decoder.restype = check_error + OPENJP2.opj_setup_decoder(codec, ctypes.byref(dparams)) @@ -1249,6 +1223,11 @@ def setup_encoder(codec, cparams, image): RuntimeError If the OpenJPEG library routine opj_setup_encoder fails. """ + ARGTYPES = [CODEC_TYPE, + ctypes.POINTER(CompressionParametersType), + ctypes.POINTER(ImageType)] + OPENJP2.opj_setup_encoder.argtypes = ARGTYPES + OPENJP2.opj_setup_encoder.restype = check_error OPENJP2.opj_setup_encoder(codec, ctypes.byref(cparams), image) @@ -1271,6 +1250,11 @@ def start_compress(codec, image, stream): RuntimeError If the OpenJPEG library routine opj_start_compress fails. """ + OPENJP2.opj_start_compress.argtypes = [CODEC_TYPE, + ctypes.POINTER(ImageType), + STREAM_TYPE_P] + OPENJP2.opj_start_compress.restype = check_error + OPENJP2.opj_start_compress(codec, image, stream) @@ -1292,6 +1276,9 @@ def stream_create_default_file_stream(fptr, isa_read_stream): stream : stream_t An OpenJPEG file stream. """ + ARGTYPES = [ctypes.c_void_p, ctypes.c_int32] + OPENJP2.opj_stream_create_default_file_stream.argtypes = ARGTYPES + OPENJP2.opj_stream_create_default_file_stream.restype = STREAM_TYPE_P read_stream = 1 if isa_read_stream else 0 stream = OPENJP2.opj_stream_create_default_file_stream(fptr, read_stream) return stream @@ -1315,6 +1302,9 @@ def stream_create_default_file_stream_v3(fname, isa_read_stream): stream : stream_t An OpenJPEG file stream. """ + ARGTYPES = [ctypes.c_char_p, ctypes.c_int32] + OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = ARGTYPES + OPENJP2.opj_stream_create_default_file_stream_v3.restype = STREAM_TYPE_P read_stream = 1 if isa_read_stream else 0 file_argument = ctypes.c_char_p(fname.encode()) stream = OPENJP2.opj_stream_create_default_file_stream_v3(file_argument, @@ -1332,6 +1322,7 @@ def stream_destroy(stream): stream : STREAM_TYPE_P The file stream. """ + OPENJP2.opj_stream_destroy.argtypes = [STREAM_TYPE_P] OPENJP2.opj_stream_destroy(stream) @@ -1345,6 +1336,7 @@ def stream_destroy_v3(stream): stream : STREAM_TYPE_P The file stream. """ + OPENJP2.opj_stream_destroy_v3.argtypes = [STREAM_TYPE_P] OPENJP2.opj_stream_destroy_v3(stream) @@ -1371,6 +1363,13 @@ def write_tile(codec, tile_index, data, data_size, stream): RuntimeError If the OpenJPEG library routine opj_write_tile fails. """ + OPENJP2.opj_write_tile.argtypes = [CODEC_TYPE, + ctypes.c_uint32, + ctypes.POINTER(ctypes.c_uint8), + ctypes.c_uint32, + STREAM_TYPE_P] + OPENJP2.opj_write_tile.restype = check_error + datap = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)) OPENJP2.opj_write_tile(codec, ctypes.c_uint32(int(tile_index)), From 89c086370641cf08e1663b933f42cc3534847352 Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 30 Sep 2013 14:55:20 -0400 Subject: [PATCH 098/122] openjp2's decode_tile_data handler was returning the codec. It should not. #125 --- glymur/lib/openjp2.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 43e4e61..82b0cfe 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -655,7 +655,6 @@ def decode_tile_data(codec, tidx, data, data_size, stream): datap, ctypes.c_uint32(data_size), stream) - return codec def create_decompress(codec_format): @@ -690,6 +689,7 @@ def destroy_codec(codec): Decompressor handle to destroy. """ OPENJP2.opj_destroy_codec.argtypes = [CODEC_TYPE] + OPENJP2.opj_destroy_codec.restype = ctypes.c_void_p OPENJP2.opj_destroy_codec(codec) @@ -840,6 +840,7 @@ def image_destroy(image): Image resource to be disposed. """ OPENJP2.opj_image_destroy.argtypes = [ctypes.POINTER(ImageType)] + OPENJP2.opj_image_destroy.restype = ctypes.c_void_p OPENJP2.opj_image_destroy(image) @@ -1056,6 +1057,7 @@ def set_default_decoder_parameters(): """ ARGTYPES = [ctypes.POINTER(DecompressionParametersType)] OPENJP2.opj_set_default_decoder_parameters.argtypes = ARGTYPES + OPENJP2.opj_set_default_decoder_parameters.restype = ctypes.c_void_p dparams = DecompressionParametersType() OPENJP2.opj_set_default_decoder_parameters(ctypes.byref(dparams)) @@ -1094,6 +1096,7 @@ def set_default_encoder_parameters(): """ ARGTYPES = [ctypes.POINTER(CompressionParametersType)] OPENJP2.opj_set_default_encoder_parameters.argtypes = ARGTYPES + OPENJP2.opj_set_default_encoder_parameters.restype = ctypes.c_void_p cparams = CompressionParametersType() OPENJP2.opj_set_default_encoder_parameters(ctypes.byref(cparams)) @@ -1323,6 +1326,7 @@ def stream_destroy(stream): The file stream. """ OPENJP2.opj_stream_destroy.argtypes = [STREAM_TYPE_P] + OPENJP2.opj_stream_destroy.restype = ctypes.c_void_p OPENJP2.opj_stream_destroy(stream) @@ -1337,6 +1341,7 @@ def stream_destroy_v3(stream): The file stream. """ OPENJP2.opj_stream_destroy_v3.argtypes = [STREAM_TYPE_P] + OPENJP2.opj_stream_destroy_v3.restype = ctypes.c_void_p OPENJP2.opj_stream_destroy_v3(stream) From 9422bccffb6a1806652b9e05470c30c5cb4b5c16 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 1 Oct 2013 10:55:28 -0400 Subject: [PATCH 099/122] Forgot to actually set argtypes for openjp2 read_header function. #125 --- glymur/lib/openjp2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/lib/openjp2.py b/glymur/lib/openjp2.py index 82b0cfe..f056db0 100644 --- a/glymur/lib/openjp2.py +++ b/glymur/lib/openjp2.py @@ -926,7 +926,7 @@ def read_header(stream, codec): """ ARGTYPES = [STREAM_TYPE_P, CODEC_TYPE, ctypes.POINTER(ctypes.POINTER(ImageType))] - OPENJP2.opj_read_header.argtypes + OPENJP2.opj_read_header.argtypes = ARGTYPES OPENJP2.opj_read_header.restype = check_error imagep = ctypes.POINTER(ImageType)() From 1fc1a635e0aeb1c88d35a23c04c14d1f131b13c7 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 1 Oct 2013 10:56:27 -0400 Subject: [PATCH 100/122] Fixed typo. --- glymur/test/test_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glymur/test/test_config.py b/glymur/test/test_config.py index 16af663..32f067a 100644 --- a/glymur/test/test_config.py +++ b/glymur/test/test_config.py @@ -124,7 +124,7 @@ class TestConfig(unittest.TestCase): @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") def test_write_without_library(self): - """Don't have openjp2 library? Must error out. + """Don't have openjpeg libraries? Must error out. """ data = glymur.Jp2k(self.j2kfile).read() with patch('glymur.lib.openjp2.OPENJP2', new=None): From c65ae274a95320a44463f986ca05d375d8b03481 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 2 Oct 2013 15:32:38 -0400 Subject: [PATCH 101/122] Minor tweaks. --- docs/source/detailed_installation.rst | 9 +++++---- docs/source/how_do_i.rst | 16 ++++++++-------- docs/source/introduction.rst | 22 ++++++---------------- glymur/version.py | 1 + 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/docs/source/detailed_installation.rst b/docs/source/detailed_installation.rst index 3f42275..3e4d9dc 100644 --- a/docs/source/detailed_installation.rst +++ b/docs/source/detailed_installation.rst @@ -7,8 +7,8 @@ Most users won't need to read this! You've been warned... Glymur Configuration '''''''''''''''''''''' -The default glymur installation process relies upon OpenJPEG version -1.X being properly installed on your system. If you have version 1.5 you can +The default glymur installation process relies upon OpenJPEG +being properly installed on your system. If you have version 1.5 you can both read and write JPEG 2000 files, but you may wish to install version 2.0 or the 2.0+ version from OpenJPEG's development trunk for better performance. If you do that, you should compile it as a shared library (named *openjp2* @@ -35,7 +35,7 @@ i.e. :: This assumes, of course, that you've installed OpenJPEG into /opt/openjp2-svn on a linux system. The location of the configuration file -is platform-dependent (of course). If you use either linux or mac, the path +can vary as well (of course). If you use either linux or mac, the path to the configuration file would normally be :: $HOME/.config/glymur/glymurrc @@ -71,7 +71,8 @@ packages/RPMs/ports/whatever without going through pip. Mac OS X -------- All the necessary packages are available to use glymur with Python 2.6, 2.7, -and 3.3 via MacPorts. You should install the following set of ports: +and 3.3 via MacPorts. For python 3.3, you should install the following set of +ports: * python33 * py33-numpy diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index cc0b227..212862d 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -3,7 +3,7 @@ How do I...? ------------ -read the lowest resolution thumbnail? +... read the lowest resolution thumbnail? ===================================== Printing the Jp2k object should reveal the number of resolutions (look in the COD segment section), but you can take a shortcut by supplying -1 as the @@ -14,7 +14,7 @@ resolution level. :: >>> j = glymur.Jp2k(file) >>> thumbnail = j.read(rlevel=-1) -display metadata? +... display metadata? ================= There are two ways. From the unix command line, the script *jp2dump* is available. :: @@ -34,7 +34,7 @@ codestream box, only the main header is printed. It is possible to print >>> print(j.get_codestream()) -add XML metadata? +... add XML metadata? ================= You can append any number of XML boxes to a JP2 file (not to a raw codestream). Consider the following XML file `data.xml` : :: @@ -66,7 +66,7 @@ The **append** method can add an XML box as shown below:: >>> jp2.append(xmlbox) >>> print(jp2) -add metadata in a more general fashion? +... add metadata in a more general fashion? ======================================= An existing raw codestream (or JP2 file) can be wrapped (re-wrapped) in a user-defined set of JP2 boxes. To get just a minimal JP2 jacket on the @@ -157,18 +157,18 @@ to add metadata, you should keep in mind that **wrap** produces a new JP2 file, while **append** modifies an existing file and is currently limited to XML boxes. -create an image with an alpha layer? +... create an image with an alpha layer? ==================================== OpenJPEG can create JP2 files with more than 3 components (requires -the development version), but by default, any extra components are +the development version of OpenJPEG), but by default, any extra components are not described as such. In order to do so, we need to rewrap such an image in a set of boxes that includes a channel definition box. This example is based on SciPy example code found at http://scipy-lectures.github.io/advanced/image_processing/#basic-manipulations . -Instead of a circular mask, however, we'll make it an ellipse since the source -image isn't square. +Instead of a circular mask we'll make it an ellipse since the source +image isn't square. :: >>> import numpy as np >>> import glymur diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 37dcb5a..e1a3b3b 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -4,9 +4,8 @@ Glymur: a Python interface for JPEG 2000 **Glymur** is an interface to the OpenJPEG library which allows one to read and write JPEG 2000 files from within Python. -Glymur supports both reading and writing of JPEG 2000 images. Writing -JPEG 2000 images is currently limited to images that can fit in memory, -however. +Glymur supports both reading and writing of JPEG 2000 images, but writing +JPEG 2000 images is currently limited to images that can fit in memory Of particular focus is retrieval of metadata. Reading Exif UUIDs is supported, as is reading XMP UUIDs as the XMP data packet is just XML. There is @@ -24,11 +23,10 @@ only supported with the 1.5 or better, however, and the trunk/development version is strongly recommended. For more information about OpenJPEG, please consult http://www.openjpeg.org. -If you use MacPorts on the mac or if you have a sufficiently recent -version of Linux, your package manager should already provide you -with a version of OpenJPEG 1.X with which glymur can already use -for read-only purposes. If your platform is windows, I suggest -using the windows installers provided to you by the OpenJPEG +If you use MacPorts or if you have a sufficiently recent version of +Linux, your package manager should already provide you with a version of +OpenJPEG 1.X which glymur can already use. If your platform is windows, +I suggest using the windows installers provided to you by the OpenJPEG folks at https://code.google.com/p/openjpeg/downloads/list . Glymur Installation @@ -47,13 +45,5 @@ line, so you should adjust your **$PATH** to take advantage of it. For example, if you install with pip's `--user` option on linux :: - $ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages $ export PATH=$HOME/.local/bin:$PATH -You can run the tests from within python as follows:: - - >>> import glymur - >>> glymur.runtests() - -Many tests are currently skipped, but the The important thing is whether or -not any tests fail. diff --git a/glymur/version.py b/glymur/version.py index 5e4122b..9603798 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -6,6 +6,7 @@ # # License: MIT +import pdb; pdb.set_trace() import sys import numpy as np from distutils.version import LooseVersion From 62db4f7e0fb2ef7c2b4a6141f5b5ec77e4ca5589 Mon Sep 17 00:00:00 2001 From: John Evans Date: Wed, 2 Oct 2013 17:18:12 -0400 Subject: [PATCH 102/122] Mistakenly committed with a pdb breakpoint set. --- glymur/version.py | 1 - 1 file changed, 1 deletion(-) diff --git a/glymur/version.py b/glymur/version.py index 9603798..5e4122b 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -6,7 +6,6 @@ # # License: MIT -import pdb; pdb.set_trace() import sys import numpy as np from distutils.version import LooseVersion From 7697230a591d3a3cf409e17ea83d2a03dd9c1057 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 07:59:24 -0400 Subject: [PATCH 103/122] Change openjpeg version from base system version to tarball version 1.5. #126 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4898e65..beff6ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,10 @@ python: before_install: - sudo apt-get update -qq - - sudo apt-get install -qq libopenjpeg2 - sudo apt-get install -qq python-numpy - sudo apt-get install -qq python3-numpy + - wget http://openjpeg.googlecode.com/files/openjpeg-1.5.0-Linux-x86_64.tar.gz + - sudo tar -xvf openjpeg-1.5.0-Linux-x86_64.tar.gz --strip-components=1 -C / # command to install dependencies install: "pip install -r travis-requirements.txt --use-mirrors" From 9bff3731168de3d38eefa01dd42c4b20c5bbc75d Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 08:06:38 -0400 Subject: [PATCH 104/122] Use verbose to be sure of what tests are running. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index beff6ab..0eb0319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ before_install: install: "pip install -r travis-requirements.txt --use-mirrors" # command to run tests -script: "python -m unittest discover" +script: "python -m unittest discover -v" notifications: email: "john.g.evans.ne@gmail.com" From c5900755ca55e6584b424c16c8075916a6fdabe1 Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 10:02:16 -0400 Subject: [PATCH 105/122] Removing verbose option. Closes #126 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0eb0319..beff6ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ before_install: install: "pip install -r travis-requirements.txt --use-mirrors" # command to run tests -script: "python -m unittest discover -v" +script: "python -m unittest discover" notifications: email: "john.g.evans.ne@gmail.com" From 6edb59ac7e876f1e0e0050f581ddbf86f350fe2d Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 10:10:36 -0400 Subject: [PATCH 106/122] Very stupid, cannot import glymur in setup.py! #127 The install requirements have not yet necessarily been taken care of yet, so pip installs will break on 2.6 and 2.7, probably due to contextlib2. --- setup.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 8d62705..b5b62aa 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,8 @@ kwargs = {'name': 'Glymur', 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'scripts': ['bin/jp2dump'], 'license': 'MIT', - 'test_suite': 'glymur.test'} + 'test_suite': 'glymur.test', + 'version': '0.5.4'} instllrqrs = ['numpy>=1.4.1'] if sys.hexversion < 0x03030000: @@ -38,7 +39,4 @@ clssfrs = ["Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules"] kwargs['classifiers'] = clssfrs -import glymur -kwargs['version'] = glymur.version.version - setup(**kwargs) From fe3964c212bbc08aff42d42cc08c8b2a7a72262e Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 10:41:12 -0400 Subject: [PATCH 107/122] Add some information about how many tests should be expected to skip. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index beff6ab..cd80fa2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,8 @@ before_install: install: "pip install -r travis-requirements.txt --use-mirrors" # command to run tests +# 2.7 should skip no more than 342 tests +# 3.3 should skip no more than 339 tests script: "python -m unittest discover" notifications: From 244fb26d9643144e772f950dd9d6e0373fa64d6e Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 10:41:41 -0400 Subject: [PATCH 108/122] Change the way versioning is included in setup.py #127 Using regular expressions should work so long as the pattern in glymur/version.py does not change. --- glymur/version.py | 2 ++ setup.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/glymur/version.py b/glymur/version.py index 5e4122b..04004fd 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -13,6 +13,8 @@ from distutils.version import LooseVersion from .lib import openjpeg as opj from .lib import openjp2 as opj2 +# Do not change the format of this next line! Doing so risks breaking +# setup.py version = "0.5.4" _sv = LooseVersion(version) version_tuple = _sv.version diff --git a/setup.py b/setup.py index b5b62aa..89e69f7 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ from setuptools import setup, find_packages +import os +import re import sys kwargs = {'name': 'Glymur', @@ -12,8 +14,7 @@ kwargs = {'name': 'Glymur', 'package_data': {'glymur': ['data/*.jp2', 'data/*.j2k']}, 'scripts': ['bin/jp2dump'], 'license': 'MIT', - 'test_suite': 'glymur.test', - 'version': '0.5.4'} + 'test_suite': 'glymur.test'} instllrqrs = ['numpy>=1.4.1'] if sys.hexversion < 0x03030000: @@ -39,4 +40,11 @@ clssfrs = ["Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules"] kwargs['classifiers'] = clssfrs +# Get the version string. Cannot do this by importing glymur! +version_file = os.path.join('glymur', 'version.py') +with open('glymur/version.py', 'rt') as fptr: + contents = fptr.read() + match = re.search('version\s*=\s*"(?P\d*.\d*.\d*.*)"\n', contents) + kwargs['version'] = match.group('version') + setup(**kwargs) From 3b6d34531dc4b3438b5581605105bb40d47e367d Mon Sep 17 00:00:00 2001 From: John Evans Date: Thu, 3 Oct 2013 11:09:58 -0400 Subject: [PATCH 109/122] Finalizing for 0.5.5 release. --- CHANGES.txt | 4 +++- docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d0e2bce..30387a6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,9 +1,11 @@ +Oct 03, 2013 - v0.5.5 Fixed pip install error introduced in 0.5.0. + Sep 24, 2013 - v0.5.4 Fixed test error restricted to v2.0. Sep 24, 2013 - v0.5.3 Removed a duplicated channel definition test in test_jp2box that could cause a segfault in 1.3 if not properly skipped. -Sep 23, 2013 - v0.5.2 Fixed some teests that have been failing since 0.5. +Sep 23, 2013 - v0.5.2 Fixed some tests that have been failing since 0.5. under various edge cases. Sep 19, 2013 - v0.5.1 Added more resiliency to XML box parsing. Fixed tests diff --git a/docs/source/conf.py b/docs/source/conf.py index e01cc91..f847e68 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.4' +release = '0.5.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 04004fd..192859f 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -15,7 +15,7 @@ from .lib import openjp2 as opj2 # Do not change the format of this next line! Doing so risks breaking # setup.py -version = "0.5.4" +version = "0.5.5" _sv = LooseVersion(version) version_tuple = _sv.version From 86d799bfb75b8eca4e311ac1065b5b53d61f352f Mon Sep 17 00:00:00 2001 From: John Evans Date: Mon, 7 Oct 2013 16:28:33 -0400 Subject: [PATCH 110/122] Reorganized the jp2k tests, dropped several duplicated ones. Closes #128 --- glymur/test/test_jp2k.py | 954 +++++++++++++++------------------------ 1 file changed, 365 insertions(+), 589 deletions(-) diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index ec174bf..636ea9a 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -55,598 +55,11 @@ def load_tests(loader, tests, ignore): return tests -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or - OPENJP2_IS_V2_OFFICIAL, - "Missing openjp2 library version 2.0+.") -class TestJp2k_2_1(unittest.TestCase): - """Test suite for version 2.0+ of openjpeg software""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - @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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 2) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @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) - j.write(data) - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 4) - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - def test_openjpeg_library_message(self): - """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 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. - tfile.write(data[0:3179]) - - # Make the DY bytes of the SIZ segment zero. That means that - # a subsampling factor is zero, which is illegal. - tfile.write(b'\x00') - tfile.write(data[3180:3182]) - tfile.write(b'\x00') - tfile.write(data[3184:3186]) - tfile.write(b'\x00') - - tfile.write(data[3186:]) - tfile.flush() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(tfile.name) - regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ - Invalid\svalues\sfor\scomp\s=\s0\s+ - :\sdx=1\sdy=0''', re.VERBOSE) - if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) - else: - with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) - - -@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, - "Not tested for 1.x") -class TestJp2k_2_0(unittest.TestCase): - """Test suite requiring at least version 2.0""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - @unittest.skipIf(not OPENJP2_IS_V2_OFFICIAL, - "Behavior is specific to 2.0 official.") - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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, OSError)): - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - data = np.zeros((128, 128, 4), dtype=np.uint8) - j.write(data) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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): - 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_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) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - j.write(data) - - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: - - # Offset of the codestream is where we start. - 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'. - write_buffer = struct.pack('>I4s', int(56), b'asoc') - tfile2.write(write_buffer) - - # Write the contained label box - 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 '. - write_buffer = struct.pack('>I4s', int(35), b'xml ') - tfile2.write(write_buffer) - - write_buffer = 'this is a test' - write_buffer = write_buffer.encode() - tfile2.write(write_buffer) - - # Now append the codestream. - tfile2.write(codestream) - tfile2.flush() - - jasoc = Jp2k(tfile2.name) - self.assertEqual(jasoc.box[3].box_id, 'asoc') - self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') - self.assertEqual(jasoc.box[3].box[0].label, 'label') - self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') - - -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is None, - "Missing openjp2 library.") -class TestJp2k_1_x(unittest.TestCase): - """Test suite for versions up to 1.5.1 of openjpeg but no further""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - def test_rlevel_max(self): - """Verify that rlevel=-1 gets us the lowest resolution image""" - j = Jp2k(self.j2kfile) - thumbnail1 = j.read(rlevel=-1) - thumbnail2 = j.read(rlevel=5) - np.testing.assert_array_equal(thumbnail1, thumbnail2) - self.assertEqual(thumbnail1.shape, (25, 15, 3)) - - def test_bad_area_parameter(self): - """Should error out appropriately if given a bad area parameter.""" - j = Jp2k(self.jp2file) - with self.assertRaises(IOError): - # Start corner must be >= 0 - j.read(area=(-1, -1, 1, 1)) - with self.assertRaises(IOError): - # End corner must be > 0 - j.read(area=(10, 10, 0, 0)) - with self.assertRaises(IOError): - # End corner must be >= start corner - j.read(area=(10, 10, 8, 8)) - - def test_rlevel_too_high(self): - """Should error out appropriately if reduce level too high""" - j = Jp2k(self.jp2file) - with self.assertRaises(IOError): - j.read(rlevel=6) - - def test_jp2_boxes(self): - """Verify the boxes of a JP2 file. Basic jp2 test.""" - jp2k = Jp2k(self.jp2file) - - # top-level boxes - self.assertEqual(len(jp2k.box), 6) - - self.assertEqual(jp2k.box[0].box_id, 'jP ') - self.assertEqual(jp2k.box[0].offset, 0) - self.assertEqual(jp2k.box[0].length, 12) - self.assertEqual(jp2k.box[0].longname, 'JPEG 2000 Signature') - - self.assertEqual(jp2k.box[1].box_id, 'ftyp') - self.assertEqual(jp2k.box[1].offset, 12) - self.assertEqual(jp2k.box[1].length, 20) - self.assertEqual(jp2k.box[1].longname, 'File Type') - - self.assertEqual(jp2k.box[2].box_id, 'jp2h') - self.assertEqual(jp2k.box[2].offset, 32) - self.assertEqual(jp2k.box[2].length, 45) - self.assertEqual(jp2k.box[2].longname, 'JP2 Header') - - self.assertEqual(jp2k.box[3].box_id, 'uuid') - self.assertEqual(jp2k.box[3].offset, 77) - self.assertEqual(jp2k.box[3].length, 638) - - self.assertEqual(jp2k.box[4].box_id, 'uuid') - self.assertEqual(jp2k.box[4].offset, 715) - self.assertEqual(jp2k.box[4].length, 2412) - - self.assertEqual(jp2k.box[5].box_id, 'jp2c') - self.assertEqual(jp2k.box[5].offset, 3127) - self.assertEqual(jp2k.box[5].length, 1132296) - - # jp2h super box - self.assertEqual(len(jp2k.box[2].box), 2) - - self.assertEqual(jp2k.box[2].box[0].box_id, 'ihdr') - self.assertEqual(jp2k.box[2].box[0].offset, 40) - self.assertEqual(jp2k.box[2].box[0].length, 22) - self.assertEqual(jp2k.box[2].box[0].longname, 'Image Header') - self.assertEqual(jp2k.box[2].box[0].height, 1456) - self.assertEqual(jp2k.box[2].box[0].width, 2592) - self.assertEqual(jp2k.box[2].box[0].num_components, 3) - self.assertEqual(jp2k.box[2].box[0].bits_per_component, 8) - self.assertEqual(jp2k.box[2].box[0].signed, False) - self.assertEqual(jp2k.box[2].box[0].compression, 7) - self.assertEqual(jp2k.box[2].box[0].colorspace_unknown, False) - self.assertEqual(jp2k.box[2].box[0].ip_provided, False) - - self.assertEqual(jp2k.box[2].box[1].box_id, 'colr') - self.assertEqual(jp2k.box[2].box[1].offset, 62) - self.assertEqual(jp2k.box[2].box[1].length, 15) - self.assertEqual(jp2k.box[2].box[1].longname, 'Colour Specification') - self.assertEqual(jp2k.box[2].box[1].precedence, 0) - self.assertEqual(jp2k.box[2].box[1].approximation, 0) - self.assertEqual(jp2k.box[2].box[1].colorspace, glymur.core.SRGB) - self.assertIsNone(jp2k.box[2].box[1].icc_profile) - - def test_j2k_box(self): - """A J2K/J2C file must not have any boxes.""" - # Verify that a J2K file has no boxes. - jp2k = Jp2k(self.j2kfile) - self.assertEqual(len(jp2k.box), 0) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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. - 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). - 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) - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - jp2k = Jp2k(tfile.name) - - self.assertEqual(jp2k.box[5].box_id, 'jp2c') - self.assertEqual(jp2k.box[5].offset, 3127) - self.assertEqual(jp2k.box[5].length, 1133427 + 8) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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. - baseline_jp2 = Jp2k(self.jp2file) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - with open(self.jp2file, 'rb') as ifile: - # Everything up until the jp2c box. - write_buffer = ifile.read(588458) - tfile.write(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) - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - new_jp2 = Jp2k(tfile.name) - - # The top level boxes in each file should match. - for j in range(len(baseline_jp2.box)): - self.assertEqual(new_jp2.box[j].box_id, - baseline_jp2.box[j].box_id) - self.assertEqual(new_jp2.box[j].offset, - baseline_jp2.box[j].offset) - self.assertEqual(new_jp2.box[j].length, - baseline_jp2.box[j].length) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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') - - # The code block dimensions are given as rows x columns. - j.write(data, cbsize=(16, 32)) - - codestream = j.get_codestream() - - # Code block size is reported as XY in the codestream. - self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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): - data = np.zeros((128, 128, 2, 2), dtype=np.uint8) - j.write(data) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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): - 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""" - with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: - j = Jp2k(tfile.name, 'wb') - 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) - j.write(data, colorspace='rgb') - self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) - - @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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @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) - j.write(data, colorspace='grey') - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - 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) - j.write(data, colorspace='gray') - self.assertEqual(j.box[2].box[0].height, 128) - self.assertEqual(j.box[2].box[0].width, 128) - self.assertEqual(j.box[2].box[0].num_components, 3) - self.assertEqual(j.box[2].box[1].colorspace, - glymur.core.GREYSCALE) - - def test_specify_ycc(self): - """Should reject YCC""" - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - j = Jp2k(tfile.name, 'wb') - 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_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: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, mct=False) - actdata = ofile.read() - np.testing.assert_array_equal(actdata, expdata) - - 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.""" - j2k = Jp2k(self.j2kfile) - expdata = j2k.read() - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - with self.assertRaises(IOError): - ofile.write(expdata[:, :, 0], mct=True) - - @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) - with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: - ofile = Jp2k(tfile.name, 'wb') - ofile.write(expdata, prog='CPRL') - actdata = ofile.read() - np.testing.assert_array_equal(actdata, expdata) - - codestream = ofile.get_codestream() - self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) - - -@unittest.skipIf(glymur.lib.openjp2.OPENJP2 is not None, - "Don't bother if openjp2 is present.") -@unittest.skipIf(glymur.lib.openjpeg.OPENJPEG is None, - "Missing openjpeg library.") -class TestJp2k15(unittest.TestCase): - """Test suite for openjpeg 1.x, not appropriate for 2.x""" - - def setUp(self): - self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() - - def tearDown(self): - pass - - def test_area(self): - """Area option not allowed for 1.5.1. - """ - j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(area=(0, 0, 100, 100)) - - def test_tile(self): - """tile option not allowed for 1.5.1. - """ - j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(tile=0) - - def test_layer(self): - """layer option not allowed for 1.5.1. - """ - j2k = Jp2k(self.j2kfile) - with self.assertRaises(TypeError): - j2k.read(layer=1) - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(glymur.version.openjpeg_version_tuple[1] < 5, - "Writing only supported with openjpeg version 1.5+.") - 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): - 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_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. - write_buffer = ifile.read(77) - tfile.write(write_buffer) - - # Write the xml box - # Length = 36, id is 'xml '. - write_buffer = struct.pack('>I4s', int(36), b'xml ') - tfile.write(write_buffer) - - write_buffer = 'this is a test' + chr(0) - write_buffer = write_buffer.encode() - tfile.write(write_buffer) - - # Get the rest of the input file. - write_buffer = ifile.read() - tfile.write(write_buffer) - tfile.flush() - - jp2k = Jp2k(tfile.name) - - self.assertEqual(jp2k.box[3].box_id, 'xml ') - self.assertEqual(jp2k.box[3].offset, 77) - self.assertEqual(jp2k.box[3].length, 36) - self.assertEqual(ET.tostring(jp2k.box[3].xml.getroot()), - b'this is a test') - - @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") - @unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, - "Segfault on official v1.x series.") - def test_openjpeg_library_message(self): - """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 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. - tfile.write(data[0:3179]) - - # Make the DY bytes of the SIZ segment zero. That means that - # a subsampling factor is zero, which is illegal. - tfile.write(b'\x00') - tfile.write(data[3180:3182]) - tfile.write(b'\x00') - tfile.write(data[3184:3186]) - tfile.write(b'\x00') - - tfile.write(data[3186:]) - tfile.flush() - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - j = Jp2k(tfile.name) - regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ - Invalid\svalues\sfor\scomp\s=\s0\s+ - :\sdx=1\sdy=0''', re.VERBOSE) - if sys.hexversion < 0x03020000: - with self.assertRaisesRegexp((IOError, OSError), regexp): - j.read(rlevel=1) - else: - with self.assertRaisesRegex((IOError, OSError), regexp): - j.read(rlevel=1) - - class TestJp2k(unittest.TestCase): """Test suite for openjpeg software starting at 1.3""" + # These tests should be run by just about all configuration. + def setUp(self): self.jp2file = glymur.data.nemo() self.j2kfile = glymur.data.goodstuff() @@ -985,5 +398,368 @@ class TestJp2k(unittest.TestCase): self.assertFalse('Make' in exif['Image'].keys()) +@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version), + "Requires at least version 1.5") +class TestJp2k_write(unittest.TestCase): + """Write tests, can be run by versions 1.5+""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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') + + # The code block dimensions are given as rows x columns. + j.write(data, cbsize=(16, 32)) + + codestream = j.get_codestream() + + # Code block size is reported as XY in the codestream. + self.assertEqual(tuple(codestream.segment[2].spcod[5:7]), (3, 2)) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + data = np.zeros((128, 128, 2, 2), dtype=np.uint8) + j.write(data) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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""" + with tempfile.NamedTemporaryFile(suffix='.j2k') as tfile: + j = Jp2k(tfile.name, 'wb') + 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) + j.write(data, colorspace='rgb') + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @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) + j.write(data, colorspace='grey') + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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) + j.write(data, colorspace='gray') + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 3) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + def test_specify_ycc(self): + """Should reject YCC""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + 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_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: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, mct=False) + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + 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.""" + j2k = Jp2k(self.j2kfile) + expdata = j2k.read() + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError): + ofile.write(expdata[:, :, 0], mct=True) + + @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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + ofile.write(expdata, prog='CPRL') + actdata = ofile.read() + np.testing.assert_array_equal(actdata, expdata) + + codestream = ofile.get_codestream() + self.assertEqual(codestream.segment[2].spcod[0], glymur.core.CPRL) + + +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] >= 2, + "Negative tests only for version 1.x") +class TestJp2k_1_x(unittest.TestCase): + """Test suite for openjpeg 1.x, not appropriate for 2.x""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + def test_area(self): + """Area option not allowed for 1.x. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(area=(0, 0, 100, 100)) + + def test_tile(self): + """tile option not allowed for 1.x. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(tile=0) + + def test_layer(self): + """layer option not allowed for 1.x. + """ + j2k = Jp2k(self.j2kfile) + with self.assertRaises(TypeError): + j2k.read(layer=1) + + +@unittest.skipIf(not OPENJP2_IS_V2_OFFICIAL, + "Tests only to be run on 2.0 official.") +class TestJp2k_2_0_official(unittest.TestCase): + """Test suite to only be run on v2.0 official.""" + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_extra_components_on_v2(self): + """Can only write 4 components on 2.0+, should error out otherwise.""" + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + data = np.zeros((128, 128, 4), dtype=np.uint8) + with self.assertRaises(IOError): + j.write(data) + + +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2, + "Requires as least v2.0") +class TestJp2k_2_0(unittest.TestCase): + """Test suite requiring at least version 2.0""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + def test_bad_area_parameter(self): + """Should error out appropriately if given a bad area parameter.""" + j = Jp2k(self.jp2file) + with self.assertRaises(IOError): + # Start corner must be >= 0 + j.read(area=(-1, -1, 1, 1)) + with self.assertRaises(IOError): + # End corner must be > 0 + j.read(area=(10, 10, 0, 0)) + with self.assertRaises(IOError): + # End corner must be >= start corner + j.read(area=(10, 10, 8, 8)) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + 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): + 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_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) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + j = Jp2k(tfile.name, 'wb') + j.write(data) + + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile2: + + # Offset of the codestream is where we start. + 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'. + write_buffer = struct.pack('>I4s', int(56), b'asoc') + tfile2.write(write_buffer) + + # Write the contained label box + 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 '. + write_buffer = struct.pack('>I4s', int(35), b'xml ') + tfile2.write(write_buffer) + + write_buffer = 'this is a test' + write_buffer = write_buffer.encode() + tfile2.write(write_buffer) + + # Now append the codestream. + tfile2.write(codestream) + tfile2.flush() + + jasoc = Jp2k(tfile2.name) + self.assertEqual(jasoc.box[3].box_id, 'asoc') + self.assertEqual(jasoc.box[3].box[0].box_id, 'lbl ') + self.assertEqual(jasoc.box[3].box[0].label, 'label') + self.assertEqual(jasoc.box[3].box[1].box_id, 'xml ') + + +@unittest.skipIf(glymur.version.openjpeg_version_tuple[0] < 2 or + OPENJP2_IS_V2_OFFICIAL, + "Missing openjp2 library version 2.0+.") +class TestJp2k_2_1(unittest.TestCase): + """Only to be run in 2.0+.""" + + def setUp(self): + self.jp2file = glymur.data.nemo() + self.j2kfile = glymur.data.goodstuff() + + def tearDown(self): + pass + + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 2) + self.assertEqual(j.box[2].box[1].colorspace, + glymur.core.GREYSCALE) + + @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) + j.write(data) + self.assertEqual(j.box[2].box[0].height, 128) + self.assertEqual(j.box[2].box[0].width, 128) + self.assertEqual(j.box[2].box[0].num_components, 4) + self.assertEqual(j.box[2].box[1].colorspace, glymur.core.SRGB) + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") + def test_openjpeg_library_message(self): + """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 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. + tfile.write(data[0:3179]) + + # Make the DY bytes of the SIZ segment zero. That means that + # a subsampling factor is zero, which is illegal. + tfile.write(b'\x00') + tfile.write(data[3180:3182]) + tfile.write(b'\x00') + tfile.write(data[3184:3186]) + tfile.write(b'\x00') + + tfile.write(data[3186:]) + tfile.flush() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + j = Jp2k(tfile.name) + regexp = re.compile(r'''OpenJPEG\slibrary\serror:\s+ + Invalid\svalues\sfor\scomp\s=\s0\s+ + :\sdx=1\sdy=0''', re.VERBOSE) + if sys.hexversion < 0x03020000: + with self.assertRaisesRegexp((IOError, OSError), regexp): + j.read(rlevel=1) + else: + with self.assertRaisesRegex((IOError, OSError), regexp): + j.read(rlevel=1) + + if __name__ == "__main__": unittest.main() From f0db9dfa2d9872f4e0440c3853e6343b41bd6db2 Mon Sep 17 00:00:00 2001 From: John Evans Date: Tue, 8 Oct 2013 09:51:43 -0400 Subject: [PATCH 111/122] openjp2 write method rewritten for exitstack support. #45 --- glymur/jp2k.py | 64 +++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 00b71c2..1bd36a4 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -474,41 +474,37 @@ class Jp2k(Jp2kBox): comptparms = _populate_comptparms(img_array, cparams) - image = opj2.image_create(comptparms, colorspace) - _populate_image_struct(cparams, image, img_array) - - codec = opj2.create_compress(cparams.codec_fmt) - - info_handler = _INFO_CALLBACK if verbose else None - opj2.set_info_handler(codec, info_handler) - opj2.set_warning_handler(codec, _WARNING_CALLBACK) - opj2.set_error_handler(codec, _ERROR_CALLBACK) - - opj2.setup_encoder(codec, cparams, image) - - if _OPENJP2_IS_OFFICIAL_V2: - fptr = libc.fopen(self.filename, 'wb') - strm = opj2.stream_create_default_file_stream(fptr, False) - else: - # This routine introduced in 2.0 devel series. - strm = opj2.stream_create_default_file_stream_v3(self.filename, - False) - - # Start to clean up after ourselves. - opj2.start_compress(codec, image, strm) - opj2.encode(codec, strm) - opj2.end_compress(codec, strm) - - if _OPENJP2_IS_OFFICIAL_V2: - opj2.stream_destroy(strm) - libc.fclose(fptr) - else: - # This routine introduced in 2.0 devel series. - opj2.stream_destroy_v3(strm) - - opj2.destroy_codec(codec) - opj2.image_destroy(image) + with ExitStack() as stack: + image = opj2.image_create(comptparms, colorspace) + stack.callback(opj2.image_destroy, image) + _populate_image_struct(cparams, image, img_array) + + codec = opj2.create_compress(cparams.codec_fmt) + stack.callback(opj2.destroy_codec, codec) + + info_handler = _INFO_CALLBACK if verbose else None + opj2.set_info_handler(codec, info_handler) + opj2.set_warning_handler(codec, _WARNING_CALLBACK) + opj2.set_error_handler(codec, _ERROR_CALLBACK) + + opj2.setup_encoder(codec, cparams, image) + + if _OPENJP2_IS_OFFICIAL_V2: + fptr = libc.fopen(self.filename, 'wb') + strm = opj2.stream_create_default_file_stream(fptr, False) + stack.callback(opj2.stream_destroy, strm) + stack.callback(libc.fclose, fptr) + else: + # This routine introduced in 2.0 devel series. + strm = opj2.stream_create_default_file_stream_v3(self.filename, + False) + stack.callback(opj2.stream_destroy_v3, strm) + + opj2.start_compress(codec, image, strm) + opj2.encode(codec, strm) + opj2.end_compress(codec, strm) + # Refresh the metadata. self.parse() From d6ef966a23bbb675ac3c9cff872ac1262fef85b9 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 9 Oct 2013 20:47:50 -0400 Subject: [PATCH 112/122] Trying to have cake and eat it too. Adding 2.6 to travis matrix. --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd80fa2..eba8919 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: python python: + - "2.6" - "2.7" - "3.3" @@ -9,14 +10,15 @@ before_install: - sudo apt-get install -qq python3-numpy - wget http://openjpeg.googlecode.com/files/openjpeg-1.5.0-Linux-x86_64.tar.gz - sudo tar -xvf openjpeg-1.5.0-Linux-x86_64.tar.gz --strip-components=1 -C / + - if [ "${TRAVIS_PYTHON_VERSION::1}" == 3 ]; then export TEST_PKG=unittest2py3k; else export TEST_PKG=unittest2; fi # command to install dependencies -install: "pip install -r travis-requirements.txt --use-mirrors" +install: + - pip install $TEST_PKG + - pip install -r travis-requirements.txt --use-mirrors # command to run tests -# 2.7 should skip no more than 342 tests -# 3.3 should skip no more than 339 tests -script: "python -m unittest discover" +script: "unit2 discover" notifications: email: "john.g.evans.ne@gmail.com" From 78915c5d959ed40476c28f33cf0fab8325e04957 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 9 Oct 2013 21:00:34 -0400 Subject: [PATCH 113/122] Taking cue from tornado travis setup. Trying separate 2.6, 2.7, 3.3 setups. --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index eba8919..a7335bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,15 +10,17 @@ before_install: - sudo apt-get install -qq python3-numpy - wget http://openjpeg.googlecode.com/files/openjpeg-1.5.0-Linux-x86_64.tar.gz - sudo tar -xvf openjpeg-1.5.0-Linux-x86_64.tar.gz --strip-components=1 -C / - - if [ "${TRAVIS_PYTHON_VERSION::1}" == 3 ]; then export TEST_PKG=unittest2py3k; else export TEST_PKG=unittest2; fi # command to install dependencies install: - - pip install $TEST_PKG - - pip install -r travis-requirements.txt --use-mirrors + - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install --use-mirrors contextlib2 mock ordereddict unittest2; fi + - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors contextlib2 mock; fi # command to run tests -script: "unit2 discover" +script: + - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then unit2 discover; fi + - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then python -m unittest discover; fi + - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then python -m unittest discover; fi notifications: email: "john.g.evans.ne@gmail.com" From f5dd49cc1bf8349e5c91a1647d7efa376bfbed41 Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 9 Oct 2013 21:07:16 -0400 Subject: [PATCH 114/122] Must use pip to install numpy on python3, it would seem. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a7335bb..9434d04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ python: before_install: - sudo apt-get update -qq - sudo apt-get install -qq python-numpy - - sudo apt-get install -qq python3-numpy - wget http://openjpeg.googlecode.com/files/openjpeg-1.5.0-Linux-x86_64.tar.gz - sudo tar -xvf openjpeg-1.5.0-Linux-x86_64.tar.gz --strip-components=1 -C / @@ -15,6 +14,7 @@ before_install: install: - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install --use-mirrors contextlib2 mock ordereddict unittest2; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors contextlib2 mock; fi + - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then pip install --use-mirrors numpy; fi # command to run tests script: From b49e113d16744c1f39c2b42b47abdb801429a8ab Mon Sep 17 00:00:00 2001 From: jevans Date: Wed, 9 Oct 2013 21:15:19 -0400 Subject: [PATCH 115/122] No need for this file anymore, it's hardcoded into .travis.yml. --- travis-requirements.txt | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 travis-requirements.txt diff --git a/travis-requirements.txt b/travis-requirements.txt deleted file mode 100644 index 9dd042a..0000000 --- a/travis-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -numpy -contextlib2>=0.4.0 -mock>=1.0.1 From f6596dceb33d34aea99328a184618b3ed0dcf686 Mon Sep 17 00:00:00 2001 From: John Evans Date: Fri, 11 Oct 2013 12:01:33 -0400 Subject: [PATCH 116/122] Fixed docstring errors. Closes #129 --- glymur/jp2box.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index f05e9de..901f9e9 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -568,7 +568,7 @@ class CodestreamHeaderBox(Jp2kBox): Returns ------- - AssociationBox instance + CodestreamHeaderBox instance """ box = CodestreamHeaderBox(length=length, offset=offset) @@ -627,7 +627,7 @@ class CompositingLayerHeaderBox(Jp2kBox): Returns ------- - AssociationBox instance + CompositingLayerHeaderBox instance """ box = CompositingLayerHeaderBox(length=length, offset=offset) @@ -638,7 +638,7 @@ class CompositingLayerHeaderBox(Jp2kBox): class ComponentMappingBox(Jp2kBox): - """Container for channel identification information. + """Container for component mapping information. Attributes ---------- @@ -1637,7 +1637,7 @@ class CaptureResolutionBox(Jp2kBox): @staticmethod def parse(fptr, offset, length): - """Parse Resolution box. + """Parse CaptureResolutionBox. Parameters ---------- @@ -1694,7 +1694,7 @@ class DisplayResolutionBox(Jp2kBox): @staticmethod def parse(fptr, offset, length): - """Parse Resolution box. + """Parse display resolution box. Parameters ---------- @@ -2047,7 +2047,7 @@ class DataEntryURLBox(Jp2kBox): @staticmethod def parse(fptr, offset, length): - """Parse Data Entry URL box. + """Parse data entry URL box. Parameters ---------- From 4c0da0dd856f3cd60e39770fc30af002ef39439b Mon Sep 17 00:00:00 2001 From: John Evans Date: Sat, 12 Oct 2013 18:57:35 -0400 Subject: [PATCH 117/122] Added xml box write test with utf-8 content. #131 --- glymur/test/test_jp2box_xml.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index ba1ff15..0bd9a59 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ Test suite specifically targeting JP2 box layout. """ @@ -94,8 +95,6 @@ class TestXML(unittest.TestCase): 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 a basic XMLBox""" j2k = Jp2k(self.j2kfile) @@ -116,8 +115,26 @@ class TestXML(unittest.TestCase): self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), b'0') - @unittest.skipIf(os.name == "nt", - "Problems using NamedTemporaryFile on windows.") + def test_utf8_xml(self): + """Should be able to write/read an XMLBox with utf-8 encoding.""" + j2k = Jp2k(self.j2kfile) + + self.jp2h.box = [self.ihdr, self.colr] + + xml_header = u'' + xml_string = u'Россия' + the_xml = ET.fromstring((xml_header + xml_string).encode('utf-8')) + xmlb = glymur.jp2box.XMLBox(xml=the_xml) + self.assertEqual(ET.tostring(xmlb.xml, encoding='utf-8').decode('utf-8'), xml_string) + + 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) + self.assertEqual(ET.tostring(jp2.box[3].xml.getroot(), encoding='utf-8').decode('utf-8'), + xml_string) + def test_xml_from_file(self): """Must be able to create an XML box from an XML file.""" j2k = Jp2k(self.j2kfile) From 79d2c134c80db0dfd8a5f500e5c86d60efde8b93 Mon Sep 17 00:00:00 2001 From: jevans Date: Sat, 12 Oct 2013 21:31:11 -0400 Subject: [PATCH 118/122] XML text now constructed via utf-8, not ascii. #131 --- glymur/jp2box.py | 4 +- glymur/test/test_jp2box_xml.py | 81 +++++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index 901f9e9..f213cab 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1870,10 +1870,8 @@ class XMLBox(Jp2kBox): # Strip out any trailing nulls, as they can foul up XML parsing. text = text.rstrip(chr(0)) - # Scan for the start of the xml declaration. - try: - elt = ET.fromstring(text) + elt = ET.fromstring(text.encode('utf-8')) xml = ET.ElementTree(elt) except ParseError as parse_error: msg = 'A problem was encountered while parsing an XML box:' diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 0bd9a59..7e6980f 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -24,6 +24,16 @@ import tempfile import warnings import xml.etree.cElementTree as ET +if sys.hexversion < 0x03000000: + from StringIO import StringIO +else: + from io import StringIO + +if sys.hexversion <= 0x03030000: + from mock import patch +else: + from unittest.mock import patch + if sys.hexversion < 0x02070000: import unittest2 as unittest else: @@ -115,26 +125,6 @@ class TestXML(unittest.TestCase): self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), b'0') - def test_utf8_xml(self): - """Should be able to write/read an XMLBox with utf-8 encoding.""" - j2k = Jp2k(self.j2kfile) - - self.jp2h.box = [self.ihdr, self.colr] - - xml_header = u'' - xml_string = u'Россия' - the_xml = ET.fromstring((xml_header + xml_string).encode('utf-8')) - xmlb = glymur.jp2box.XMLBox(xml=the_xml) - self.assertEqual(ET.tostring(xmlb.xml, encoding='utf-8').decode('utf-8'), xml_string) - - 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) - self.assertEqual(ET.tostring(jp2.box[3].xml.getroot(), encoding='utf-8').decode('utf-8'), - xml_string) - def test_xml_from_file(self): """Must be able to create an XML box from an XML file.""" j2k = Jp2k(self.j2kfile) @@ -159,6 +149,56 @@ class TestXML(unittest.TestCase): self.assertEqual(neighbor.attrib['direction'], 'N') +@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") +class TestUTF8XML(unittest.TestCase): + """Test suite for UTF-8 XML boxes.""" + + def setUp(self): + """Create a JP2 file with a UTF-8 XML box.""" + self.j2kfile = glymur.data.goodstuff() + + # 'Россия' is 'Russia' in Cyrillic, not that it matters. + + xml = u""" + Россия""" + with tempfile.NamedTemporaryFile(suffix=".xml", delete=False) as tfile: + tfile.write(xml.encode('utf-8')) + tfile.flush() + self.xmlfile = tfile.name + + j2k = glymur.Jp2k(self.j2kfile) + with tempfile.NamedTemporaryFile(suffix=".jp2", delete=False) as tfile: + jp2 = j2k.wrap(tfile.name) + xmlbox = glymur.jp2box.XMLBox(filename=self.xmlfile) + jp2.append(xmlbox) + self.jp2_xml_file = tfile.name + + def tearDown(self): + os.unlink(self.xmlfile) + os.unlink(self.jp2_xml_file) + + def test_utf8_xml(self): + """Should be able to write/read an XMLBox with utf-8 encoding.""" + jp2 = Jp2k(self.jp2_xml_file) + box_xml = jp2.box[-1].xml.getroot() + box_xml_str = ET.tostring(box_xml, encoding='utf-8').decode('utf-8') + self.assertEqual(box_xml_str, + u'Россия') + + @unittest.skip("Does not print properly.") + def test_printing_utf8_xml(self): + """Should be able to print an XMLBox with utf-8 encoding.""" + jp2 = Jp2k(self.jp2_xml_file) + with patch('sys.stdout', new=StringIO()) as fake_out: + print(jp2.box[-1]) + actual = fake_out.getvalue().strip() + lines = ["XML Box (xml ) @ (115305, 39)", + " u'Россия'"] + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + + + @unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows") class TestJp2kBadXmlFile(unittest.TestCase): """Test suite for bad XML box situations""" @@ -196,7 +236,6 @@ class TestJp2kBadXmlFile(unittest.TestCase): def setUp(self): self.jp2file = glymur.data.nemo() - self.j2kfile = glymur.data.goodstuff() def tearDown(self): pass From ff97e0fb8244048d18c26206f9abea87beac290b Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 13 Oct 2013 11:40:54 -0400 Subject: [PATCH 119/122] Printing of XML and UUID boxes with non-ascii characters only fully supported in 3.x In 2.x, the XML contents will be printed as entity references instead. It's just too difficult to get both 2.x and 3.x to be entirely consistent, and so 3.x gets the preferential treatment. Closes #131. --- glymur/jp2box.py | 15 ++++++-- glymur/test/test_jp2box_xml.py | 62 ++++++++++------------------------ glymur/test/test_printing.py | 42 +++++++++++++++++++++++ 3 files changed, 71 insertions(+), 48 deletions(-) diff --git a/glymur/jp2box.py b/glymur/jp2box.py index f213cab..bf88e4d 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -2747,9 +2747,18 @@ def _pretty_print_xml(xml, level=0): """ xml = copy.deepcopy(xml) _indent(xml.getroot(), level=level) - xmltext = ET.tostring(xml.getroot()).decode('utf-8') + xmltext = ET.tostring(xml.getroot(), encoding='utf-8').decode('utf-8') # Indent it a bit. lst = [(' ' + x) for x in xmltext.split('\n')] - xml = '\n'.join(lst) - return '\n{0}'.format(xml) + try: + xml = '\n'.join(lst) + return '\n{0}'.format(xml) + except UnicodeEncodeError: + # This can happen on python 2.x if the character set contains certain + # non-ascii characters. Just print out the corresponding xml char + # entities instead. + xml = u'\n'.join(lst) + text = u'\n{0}'.format(xml) + text = text.encode('ascii', 'xmlcharrefreplace') + return text diff --git a/glymur/test/test_jp2box_xml.py b/glymur/test/test_jp2box_xml.py index 7e6980f..b875188 100644 --- a/glymur/test/test_jp2box_xml.py +++ b/glymur/test/test_jp2box_xml.py @@ -148,54 +148,26 @@ class TestXML(unittest.TestCase): self.assertEqual(neighbor.attrib['name'], 'Malaysia') self.assertEqual(neighbor.attrib['direction'], 'N') - -@unittest.skipIf(os.name == "nt", "Temporary file issue on window.") -class TestUTF8XML(unittest.TestCase): - """Test suite for UTF-8 XML boxes.""" - - def setUp(self): - """Create a JP2 file with a UTF-8 XML box.""" - self.j2kfile = glymur.data.goodstuff() - - # 'Россия' is 'Russia' in Cyrillic, not that it matters. - - xml = u""" - Россия""" - with tempfile.NamedTemporaryFile(suffix=".xml", delete=False) as tfile: - tfile.write(xml.encode('utf-8')) - tfile.flush() - self.xmlfile = tfile.name - - j2k = glymur.Jp2k(self.j2kfile) - with tempfile.NamedTemporaryFile(suffix=".jp2", delete=False) as tfile: - jp2 = j2k.wrap(tfile.name) - xmlbox = glymur.jp2box.XMLBox(filename=self.xmlfile) - jp2.append(xmlbox) - self.jp2_xml_file = tfile.name - - def tearDown(self): - os.unlink(self.xmlfile) - os.unlink(self.jp2_xml_file) - def test_utf8_xml(self): """Should be able to write/read an XMLBox with utf-8 encoding.""" - jp2 = Jp2k(self.jp2_xml_file) - box_xml = jp2.box[-1].xml.getroot() - box_xml_str = ET.tostring(box_xml, encoding='utf-8').decode('utf-8') - self.assertEqual(box_xml_str, - u'Россия') + # 'Россия' is 'Russia' in Cyrillic, not that it matters. + xml = u""" + Россия""" + with tempfile.NamedTemporaryFile(suffix=".xml") as xmlfile: + xmlfile.write(xml.encode('utf-8')) + xmlfile.flush() - @unittest.skip("Does not print properly.") - def test_printing_utf8_xml(self): - """Should be able to print an XMLBox with utf-8 encoding.""" - jp2 = Jp2k(self.jp2_xml_file) - with patch('sys.stdout', new=StringIO()) as fake_out: - print(jp2.box[-1]) - actual = fake_out.getvalue().strip() - lines = ["XML Box (xml ) @ (115305, 39)", - " u'Россия'"] - expected = '\n'.join(lines) - self.assertEqual(actual, expected) + j2k = glymur.Jp2k(self.j2kfile) + with tempfile.NamedTemporaryFile(suffix=".jp2") as jfile: + jp2 = j2k.wrap(jfile.name) + xmlbox = glymur.jp2box.XMLBox(filename=xmlfile.name) + jp2.append(xmlbox) + + box_xml = jp2.box[-1].xml.getroot() + box_xml_str = ET.tostring(box_xml, + encoding='utf-8').decode('utf-8') + self.assertEqual(box_xml_str, + u'Россия') diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 2694aa2..ef2b7f2 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Test suite for printing. """ # C0302: don't care too much about having too many lines in a test module @@ -15,6 +16,7 @@ import struct import sys import tempfile import warnings +from xml.etree import cElementTree as ET if sys.hexversion < 0x02070000: import unittest2 as unittest @@ -730,6 +732,46 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) + @unittest.skipIf(sys.hexversion < 0x02070000, + "Differences in XML printing between 2.6 and 2.7") + def test_xml_latin1(self): + """Should be able to print an XMLBox with utf-8 encoding (latin1).""" + text = u""" + Strömung""" + if sys.hexversion < 0x03000000: + xml = ET.parse(StringIO(text.encode('utf-8'))) + else: + xml = ET.parse(StringIO(text)) + + xmlbox = glymur.jp2box.XMLBox(xml=xml) + with patch('sys.stdout', new=StringIO()) as fake_out: + print(xmlbox) + actual = fake_out.getvalue().strip() + lines = ["XML Box (xml ) @ (-1, 0)", + " Strömung"] + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + + @unittest.skipIf(sys.hexversion < 0x02070000, + "Differences in XML printing between 2.6 and 2.7") + def test_xml_cyrrilic(self): + """Should be able to print an XMLBox with utf-8 encoding (cyrrillic).""" + text = u""" + Россия""" + if sys.hexversion < 0x03000000: + xml = ET.parse(StringIO(text.encode('utf-8'))) + else: + xml = ET.parse(StringIO(text)) + + xmlbox = glymur.jp2box.XMLBox(xml=xml) + with patch('sys.stdout', new=StringIO()) as fake_out: + print(xmlbox) + actual = fake_out.getvalue().strip() + lines = ["XML Box (xml ) @ (-1, 0)", + " Россия"] + expected = '\n'.join(lines) + self.assertEqual(actual, expected) + @unittest.skipIf(OPJ_DATA_ROOT is None, "OPJ_DATA_ROOT environment variable not set") def test_channel_definition(self): From a886234f015fac98c97689788d0518f98ac14436 Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 13 Oct 2013 12:02:23 -0400 Subject: [PATCH 120/122] Must use hex escapes to confirm 2.7 output. Closes #131 (again) --- glymur/test/test_printing.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index ef2b7f2..9d3374e 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -747,8 +747,12 @@ class TestPrinting(unittest.TestCase): with patch('sys.stdout', new=StringIO()) as fake_out: print(xmlbox) actual = fake_out.getvalue().strip() - lines = ["XML Box (xml ) @ (-1, 0)", - " Strömung"] + if sys.hexversion < 0x03000000: + lines = ["XML Box (xml ) @ (-1, 0)", + " Str\xc3\xb6mung"] + else: + lines = ["XML Box (xml ) @ (-1, 0)", + " Strömung"] expected = '\n'.join(lines) self.assertEqual(actual, expected) @@ -767,8 +771,13 @@ class TestPrinting(unittest.TestCase): with patch('sys.stdout', new=StringIO()) as fake_out: print(xmlbox) actual = fake_out.getvalue().strip() - lines = ["XML Box (xml ) @ (-1, 0)", - " Россия"] + if sys.hexversion < 0x03000000: + lines = ["XML Box (xml ) @ (-1, 0)", + " \xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f"] + else: + lines = ["XML Box (xml ) @ (-1, 0)", + " Россия"] + expected = '\n'.join(lines) self.assertEqual(actual, expected) From 4c09d3ad3afed1c392ad62e6c5e85850d32169de Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 13 Oct 2013 12:12:20 -0400 Subject: [PATCH 121/122] Disabling test_xml_cyrrilic and test_xml_latin1 on 2.7 There seems to be inconsistencies between different versions of 2.x as to how non-ascii XML chars get printed, so disable those tests for now. Closes #131 (again). --- glymur/test/test_printing.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py index 9d3374e..bb7da3e 100644 --- a/glymur/test/test_printing.py +++ b/glymur/test/test_printing.py @@ -732,10 +732,15 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(sys.hexversion < 0x02070000, - "Differences in XML printing between 2.6 and 2.7") + @unittest.skipIf(sys.hexversion < 0x03000000, + "Only trusting python3 for printing non-ascii chars") def test_xml_latin1(self): """Should be able to print an XMLBox with utf-8 encoding (latin1).""" + # Seems to be inconsistencies between different versions of python2.x + # as to what gets printed. + # + # 2.7.5 (fedora 19) prints xml entities. + # 2.7.3 seems to want to print hex escapes. text = u""" Strömung""" if sys.hexversion < 0x03000000: @@ -756,10 +761,15 @@ class TestPrinting(unittest.TestCase): expected = '\n'.join(lines) self.assertEqual(actual, expected) - @unittest.skipIf(sys.hexversion < 0x02070000, - "Differences in XML printing between 2.6 and 2.7") + @unittest.skipIf(sys.hexversion < 0x03000000, + "Only trusting python3 for printing non-ascii chars") def test_xml_cyrrilic(self): """Should be able to print an XMLBox with utf-8 encoding (cyrrillic).""" + # Seems to be inconsistencies between different versions of python2.x + # as to what gets printed. + # + # 2.7.5 (fedora 19) prints xml entities. + # 2.7.3 seems to want to print hex escapes. text = u""" Россия""" if sys.hexversion < 0x03000000: @@ -773,7 +783,7 @@ class TestPrinting(unittest.TestCase): actual = fake_out.getvalue().strip() if sys.hexversion < 0x03000000: lines = ["XML Box (xml ) @ (-1, 0)", - " \xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f"] + " Россия"] else: lines = ["XML Box (xml ) @ (-1, 0)", " Россия"] From f08f1d9bb9059bf61c0faa72cf5974575c5f93ef Mon Sep 17 00:00:00 2001 From: John Evans Date: Sun, 13 Oct 2013 12:30:28 -0400 Subject: [PATCH 122/122] Finalizing 0.5.6 release. --- CHANGES.txt | 3 +++ docs/source/conf.py | 2 +- glymur/version.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 30387a6..40846e4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Oct 13, 2013 - v0.5.6 Fixed handling of non-ascii chars in XML boxes. Fixed + some docstring errors in jp2box module. + Oct 03, 2013 - v0.5.5 Fixed pip install error introduced in 0.5.0. Sep 24, 2013 - v0.5.4 Fixed test error restricted to v2.0. diff --git a/docs/source/conf.py b/docs/source/conf.py index f847e68..44fc9e0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.5.5' +release = '0.5.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/glymur/version.py b/glymur/version.py index 192859f..af7523e 100644 --- a/glymur/version.py +++ b/glymur/version.py @@ -15,7 +15,7 @@ from .lib import openjp2 as opj2 # Do not change the format of this next line! Doing so risks breaking # setup.py -version = "0.5.5" +version = "0.5.6" _sv = LooseVersion(version) version_tuple = _sv.version