Changed nemo.jp2 to have a single XMP UUID. #104
This commit is contained in:
parent
0e302a5710
commit
08aaa25fdd
7 changed files with 169 additions and 145 deletions
Binary file not shown.
|
|
@ -2136,12 +2136,6 @@ class UUIDBox(Jp2kBox):
|
|||
self.data = raw_data
|
||||
self._type = 'unknown'
|
||||
|
||||
if length == 0:
|
||||
# Need to compute the length.
|
||||
# The length is 8 (L and T fields) + 16 (length of UUID identifier)
|
||||
# + length of uuid data.
|
||||
length = 24 + len(self.data)
|
||||
|
||||
self.length = length
|
||||
self.offset = offset
|
||||
|
||||
|
|
@ -2179,9 +2173,15 @@ class UUIDBox(Jp2kBox):
|
|||
if self._type != 'XMP':
|
||||
msg = "Only XMP UUID boxes can currently be written."
|
||||
raise NotImplementedError(msg)
|
||||
read_buffer = struct.pack('>I4s', self.length, 'uuid')
|
||||
serialized_buffer = b'<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>'
|
||||
serialized_buffer += ET.tostring(self.data.getroot(), encoding='utf-8')
|
||||
serialized_buffer += b'<?xpacket end="w"?>'
|
||||
if self.length == 0:
|
||||
self.length = 24 + len(serialized_buffer)
|
||||
read_buffer = struct.pack('>I4s', self.length, b'uuid')
|
||||
fptr.write(read_buffer)
|
||||
fptr.write(self.data)
|
||||
fptr.write(self.uuid.bytes)
|
||||
fptr.write(serialized_buffer)
|
||||
|
||||
@staticmethod
|
||||
def parse(fptr, offset, length):
|
||||
|
|
|
|||
|
|
@ -1013,7 +1013,7 @@ class Jp2k(Jp2kBox):
|
|||
>>> jp2 = glymur.Jp2k(jfile)
|
||||
>>> codestream = jp2.get_codestream()
|
||||
>>> print(codestream.segment[1])
|
||||
SIZ marker segment @ (3137, 47)
|
||||
SIZ marker segment @ (3233, 47)
|
||||
Profile: 2
|
||||
Reference Grid Height, Width: (1456 x 2592)
|
||||
Vertical, Horizontal Reference Grid Offset: (0 x 0)
|
||||
|
|
|
|||
|
|
@ -167,3 +167,90 @@ def read_pgx_header(pgx_file):
|
|||
|
||||
header = header.rstrip()
|
||||
return header, pos
|
||||
|
||||
nemo_xmp_box = """UUID Box (uuid) @ (77, 3146)
|
||||
UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)
|
||||
UUID Data:
|
||||
<ns0:xmpmeta xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ns0="adobe:ns:meta/" xmlns:ns2="http://ns.adobe.com/xap/1.0/" xmlns:ns3="http://ns.adobe.com/tiff/1.0/" xmlns:ns4="http://ns.adobe.com/exif/1.0/" xmlns:ns5="http://ns.adobe.com/photoshop/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ns0:xmptk="Exempi + XMP Core 5.1.2">
|
||||
<rdf:RDF>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns2:CreatorTool>Google</ns2:CreatorTool>
|
||||
<ns2:CreateDate>2013-02-09T14:47:53</ns2:CreateDate>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns3:YCbCrPositioning>1</ns3:YCbCrPositioning>
|
||||
<ns3:XResolution>72/1</ns3:XResolution>
|
||||
<ns3:YResolution>72/1</ns3:YResolution>
|
||||
<ns3:ResolutionUnit>2</ns3:ResolutionUnit>
|
||||
<ns3:Make>HTC</ns3:Make>
|
||||
<ns3:Model>HTC Glacier</ns3:Model>
|
||||
<ns3:ImageWidth>2592</ns3:ImageWidth>
|
||||
<ns3:ImageLength>1456</ns3:ImageLength>
|
||||
<ns3:BitsPerSample>
|
||||
<rdf:Seq>
|
||||
<rdf:li>8</rdf:li>
|
||||
<rdf:li>8</rdf:li>
|
||||
<rdf:li>8</rdf:li>
|
||||
</rdf:Seq>
|
||||
</ns3:BitsPerSample>
|
||||
<ns3:PhotometricInterpretation>2</ns3:PhotometricInterpretation>
|
||||
<ns3:SamplesPerPixel>3</ns3:SamplesPerPixel>
|
||||
<ns3:WhitePoint>
|
||||
<rdf:Seq>
|
||||
<rdf:li>1343036288/4294967295</rdf:li>
|
||||
<rdf:li>1413044224/4294967295</rdf:li>
|
||||
</rdf:Seq>
|
||||
</ns3:WhitePoint>
|
||||
<ns3:PrimaryChromaticities>
|
||||
<rdf:Seq>
|
||||
<rdf:li>2748779008/4294967295</rdf:li>
|
||||
<rdf:li>1417339264/4294967295</rdf:li>
|
||||
<rdf:li>1288490240/4294967295</rdf:li>
|
||||
<rdf:li>2576980480/4294967295</rdf:li>
|
||||
<rdf:li>644245120/4294967295</rdf:li>
|
||||
<rdf:li>257698032/4294967295</rdf:li>
|
||||
</rdf:Seq>
|
||||
</ns3:PrimaryChromaticities>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns4:ColorSpace>1</ns4:ColorSpace>
|
||||
<ns4:PixelXDimension>2528</ns4:PixelXDimension>
|
||||
<ns4:PixelYDimension>1424</ns4:PixelYDimension>
|
||||
<ns4:FocalLength>353/100</ns4:FocalLength>
|
||||
<ns4:GPSAltitudeRef>0</ns4:GPSAltitudeRef>
|
||||
<ns4:GPSAltitude>0/1</ns4:GPSAltitude>
|
||||
<ns4:GPSMapDatum>WGS-84</ns4:GPSMapDatum>
|
||||
<ns4:DateTimeOriginal>2013-02-09T14:47:53</ns4:DateTimeOriginal>
|
||||
<ns4:ISOSpeedRatings>
|
||||
<rdf:Seq>
|
||||
<rdf:li>76</rdf:li>
|
||||
</rdf:Seq>
|
||||
</ns4:ISOSpeedRatings>
|
||||
<ns4:ExifVersion>0220</ns4:ExifVersion>
|
||||
<ns4:FlashpixVersion>0100</ns4:FlashpixVersion>
|
||||
<ns4:ComponentsConfiguration>
|
||||
<rdf:Seq>
|
||||
<rdf:li>1</rdf:li>
|
||||
<rdf:li>2</rdf:li>
|
||||
<rdf:li>3</rdf:li>
|
||||
<rdf:li>0</rdf:li>
|
||||
</rdf:Seq>
|
||||
</ns4:ComponentsConfiguration>
|
||||
<ns4:GPSLatitude>42,20.56N</ns4:GPSLatitude>
|
||||
<ns4:GPSLongitude>71,5.29W</ns4:GPSLongitude>
|
||||
<ns4:GPSTimeStamp>2013-02-09T19:47:53Z</ns4:GPSTimeStamp>
|
||||
<ns4:GPSProcessingMethod>NETWORK</ns4:GPSProcessingMethod>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<ns5:DateCreated>2013-02-09T14:47:53</ns5:DateCreated>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="">
|
||||
<dc:Creator>
|
||||
<rdf:Seq>
|
||||
<rdf:li>Glymur</rdf:li>
|
||||
<rdf:li>Python XMP Toolkit</rdf:li>
|
||||
</rdf:Seq>
|
||||
</dc:Creator>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
</ns0:xmpmeta>"""
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ class TestAppend(unittest.TestCase):
|
|||
# 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 ']
|
||||
expected = ['jP ', 'ftyp', 'jp2h', 'uuid', 'jp2c', 'xml ']
|
||||
self.assertEqual(box_ids, expected)
|
||||
self.assertEqual(ET.tostring(jp2.box[-1].xml.getroot()),
|
||||
b'<data>0</data>')
|
||||
|
|
@ -468,7 +468,7 @@ class TestAppend(unittest.TestCase):
|
|||
# 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 ']
|
||||
expected = ['jP ', 'ftyp', 'jp2h', 'uuid', 'jp2c', 'xml ']
|
||||
self.assertEqual(box_ids, expected)
|
||||
self.assertEqual(ET.tostring(jp2.box[-1].xml.getroot()),
|
||||
b'<data>0</data>')
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class TestJp2k(unittest.TestCase):
|
|||
jp2k = Jp2k(self.jp2file)
|
||||
|
||||
# top-level boxes
|
||||
self.assertEqual(len(jp2k.box), 6)
|
||||
self.assertEqual(len(jp2k.box), 5)
|
||||
|
||||
self.assertEqual(jp2k.box[0].box_id, 'jP ')
|
||||
self.assertEqual(jp2k.box[0].offset, 0)
|
||||
|
|
@ -119,15 +119,11 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
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[3].length, 3146)
|
||||
|
||||
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)
|
||||
self.assertEqual(jp2k.box[4].box_id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[4].offset, 3223)
|
||||
self.assertEqual(jp2k.box[4].length, 1132296)
|
||||
|
||||
# jp2h super box
|
||||
self.assertEqual(len(jp2k.box[2].box), 2)
|
||||
|
|
@ -169,7 +165,7 @@ class TestJp2k(unittest.TestCase):
|
|||
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)
|
||||
write_buffer = ifile.read(3223)
|
||||
tfile.write(write_buffer)
|
||||
|
||||
# The L field must be 1 in order to signal the presence of the
|
||||
|
|
@ -190,9 +186,9 @@ class TestJp2k(unittest.TestCase):
|
|||
|
||||
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)
|
||||
self.assertEqual(jp2k.box[4].box_id, 'jp2c')
|
||||
self.assertEqual(jp2k.box[4].offset, 3223)
|
||||
self.assertEqual(jp2k.box[4].length, 1133427 + 8)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "NamedTemporaryFile issue on windows")
|
||||
def test_length_field_is_zero(self):
|
||||
|
|
@ -357,45 +353,12 @@ class TestJp2k(unittest.TestCase):
|
|||
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
|
||||
xmp = j.box[3].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)
|
||||
ns2 = '{http://ns.adobe.com/xap/1.0/}'
|
||||
name = '{0}RDF/{0}Description/{1}CreatorTool'.format(ns0, ns2)
|
||||
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('<H', int(171))
|
||||
fptr.write(write_buffer)
|
||||
|
||||
# Verify that a warning is issued, but only on python3.
|
||||
# On python2, just suppress the warning.
|
||||
if sys.hexversion < 0x03030000:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
j = Jp2k(tfile.name)
|
||||
else:
|
||||
with self.assertWarns(UserWarning):
|
||||
j = Jp2k(tfile.name)
|
||||
|
||||
exif = j.box[3].data
|
||||
# Were the tag == 271, 'Make' would be in the keys instead.
|
||||
self.assertTrue(171 in exif['Image'].keys())
|
||||
self.assertFalse('Make' in exif['Image'].keys())
|
||||
self.assertEqual(elt.text, 'Google')
|
||||
|
||||
|
||||
@unittest.skipIf(re.match(r"""1\.[01234]""", glymur.version.openjpeg_version),
|
||||
|
|
@ -733,19 +696,22 @@ class TestJp2k_2_1(unittest.TestCase):
|
|||
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])
|
||||
# Codestream starts at byte 3323. SIZ marker at 3233.
|
||||
# COD marker at 3282. Subsampling at 3276.
|
||||
offset = 3223
|
||||
tfile.write(data[0:offset+52])
|
||||
|
||||
# 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(data[offset+53:offset+55])
|
||||
tfile.write(b'\x00')
|
||||
tfile.write(data[3184:3186])
|
||||
tfile.write(data[offset+57:offset+59])
|
||||
#tfile.write(data[3184:3186])
|
||||
tfile.write(b'\x00')
|
||||
|
||||
tfile.write(data[3186:])
|
||||
tfile.write(data[offset+59:])
|
||||
#tfile.write(data[3186:])
|
||||
tfile.flush()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ else:
|
|||
|
||||
import glymur
|
||||
from glymur import Jp2k
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file
|
||||
from .fixtures import OPJ_DATA_ROOT, opj_data_file, nemo_xmp_box
|
||||
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
|
||||
|
|
@ -230,7 +230,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[6])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['COC marker segment @ (3260, 9)',
|
||||
lines = ['COC marker segment @ (3356, 9)',
|
||||
' Associated component: 1',
|
||||
' Coding style for this component: '
|
||||
+ 'Entropy coder, PARTITION = 0',
|
||||
|
|
@ -258,7 +258,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[2])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['COD marker segment @ (3186, 12)',
|
||||
lines = ['COD marker segment @ (3282, 12)',
|
||||
' Coding style:',
|
||||
' Entropy coder, without partitions',
|
||||
' SOP marker segments: False',
|
||||
|
|
@ -424,7 +424,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[-1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['EOC marker segment @ (1135421, 0)']
|
||||
lines = ['EOC marker segment @ (1135517, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -521,7 +521,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[7])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['QCC marker segment @ (3271, 8)',
|
||||
lines = ['QCC marker segment @ (3367, 8)',
|
||||
' Associated Component: 1',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||
|
|
@ -537,7 +537,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[3])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['QCD marker segment @ (3200, 7)',
|
||||
lines = ['QCD marker segment @ (3296, 7)',
|
||||
' Quantization style: no quantization, 2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]']
|
||||
|
||||
|
|
@ -552,7 +552,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[1])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['SIZ marker segment @ (3137, 47)',
|
||||
lines = ['SIZ marker segment @ (3233, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||
|
|
@ -574,7 +574,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[0])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['SOC marker segment @ (3135, 0)']
|
||||
lines = ['SOC marker segment @ (3231, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -586,7 +586,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[10])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['SOD marker segment @ (3302, 0)']
|
||||
lines = ['SOD marker segment @ (3398, 0)']
|
||||
expected = '\n'.join(lines)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ class TestPrinting(unittest.TestCase):
|
|||
print(codestream.segment[5])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ['SOT marker segment @ (3248, 10)',
|
||||
lines = ['SOT marker segment @ (3344, 10)',
|
||||
' Tile part index: 0',
|
||||
' Tile part length: 1132173',
|
||||
' Tile part instance: 0',
|
||||
|
|
@ -632,22 +632,10 @@ class TestPrinting(unittest.TestCase):
|
|||
"""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])
|
||||
print(j.box[3])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lst = ['UUID Box (uuid) @ (715, 2412)',
|
||||
' UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP)',
|
||||
' UUID Data: ',
|
||||
' <ns0:xmpmeta xmlns:ns0="adobe:ns:meta/" '
|
||||
+ 'xmlns:ns2="http://ns.adobe.com/xap/1.0/" '
|
||||
+ 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
|
||||
+ 'ns0:xmptk="XMP Core 4.4.0-Exiv2">',
|
||||
' <rdf:RDF>',
|
||||
' <rdf:Description ns2:CreatorTool="glymur" '
|
||||
+ 'rdf:about="" />',
|
||||
' </rdf:RDF>',
|
||||
' </ns0:xmpmeta>']
|
||||
expected = '\n'.join(lst)
|
||||
expected = nemo_xmp_box
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_codestream(self):
|
||||
|
|
@ -657,8 +645,8 @@ class TestPrinting(unittest.TestCase):
|
|||
print(j.get_codestream())
|
||||
actual = fake_out.getvalue().strip()
|
||||
lst = ['Codestream:',
|
||||
' SOC marker segment @ (3135, 0)',
|
||||
' SIZ marker segment @ (3137, 47)',
|
||||
' SOC marker segment @ (3231, 0)',
|
||||
' SIZ marker segment @ (3233, 47)',
|
||||
' Profile: 2',
|
||||
' Reference Grid Height, Width: (1456 x 2592)',
|
||||
' Vertical, Horizontal Reference Grid Offset: (0 x 0)',
|
||||
|
|
@ -668,7 +656,7 @@ class TestPrinting(unittest.TestCase):
|
|||
' Signed: (False, False, False)',
|
||||
' Vertical, Horizontal Subsampling: '
|
||||
+ '((1, 1), (1, 1), (1, 1))',
|
||||
' COD marker segment @ (3186, 12)',
|
||||
' COD marker segment @ (3282, 12)',
|
||||
' Coding style:',
|
||||
' Entropy coder, without partitions',
|
||||
' SOP marker segments: False',
|
||||
|
|
@ -690,11 +678,11 @@ class TestPrinting(unittest.TestCase):
|
|||
' Vertically stripe causal context: False',
|
||||
' Predictable termination: False',
|
||||
' Segmentation symbols: False',
|
||||
' QCD marker segment @ (3200, 7)',
|
||||
' QCD marker segment @ (3296, 7)',
|
||||
' Quantization style: no quantization, '
|
||||
+ '2 guard bits',
|
||||
' Step size: [(0, 8), (0, 9), (0, 9), (0, 10)]',
|
||||
' CME marker segment @ (3209, 37)',
|
||||
' CME marker segment @ (3305, 37)',
|
||||
' "Created by OpenJPEG version 2.0.0"']
|
||||
expected = '\n'.join(lst)
|
||||
self.assertEqual(actual, expected)
|
||||
|
|
@ -1046,59 +1034,42 @@ class TestPrinting(unittest.TestCase):
|
|||
"Ordered dicts not printing well in 2.7")
|
||||
def test_exif_uuid(self):
|
||||
"""Verify printing of exif information"""
|
||||
j = glymur.Jp2k(self.jp2file)
|
||||
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
|
||||
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[3])
|
||||
actual = fake_out.getvalue().strip()
|
||||
with open(self.jp2file, 'rb') as ifptr:
|
||||
tfile.write(ifptr.read())
|
||||
|
||||
lines = ["UUID Box (uuid) @ (77, 638)",
|
||||
# Write L, T, UUID identifier.
|
||||
tfile.write(struct.pack('>I4s', 76, b'uuid'))
|
||||
tfile.write(b'JpgTiffExif->JP2')
|
||||
|
||||
tfile.write(b'Exif\x00\x00')
|
||||
xbuffer = struct.pack('<BBHI', 73, 73, 42, 8)
|
||||
tfile.write(xbuffer)
|
||||
|
||||
# We will write just three tags.
|
||||
tfile.write(struct.pack('<H', 3))
|
||||
|
||||
# The "Make" tag is tag no. 271.
|
||||
tfile.write(struct.pack('<HHII', 256, 4, 1, 256))
|
||||
tfile.write(struct.pack('<HHII', 257, 4, 1, 512))
|
||||
tfile.write(struct.pack('<HHI4s', 271, 2, 3, b'HTC\x00'))
|
||||
tfile.flush()
|
||||
|
||||
j = glymur.Jp2k(tfile.name)
|
||||
|
||||
with patch('sys.stdout', new=StringIO()) as fake_out:
|
||||
print(j.box[5])
|
||||
actual = fake_out.getvalue().strip()
|
||||
|
||||
lines = ["UUID Box (uuid) @ (1135519, 76)",
|
||||
" UUID: 4a706754-6966-6645-7869-662d3e4a5032 (Exif)",
|
||||
" UUID Data: ",
|
||||
"{'Image': {'Make': 'HTC',",
|
||||
" 'Model': 'HTC Glacier',",
|
||||
" 'XResolution': 72.0,",
|
||||
" 'YResolution': 72.0,",
|
||||
" 'ResolutionUnit': 2,",
|
||||
" 'YCbCrPositioning': 1,",
|
||||
" 'ExifTag': 138,",
|
||||
" 'GPSTag': 354},",
|
||||
" 'Photo': {'ISOSpeedRatings': 76,",
|
||||
" 'ExifVersion': (48, 50, 50, 48),",
|
||||
" 'DateTimeOriginal': '2013:02:09 14:47:53',",
|
||||
" 'DateTimeDigitized': '2013:02:09 14:47:53',",
|
||||
" 'ComponentsConfiguration': (1, 2, 3, 0),",
|
||||
" 'FocalLength': 3.53,",
|
||||
" 'FlashpixVersion': (48, 49, 48, 48),",
|
||||
" 'ColorSpace': 1,",
|
||||
" 'PixelXDimension': 2528,",
|
||||
" 'PixelYDimension': 1424,",
|
||||
" 'InteroperabilityTag': 324},",
|
||||
" 'GPSInfo': {'GPSVersionID': (2, 2, 0),",
|
||||
" 'GPSLatitudeRef': 'N',",
|
||||
" 'GPSLatitude': [42.0, 20.0, 33.61],",
|
||||
" 'GPSLongitudeRef': 'W',",
|
||||
" 'GPSLongitude': [71.0, 5.0, 17.32],",
|
||||
" 'GPSAltitudeRef': 0,",
|
||||
" 'GPSAltitude': 0.0,",
|
||||
" 'GPSTimeStamp': [19.0, 47.0, 53.0],",
|
||||
" 'GPSMapDatum': 'WGS-84',",
|
||||
" 'GPSProcessingMethod': (65,",
|
||||
" 83,",
|
||||
" 67,",
|
||||
" 73,",
|
||||
" 73,",
|
||||
" 0,",
|
||||
" 0,",
|
||||
" 0,",
|
||||
" 78,",
|
||||
" 69,",
|
||||
" 84,",
|
||||
" 87,",
|
||||
" 79,",
|
||||
" 82,",
|
||||
" 75),",
|
||||
" 'GPSDateStamp': '2013:02:09'},",
|
||||
"{'Image': {'ImageWidth': 256,",
|
||||
" 'ImageLength': 512,",
|
||||
" 'Make': 'HTC'},",
|
||||
" 'Photo': None,",
|
||||
" 'GPSInfo': None,",
|
||||
" 'Iop': None}"]
|
||||
|
||||
expected = '\n'.join(lines)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue