From 08aaa25fdd03dcad140c1bd6b82b31840d633961 Mon Sep 17 00:00:00 2001 From: jevans Date: Thu, 24 Oct 2013 19:05:11 -0400 Subject: [PATCH] Changed nemo.jp2 to have a single XMP UUID. #104 --- glymur/data/nemo.jp2 | Bin 1135423 -> 1135519 bytes glymur/jp2box.py | 16 ++--- glymur/jp2k.py | 2 +- glymur/test/fixtures.py | 87 ++++++++++++++++++++++++ glymur/test/test_jp2box.py | 4 +- glymur/test/test_jp2k.py | 78 ++++++--------------- glymur/test/test_printing.py | 127 ++++++++++++++--------------------- 7 files changed, 169 insertions(+), 145 deletions(-) diff --git a/glymur/data/nemo.jp2 b/glymur/data/nemo.jp2 index 55d199cfe6ebc1630bd87a238c6f4cb4b7333d9d..838583d2f3e22a49d877299178a764436b808e74 100644 GIT binary patch delta 2966 zcma)8&2QsG6c^3%Rmzt*f<(3|C$_OY9w)KYT7t9q!gl{X$|VkgdO4^Oh+`@J{sYu>!Se?R~AkMp0e_YS^Z{=4_t z^1r>u-=BnuYAu2&AgR+_1b&!Uo_l&YOVh|wlxQCNEf!A|&sB&|0urW)qO~;Tu)u=$ z>7nDX7sLWhZloka%YPc5W)i7OvtiQ8by_Y9l$1^;U{ftA;(8=m&`qRKkBnw4Wyy?1 ziuQW8`^}Tsn^?oMi{&qk#~J)L zn~)=9^e~`BgAEb5dd>Rnw1EbgY_V4O_Tl8G1=kU_kFg;m4kl z#Eof`QWo-)PnN$mK9N4?)?M#KFCMUjasUmdw#H4>@C!$D>vl*I=FfA39i$ZaGFL+H zYN2<-Y;8ee*U)c6n%YRXvB8z-E9airUyXYLmH(|}%p*P*Hv7KgQW6)SoSmaG9^qx+ zOvw%P(wU76vpBEBl=gDoQxZ-AsbQln%$2zk`Xx=10f|RW5cwo8w5a`v{2>0sZ{}0G zE6M|3TpJ3*i}mV!p}n#zT-rVz+Dx|wymR3m#ninFQxZpU2A3+YUlH{-Vg-)z{gM#SxI6;Ns9a&$e42=Rt+9m46$??MNLU@@<_ ze(}_lrxCX5?B$`I!<+k@WN}_a6`>+&f-ShxsSDppW)WRHCk1?6jtz-a>9HVUAzv$c zES%8kJQlM~ILf`w{oJ^N)p*wTZ3iF5Upan>hgiyd@mI}D;a^tk;Hvgd!Drr7Hbzg7 z+A`YDL=!^!rAS81nJkbXd&}vjhCXb!Z?F|8Kv-0Rhq>V>%@0bo41vKm9+;k zb4ijwpIni2#ytDk`S|8~_>ENC0)Vzi#%d@u;12VB=z7)jM&6wHPDH$lQ>7iJ3feMS z*eqs?=dM<)mk##6{}9Y!NhlXi7Ig3c@rC(L$M>{*npT0E70%CW=X)JLv>G!XTd)o0 zC&4;s@AG`gUD^Ke=-{WLgV%uefEqxLfL;fB1L#elw}9RT+6Q_Eh~wV{dJpJ*pb!2! JI{5J8{{NWigc<+< delta 2973 zcmcJN&rTCj6vpq&v=pX=q7WBWlVKu}kkFZy63e7CF>NhHE&rO}w%C?5wzO6t)rFHN z3B*;A#I3CK5nQ-nqHV4yH`lCSqW=bn3h=ic<|_ssFPOlMK&-*0bM zOAF17LbX!Kw5ye={3rPFeRv&ao$la6b17RZzO0s8WF9e1|6l#&;lA1C87=MjjB(Ux zR24cr8AWOot_rEsxmQh^lf&`sr-^kvZG%0YU`kJ6=M(%%|yL zd{H$rt*KE>os}XnE%r#8nLamHM12YMJT79s-pXto?i7zro%r#~5rG!swP-1Qv^2Zi)rY%bDgM1G)4=qgDi{j7)JhApP5H!#3O7~*gC`3we0FtJVwal)l@ErTs~7+TU>c+c`Zyy z$UyC2d0hDW^Y~zAEH5V7TD#t?m$!;iyI$LTqqXPcVyUrS*5GMcktL&K>(!k6;`x%4 zYP8ByEF24~Q~2BNMCGI?C0eD5wvv8w_=SrfCjDbWqJ)q2t2Yl{b9eN1v8hDDsv^@p zAhlGhT-<833XMi>PTr`!t#7wvg*H=Ix1^X*PNu_#t55Ilv`dOJ#K!L##mcusY%PCkjT|Tr)krTpZ#nN=L=ivk o2KIIX9K=HcI4s', self.length, 'uuid') + serialized_buffer = b'' + serialized_buffer += ET.tostring(self.data.getroot(), encoding='utf-8') + serialized_buffer += b'' + 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): diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 45eaf39..42eaab5 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -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) diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py index b872f1d..68c0706 100644 --- a/glymur/test/fixtures.py +++ b/glymur/test/fixtures.py @@ -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: + + + + Google + 2013-02-09T14:47:53 + + + 1 + 72/1 + 72/1 + 2 + HTC + HTC Glacier + 2592 + 1456 + + + 8 + 8 + 8 + + + 2 + 3 + + + 1343036288/4294967295 + 1413044224/4294967295 + + + + + 2748779008/4294967295 + 1417339264/4294967295 + 1288490240/4294967295 + 2576980480/4294967295 + 644245120/4294967295 + 257698032/4294967295 + + + + + 1 + 2528 + 1424 + 353/100 + 0 + 0/1 + WGS-84 + 2013-02-09T14:47:53 + + + 76 + + + 0220 + 0100 + + + 1 + 2 + 3 + 0 + + + 42,20.56N + 71,5.29W + 2013-02-09T19:47:53Z + NETWORK + + + 2013-02-09T14:47:53 + + + + + Glymur + Python XMP Toolkit + + + + + """ diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index ff61bc5..2f6241c 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -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'0') @@ -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'0') diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 636ea9a..c9e750a 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -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('', - ' ', - ' ', - ' ', - ' '] - 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('