[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