[Git][debian-gis-team/glymur][upstream] New upstream version 0.10.1

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Fri Jul 1 19:25:34 BST 2022



Antonio Valentino pushed to branch upstream at Debian GIS Project / glymur


Commits:
b1bd50c1 by Antonio Valentino at 2022-07-01T18:13:31+00:00
New upstream version 0.10.1
- - - - -


8 changed files:

- CHANGES.txt
- docs/source/conf.py
- docs/source/how_do_i.rst
- docs/source/whatsnew/0.10.0.rst → docs/source/whatsnew/0.10.rst
- glymur/jp2box.py
- glymur/version.py
- setup.cfg
- tests/test_jp2box.py


Changes:

=====================================
CHANGES.txt
=====================================
@@ -1,3 +1,7 @@
+June 28, 2022 - v0.10.1
+    Add write capability for Resolution boxes
+    Add example documentation for reading layers
+
 June 15, 2022 - v0.10.0
     Allow parsing of Exif UUIDs missing the EXIF\00\00 lead-in
     Add read support for additional Exif tags


=====================================
docs/source/conf.py
=====================================
@@ -78,7 +78,7 @@ copyright = '2013-2022, John Evans'
 # The short X.Y version.
 version = '0.10'
 # The full version, including alpha/beta/rc tags.
-release = '0.10.0'
+release = '0.10.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.


=====================================
docs/source/how_do_i.rst
=====================================
@@ -10,7 +10,7 @@ Jp2k implements slicing via the :py:meth:`__getitem__` method and
 hooks it into the multiple resolution property of JPEG 2000 imagery.
 This allows you to retrieve multiresolution imagery via
 array-style slicing, i.e. strides.  For example, here's how
-to retrieve a full resolution and first lower-resolution image ::
+to retrieve a full resolution and first lower-resolution image. ::
 
     >>> import glymur
     >>> jp2file = glymur.data.nemo() # just a path to a JPEG2000 file
@@ -22,6 +22,21 @@ to retrieve a full resolution and first lower-resolution image ::
     >>> thumbnail.shape
     (728, 1296, 3)
 
+************************
+... read an image layer?
+************************
+JPEG2000 has layers which allow you to specify images with different
+levels of quality.  Different layers may be specified by utilizing 
+the layer property.  The default layer value is 0, which specifies the
+first layer. ::
+
+    >>> import glymur
+    >>> file = glymur.data.jpxfile() # just a path to a JPEG2000 file
+    >>> jp2 = glymur.Jp2k(file)
+    >>> d0 = j[:] # first layer
+    >>> j.layer = 3
+    >>> d3 = j[:] # third layer
+
 *********************************************************
 ... make use of OpenJPEG's thread support to read images?
 *********************************************************


=====================================
docs/source/whatsnew/0.10.0.rst → docs/source/whatsnew/0.10.rst
=====================================
@@ -2,6 +2,13 @@
 Changes in glymur 0.10
 ######################
 
+*****************
+Changes in 0.10.1
+*****************
+
+    Add write capability for Resolution boxes
+    Add example documentation for reading layers
+
 *****************
 Changes in 0.10.0
 *****************
@@ -9,3 +16,4 @@ Changes in 0.10.0
     Allow parsing of Exif UUIDs missing the EXIF\00\00 lead-in
     Add read support for additional Exif tags
     Add support for TLM segment generation
+


=====================================
glymur/jp2box.py
=====================================
@@ -12,12 +12,15 @@ References
 """
 
 # Standard library imports ...
+from fractions import Fraction
 import io
+from numbers import Number
 import os
 import pprint
 import struct
 import sys
 import textwrap
+from typing import Tuple
 from uuid import UUID
 import warnings
 
@@ -2540,6 +2543,11 @@ class ResolutionBox(Jp2kBox):
         msg = self._str_superbox()
         return msg
 
+    def write(self, fptr):
+        """Write a Resolution super box to file.
+        """
+        self._write_superbox(fptr, b'res ')
+
     @classmethod
     def parse(cls, fptr, offset, length):
         """Parse Resolution box.
@@ -2644,6 +2652,21 @@ class CaptureResolutionBox(Jp2kBox):
 
         return cls(vres, hres, length=length, offset=offset)
 
+    def write(self, fptr):
+        """Write a CaptureResolution box to file.
+        """
+
+        # 4 bytes for length, 4 for the ID, always 10 bytes for the payload
+        length = 18
+
+        fptr.write(struct.pack('>I4s', length, b'resc'))
+
+        re1, rn1, rd1 = decompose_resolution(self.vertical_resolution)
+        re2, rn2, rd2 = decompose_resolution(self.horizontal_resolution)
+
+        buffer = struct.pack('>HHHHbb', rn1, rd1, rn2, rd2, re1, re2)
+        fptr.write(buffer)
+
 
 class DisplayResolutionBox(Jp2kBox):
     """Container for Display resolution box information.
@@ -2721,6 +2744,21 @@ class DisplayResolutionBox(Jp2kBox):
 
         return cls(vres, hres, length=length, offset=offset)
 
+    def write(self, fptr):
+        """Write a DisplayResolution box to file.
+        """
+
+        # 4 bytes for length, 4 for the ID, always 10 bytes for the payload
+        length = 18
+
+        fptr.write(struct.pack('>I4s', length, b'resd'))
+
+        re1, rn1, rd1 = decompose_resolution(self.vertical_resolution)
+        re2, rn2, rd2 = decompose_resolution(self.horizontal_resolution)
+
+        buffer = struct.pack('>HHHHbb', rn1, rd1, rn2, rd2, re1, re2)
+        fptr.write(buffer)
+
 
 class LabelBox(Jp2kBox):
     """Container for Label box information.
@@ -3659,3 +3697,56 @@ _BOX_WITH_ID = {
     b'url ': DataEntryURLBox,
     b'uuid': UUIDBox,
     b'xml ': XMLBox}
+
+
+def decompose_resolution(value: Number) -> Tuple[int, int, int]:
+    """Method by John-P (John Pocock)
+    Find an integer fraction and exponent representation of a number.
+    The result is of the form:
+    (numerator / denominator) * 10 ** exponent
+    The numerator and denominator are both 16-bit unsigned integers.
+    The exponent is a signed integer (between -128 and 127).
+    Args:
+        value:
+            A number to be represented as a fraction.
+    Returns:
+        A tuple of the form (numerator, denominator, exponent).
+    """
+    frac = Fraction(value)
+    max_allowed_frac = Fraction(2**15 - 1)
+    min_allowed_frac = 1 / max_allowed_frac
+    exponent = 0
+
+    # Shift the fraction into a normal range
+    while frac < min_allowed_frac:
+        exponent -= 1
+        frac *= 10
+    while frac > max_allowed_frac:
+        exponent += 1
+        frac /= 10
+
+    # Limit the denominator to 16 bits
+    frac = frac.limit_denominator(2**16 - 1)
+
+    # Adjust the exponent to make numerator fit in 16-bits
+    for _ in range(127):
+        if frac.numerator < 2**16 - 1:
+            break
+        exponent += 1
+        frac /= 10
+        frac = frac.limit_denominator(2**16 - 1)
+
+    # Give up if invalid at this point
+    if any(
+        [
+            frac.numerator > 2**16 - 1,
+            frac.denominator > 2**16 - 1,
+            exponent > 127,
+            exponent < -128,
+        ]
+    ):
+        raise ValueError(
+            "Could not represent resolution as an integer fraction."
+        )
+
+    return exponent, frac.numerator, frac.denominator


=====================================
glymur/version.py
=====================================
@@ -21,7 +21,7 @@ from .lib import tiff
 
 # Do not change the format of this next line!  Doing so risks breaking
 # setup.py
-version = "0.10.0"
+version = "0.10.1"
 
 version_tuple = parse(version).release
 


=====================================
setup.cfg
=====================================
@@ -1,6 +1,6 @@
 [metadata]
 name = Glymur
-version = 0.10.0
+version = 0.10.1
 author = 'John Evans'
 author_email = "John Evans" <john.g.evans.ne at gmail.com>
 license = 'MIT'


=====================================
tests/test_jp2box.py
=====================================
@@ -418,6 +418,105 @@ class TestFileTypeBox(fixtures.TestCommon):
                 Jp2k(tfile.name)
 
 
+class TestResolutionBoxes(fixtures.TestCommon):
+    """
+    Test suite for resolution boxes
+    """
+    def test_repr(self):
+        """
+        Verify __repr__ method on resolution boxes.
+        """
+        resc = glymur.jp2box.CaptureResolutionBox(0.5, 2.5)
+        resd = glymur.jp2box.DisplayResolutionBox(2.5, 0.5)
+        res_super_box = glymur.jp2box.ResolutionBox(box=[resc, resd])
+
+        newbox = eval(repr(res_super_box))
+
+        self.assertEqual(newbox.box_id, 'res ')
+        self.assertEqual(newbox.box[0].box_id, 'resc')
+        self.assertEqual(newbox.box[0].vertical_resolution, 0.5)
+        self.assertEqual(newbox.box[0].horizontal_resolution, 2.5)
+        self.assertEqual(newbox.box[1].box_id, 'resd')
+        self.assertEqual(newbox.box[1].vertical_resolution, 2.5)
+        self.assertEqual(newbox.box[1].horizontal_resolution, 0.5)
+
+    def test_resolution_superbox(self):
+        """
+        SCENARIO:  write a resolution superbox
+
+        Expected Results:  do not error out, can parse the written box
+        """
+        vres = 0.5
+        hres = 2.5
+        resc = glymur.jp2box.CaptureResolutionBox(vres, hres)
+        resd = glymur.jp2box.DisplayResolutionBox(vres, hres)
+        rbox = glymur.jp2box.ResolutionBox(box=[resc, resd])
+
+        with open(self.temp_jp2_filename, mode='wb') as tfile:
+            rbox.write(tfile)
+
+        with open(self.temp_jp2_filename, mode='rb') as tfile:
+            tfile.seek(8)
+            rbox_read = glymur.jp2box.ResolutionBox.parse(tfile, 0, 44)
+
+        self.assertEqual(rbox_read.box[0].vertical_resolution, vres)
+        self.assertEqual(rbox_read.box[0].horizontal_resolution, hres)
+        self.assertEqual(rbox_read.box[1].vertical_resolution, vres)
+        self.assertEqual(rbox_read.box[1].horizontal_resolution, hres)
+
+    def test_write_capture_resolution_box_high_res(self):
+        """
+        SCENARIO:  write a capture resolution box with no information other
+        than the floating point components.  The components have a very high
+        resolution.
+
+        Expected Results:  do not error out, can parse the written box
+        """
+        vres = 1.8738870547679375e+29
+        hres = 3333444444.44444
+        resc = glymur.jp2box.CaptureResolutionBox(vres, hres)
+
+        with open(self.temp_jp2_filename, mode='wb') as tfile:
+            resc.write(tfile)
+
+        with open(self.temp_jp2_filename, mode='rb') as tfile:
+            tfile.seek(8)
+            resc_read = glymur.jp2box.CaptureResolutionBox.parse(tfile, 8, 18)
+
+        np.testing.assert_allclose(
+            vres, resc_read.vertical_resolution, rtol=1e-6
+        )
+        np.testing.assert_allclose(
+            hres, resc_read.horizontal_resolution, rtol=1e-6
+        )
+
+    def test_write_capture_resolution_box_low_res(self):
+        """
+        SCENARIO:  write a capture resolution box with no information other
+        than the floating point components.  The components have a very low
+        resolution.
+
+        Expected Results:  do not error out, can parse the written box
+        """
+        vres = 1.8738870547679375e-29
+        hres = 0.333344444444444
+        resc = glymur.jp2box.CaptureResolutionBox(vres, hres)
+
+        with open(self.temp_jp2_filename, mode='wb') as tfile:
+            resc.write(tfile)
+
+        with open(self.temp_jp2_filename, mode='rb') as tfile:
+            tfile.seek(8)
+            resc_read = glymur.jp2box.CaptureResolutionBox.parse(tfile, 8, 18)
+
+        np.testing.assert_allclose(
+            vres, resc_read.vertical_resolution, rtol=1e-6
+        )
+        np.testing.assert_allclose(
+            hres, resc_read.horizontal_resolution, rtol=1e-6
+        )
+
+
 class TestPaletteBox(fixtures.TestCommon):
     """Test suite for pclr box instantiation."""
 
@@ -1179,22 +1278,6 @@ class TestRepr(MetadataBase):
         self.assertEqual(newbox.mapping_type, (1, 1, 1))
         self.assertEqual(newbox.palette_index, (0, 1, 2))
 
-    def test_resolution_boxes(self):
-        """Verify __repr__ method on resolution boxes."""
-        resc = glymur.jp2box.CaptureResolutionBox(0.5, 2.5)
-        resd = glymur.jp2box.DisplayResolutionBox(2.5, 0.5)
-        res_super_box = glymur.jp2box.ResolutionBox(box=[resc, resd])
-
-        newbox = eval(repr(res_super_box))
-
-        self.assertEqual(newbox.box_id, 'res ')
-        self.assertEqual(newbox.box[0].box_id, 'resc')
-        self.assertEqual(newbox.box[0].vertical_resolution, 0.5)
-        self.assertEqual(newbox.box[0].horizontal_resolution, 2.5)
-        self.assertEqual(newbox.box[1].box_id, 'resd')
-        self.assertEqual(newbox.box[1].vertical_resolution, 2.5)
-        self.assertEqual(newbox.box[1].horizontal_resolution, 0.5)
-
     def test_label_box(self):
         """Verify __repr__ method on label box."""
         lbl = glymur.jp2box.LabelBox("this is a test")



View it on GitLab: https://salsa.debian.org/debian-gis-team/glymur/-/commit/b1bd50c1987bb74b64ed0c0461bead57467f1739

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/glymur/-/commit/b1bd50c1987bb74b64ed0c0461bead57467f1739
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20220701/91785322/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list