diff --git a/CHANGES.txt b/CHANGES.txt index 76abc9b..bd5acf8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +Jun 02, 2013 - v0.1.3p1 Raising IOErrors when code block size and precinct + sizes are not in harmony. Added statement to docs about upstream library + dependence. Added roadmap to docs. + May 30, 2013 - v0.1.2. Added XMP UUID read support. Added jp2 boxes to rst docs, XMLBox.indent method made into a private module method. Precinct sizes restricted to be multiples of two. diff --git a/MANIFEST b/MANIFEST index 49ff165..281450e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,14 +1,22 @@ # file GENERATED by distutils, do NOT edit -README setup.py -jptools/__init__.py -jptools/codestream.py -jptools/core.py -jptools/jp2box.py -jptools/jp2k.py -jptools/data/emneck.jp2 -jptools/test/__init__.py -jptools/test/test_codestream.py -jptools/test/test_conformance.py -jptools/test/test_jp2k.py -jptools/test/test_printing.py +bin/jp2dump +glymur/__init__.py +glymur/codestream.py +glymur/core.py +glymur/jp2box.py +glymur/jp2dump.py +glymur/jp2k.py +glymur/data/nemo.jp2 +glymur/lib/__init__.py +glymur/lib/openjp2.py +glymur/lib/test/__init__.py +glymur/lib/test/test_openjp2.py +glymur/test/__init__.py +glymur/test/test_callbacks.py +glymur/test/test_codestream.py +glymur/test/test_jp2k.py +glymur/test/test_opj_suite.py +glymur/test/test_opj_suite_neg.py +glymur/test/test_opj_suite_write.py +glymur/test/test_printing.py diff --git a/docs/source/conf.py b/docs/source/conf.py index 8d48cf2..0b72b85 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -75,7 +75,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.1' # The full version, including alpha/beta/rc tags. -release = '0.1.2' +release = '0.1.3p1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/index.rst b/docs/source/index.rst index 43632b4..ffc9fa7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -14,6 +14,7 @@ Contents: introduction api how_do_i + roadmap Indices and tables diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index d07943f..c090d71 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -1,19 +1,23 @@ ========================================= -glymur: a Python interface for JPEG 2000 +Glymur: a Python interface for JPEG 2000 ========================================= -**glymur** contains a Python interface to the OpenJPEG library +**Glymur** contains a Python interface to the OpenJPEG library which allows linux and mac users to read and write JPEG 2000 files. For more -information about OpenJPEG, please consult http://www.openjpeg.org. glymur -should be considered to be alpha-quality software. +information about OpenJPEG, please consult http://www.openjpeg.org. Glymur +currently relies upon a development version of the OpenJPEG library, and so, +while useable, it is totally at the mercy of any upstream changes +made to the development version of OpenJPEG. -glymur tries to support reading and writing of JP2 and J2C files. Writing -J2C/JP2 files is currently limited to images that can fit in memory, however. -Of particular focus is metadata retrieval, such as XMP packets. +Glymur supports both reading and writing of JPEG 2000 images (part 1). Writing +JPEG 2000 images is currently limited to images that can fit in memory, +however. -There is some very limited support for reading JPX -metadata. For instance, **asoc** and **labl** boxes are recognized, so GMLJP2 -metadata can be retrieved from such JPX files. +Of particular focus is retrieval of metadata. Reading XMP UUID +boxes is supported, as the data block consists of XML. There is +some very limited support for reading JPX metadata. For instance, +**asoc** and **labl** boxes are recognized, so GMLJP2 metadata can +be retrieved from such JPX files. ------------ Requirements diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst new file mode 100644 index 0000000..d010885 --- /dev/null +++ b/docs/source/roadmap.rst @@ -0,0 +1,9 @@ +Roadmap +======= + +Here's an incomplete list of what I'd like to focus on in the near future. + + * continue to monitor upstream changes in the **openjp2** library + * add read support or Exif UUIDs + * investigate using CFFI or cython instead of ctypes to wrap **openjp2** + diff --git a/glymur/jp2k.py b/glymur/jp2k.py index 8d5272b..a42e291 100644 --- a/glymur/jp2k.py +++ b/glymur/jp2k.py @@ -233,6 +233,11 @@ class Jp2k(Jp2kBox): msg = "Code block area cannot exceed 4096. " msg += "Code block height and width must be larger than 4." raise RuntimeError(msg) + if ((math.log(h, 2) != math.floor(math.log(h, 2)) or + math.log(w, 2) != math.floor(math.log(w, 2)))): + msg = "Bad code block size ({0}, {1}), " + msg += "must be powers of 2." + raise IOError(msg.format(h, w)) cparams.cblockw_init = w cparams.cblockh_init = h @@ -269,10 +274,16 @@ class Jp2k(Jp2kBox): if psizes is not None: for j, (prch, prcw) in enumerate(psizes): + if j == 0 and cbsize is not None: + cblkh, cblkw = cbsize + if cblkh * 2 > prch or cblkw * 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 size ({0}, {1}), " - msg += "must be multiple of 2." + msg = "Bad precinct sizes ({0}, {1}), " + msg += "must be powers of 2." raise IOError(msg.format(prch, prcw)) cparams.prcw_init[j] = prcw diff --git a/glymur/test/test_jp2k.py b/glymur/test/test_jp2k.py index 64355fa..41628c2 100644 --- a/glymur/test/test_jp2k.py +++ b/glymur/test/test_jp2k.py @@ -150,6 +150,19 @@ class TestJp2k(unittest.TestCase): subsetdata = j.read(area=(0, 0, 512, 512)) np.testing.assert_array_equal(tiledata, subsetdata) + def test_write_cprl(self): + # Issue 17 + j = Jp2k(self.jp2file) + expdata = j.read(reduce=2) + 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) + + c = ofile.get_codestream() + self.assertEqual(c.segment[2].SPcod[0], glymur.core.CPRL) + def test_jp2_boxes(self): # Verify the boxes of a JP2 file. jp2k = Jp2k(self.jp2file) diff --git a/glymur/test/test_opj_suite_neg.py b/glymur/test/test_opj_suite_neg.py index f33b981..0862c42 100644 --- a/glymur/test/test_opj_suite_neg.py +++ b/glymur/test/test_opj_suite_neg.py @@ -153,7 +153,7 @@ class TestSuiteNegative(unittest.TestCase): j = Jp2k(infile) def test_precinct_size_not_multiple_of_two(self): - # Seems like precinct size should be a multiple of two. + # Seems like precinct sizes should be powers of two. ifile = Jp2k(self.jp2file) data = ifile.read(reduce=3) with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: @@ -161,5 +161,26 @@ class TestSuiteNegative(unittest.TestCase): with self.assertRaises(IOError) as ce: ofile.write(data, psizes=[(13, 13)]) + def test_codeblock_size_not_multiple_of_two(self): + # Seems like code block sizes should be powers of two. + ifile = Jp2k(self.jp2file) + data = ifile.read(reduce=3) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError) as ce: + ofile.write(data, cbsize=(13, 12)) + + def test_codeblock_size_with_precinct_size(self): + # Seems like code block sizes should never exceed half that of + # precinct size. + ifile = Jp2k(self.jp2file) + data = ifile.read(reduce=3) + with tempfile.NamedTemporaryFile(suffix='.jp2') as tfile: + ofile = Jp2k(tfile.name, 'wb') + with self.assertRaises(IOError) as ce: + ofile.write(data, + cbsize=(64, 64), + psizes=[(64, 64)]) + if __name__ == "__main__": unittest.main() diff --git a/setup.py b/setup.py index b7c483a..449cb96 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from distutils.core import setup kwargs = {'name': 'Glymur', - 'version': '0.1.2', + 'version': '0.1.3p1', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans',