[Git][debian-gis-team/glymur][master] 5 commits: New upstream version 0.14.3

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Sun Aug 10 16:10:12 BST 2025



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


Commits:
e2297c5e by Antonio Valentino at 2025-08-08T06:10:25+00:00
New upstream version 0.14.3
- - - - -
95c69489 by Antonio Valentino at 2025-08-08T06:10:34+00:00
Update upstream source from tag 'upstream/0.14.3'

Update to upstream version '0.14.3'
with Debian dir e2f522501c7f6cf58633756cc7c7857ddfa5f64c
- - - - -
830e1b61 by Antonio Valentino at 2025-08-08T06:12:19+00:00
New upstream release

- - - - -
fb4a2983 by Antonio Valentino at 2025-08-10T15:08:30+00:00
Set upstream metadata fields: Documentation.

Changes-By: lintian-brush

- - - - -
a5b27e9b by Antonio Valentino at 2025-08-10T15:09:04+00:00
Set distribution to usntable

- - - - -


25 changed files:

- .circleci/config.yml
- CHANGES.txt
- debian/changelog
- debian/upstream/metadata
- docs/source/conf.py
- docs/source/how_do_i.rst
- docs/source/whatsnew/0.14.rst
- glymur/_core_converter.py
- glymur/jp2box.py
- glymur/jp2k.py
- glymur/jp2kr.py
- + glymur/lib/_tiff.py
- glymur/lib/tiff.py
- glymur/tiff.py
- glymur/version.py
- pyproject.toml
- tests/test_callbacks.py
- tests/test_commandline_tiff2jp2.py
- tests/test_jp2k.py
- tests/test_jp2k_writes.py
- tests/test_jp2kr.py
- tests/test_libtiff.py
- tests/test_printing.py
- tests/test_tiff2jp2.py
- tests/test_warnings.py


Changes:

=====================================
.circleci/config.yml
=====================================
@@ -42,6 +42,8 @@ test-template: &test-template
           export PATH=$HOME/miniconda/bin:$PATH
           source activate glymur
           pytest -n 4 -x
+          pytest --doctest-glob='*.rst' docs/source/how_do_i.rst
+          pytest --doctest-modules glymur
 
 jobs:
   travis-311-no-gdal:


=====================================
CHANGES.txt
=====================================
@@ -1,3 +1,13 @@
+Jun 12, 2025 - v0.14.3
+    Fix DeprecationWarning upon import
+
+Jun 12, 2025 - v0.14.2
+    Fix test suite for python 3.14 regular expressions
+    Remove long-since-deprecated Jp2kr.read method
+    Make Jp2kr.parse method private
+    Make glymur.lib.tiff module private
+    Add doctests into circleci config
+
 Apr 06, 2025 - v0.14.1
     Fix doc builds for API
     Add additional API examples for Jp2k, Jp2kr


=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+glymur (0.14.3-1) unstable; urgency=medium
+
+  * New upstream release.
+  * Set upstream metadata fields: Documentation.
+
+ -- Antonio Valentino <antonio.valentino at tiscali.it>  Sun, 10 Aug 2025 15:08:57 +0000
+
 glymur (0.14.1-1) unstable; urgency=medium
 
   * New upstream release.


=====================================
debian/upstream/metadata
=====================================
@@ -1,4 +1,5 @@
 Bug-Database: https://github.com/quintusdias/glymur/issues
 Bug-Submit: https://github.com/quintusdias/glymur/issues/new
+Documentation: https://glymur.readthedocs.io
 Repository: https://github.com/quintusdias/glymur.git
 Repository-Browse: https://github.com/quintusdias/glymur


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


=====================================
docs/source/how_do_i.rst
=====================================
@@ -771,7 +771,7 @@ are wrapped in a BytesIO object, which is fed to the most-excellent Pillow packa
     >>> from PIL import ImageCms
     >>> from io import BytesIO
     >>> # this assumes you have access to the test suite
-    >>> p = pathlib.Path('tests/data/text_GBR.jp2')
+    >>> p = pathlib.Path('tests/data/from-openjpeg/text_GBR.jp2')
     >>> # This next step may produce a harmless warning that has nothing to do with ICC profiles.
     >>> j = Jp2k(p)
     >>> # The 2nd sub box of the 4th box is a ColourSpecification box.


=====================================
docs/source/whatsnew/0.14.rst
=====================================
@@ -2,6 +2,22 @@
 Changes in glymur 0.14
 ######################
 
+*****************
+Changes in 0.14.3
+*****************
+
+    * Fix DeprecationWarning upon import
+
+*****************
+Changes in 0.14.2
+*****************
+
+    * Fix test suite for python 3.14 regular expressions
+    * Remove long-since-deprecated Jp2kr.read method
+    * Make Jp2kr.parse method private
+    * Make glymur.lib.tiff module private
+    * Add doctests into circleci config
+
 *****************
 Changes in 0.14.1
 *****************


=====================================
glymur/_core_converter.py
=====================================
@@ -9,7 +9,7 @@ from uuid import UUID
 
 # local imports
 from . import jp2box
-from .lib.tiff import DATATYPE2FMT
+from .lib._tiff import DATATYPE2FMT
 from .jp2k import Jp2k
 from glymur.core import RESTRICTED_ICC_PROFILE
 


=====================================
glymur/jp2box.py
=====================================
@@ -51,7 +51,7 @@ from .core import (
     ANY_ICC_PROFILE,
     VENDOR_COLOR_METHOD,
 )
-from .lib.tiff import tiff_header, BadTiffTagDatatype
+from .lib._tiff import tiff_header, BadTiffTagDatatype
 from . import get_option
 from ._iccprofile import _ICCProfile
 


=====================================
glymur/jp2k.py
=====================================
@@ -216,7 +216,7 @@ class Jp2k(Jp2kr):
         force : bool
             If true, then run finalize operations
         """
-        self.parse(force=force_parse)
+        self._parse(force=force_parse)
 
         if (
             self._capture_resolution is None
@@ -256,7 +256,7 @@ class Jp2k(Jp2kr):
         temp_filename = self.filename + ".tmp"
         self.wrap(temp_filename, boxes=self.box)
         shutil.move(temp_filename, self.filename)
-        self.parse(force=True)
+        self._parse(force=True)
 
     def _validate_kwargs(self):
         """Validate keyword parameters passed to the constructor."""
@@ -817,7 +817,7 @@ class Jp2k(Jp2kr):
         with self.path.open("ab") as ofile:
             box.write(ofile)
 
-        self.parse(force=True)
+        self._parse(force=True)
 
     def wrap(self, filename, boxes=None):
         """


=====================================
glymur/jp2kr.py
=====================================
@@ -107,7 +107,7 @@ class Jp2kr(Jp2kBox):
         if not self.path.exists():
             raise FileNotFoundError(f"{self.filename} does not exist.")
 
-        self.parse()
+        self._parse()
         self._initialize_shape()
 
     def _initialize_shape(self):
@@ -393,6 +393,15 @@ class Jp2kr(Jp2kBox):
         return "\n".join(metadata)
 
     def parse(self, force=False):
+        """
+        .. deprecated:: 0.15.0
+        """
+        breakpoint()
+        msg = "Deprecated, do not use."
+        warnings.warn(msg, DeprecationWarning)
+        self._parse(force=force)
+
+    def _parse(self, force=False):
         """Parses the JPEG 2000 file.
 
         Parameters
@@ -633,25 +642,6 @@ class Jp2kr(Jp2kBox):
         # Ok, 3 arguments in pargs.
         return data[:, :, bands]
 
-    def read(self, **kwargs):
-        """Read a JPEG 2000 image.
-
-        .. deprecated:: 0.13.5
-           Use numpy-style slicing instead.
-
-        Returns
-        -------
-        img_array : ndarray
-            The image data.
-        """
-
-        if "ignore_pclr_cmap_cdef" in kwargs:
-            self.ignore_pclr_cmap_cdef = kwargs["ignore_pclr_cmap_cdef"]
-            kwargs.pop("ignore_pclr_cmap_cdef")
-        warnings.warn("Use array-style slicing instead.", DeprecationWarning)
-        img = self._read(**kwargs)
-        return img
-
     def _subsampling_sanity_check(self):
         """Check for differing subsample factors."""
         if self._decoded_components is None:
@@ -854,7 +844,7 @@ class Jp2kr(Jp2kBox):
 
         The only time you should ever use this method is when the image has
         different subsampling factors across components.  Otherwise you should
-        use the read method.
+        use numpy-style slicing.
 
         Parameters
         ----------
@@ -966,7 +956,7 @@ class Jp2kr(Jp2kBox):
         return image
 
     def _component2dtype(self, component):
-        """Determin the appropriate numpy datatype for an OpenJPEG component.
+        """Determine the appropriate numpy datatype for an OpenJPEG component.
 
         Parameters
         ----------


=====================================
glymur/lib/_tiff.py
=====================================
@@ -0,0 +1,2142 @@
+# standard library imports
+from collections import OrderedDict
+import ctypes
+from enum import IntEnum
+import os
+import queue
+import re
+import struct
+import warnings
+
+# 3rd party library imports
+import numpy as np
+
+# Local imports
+from ..config import glymur_config
+
+# The error messages queue
+EQ = queue.Queue()
+
+loader = ctypes.windll.LoadLibrary if os.name == "nt" else ctypes.CDLL
+_LIBTIFF = glymur_config("tiff")
+_LIBC = glymur_config("c")
+
+
+class LibTIFFError(RuntimeError):
+    """Raise this exception if we detect a generic error from libtiff."""
+
+    pass
+
+
+class Compression(IntEnum):
+    """Compression scheme used on the image data.
+
+    See Also
+    --------
+    Photometric : The color space of the image data.
+    """
+
+    NONE = 1
+    CCITTRLE = 2  # CCITT modified Huffman RLE
+    CCITTFAX3 = 3  # CCITT Group 3 fax encoding
+    CCITT_T4 = 3  # CCITT T.4 (TIFF 6 name)
+    CCITTFAX4 = 4  # CCITT Group 4 fax encoding
+    CCITT_T6 = 4  # CCITT T.6 (TIFF 6 name)
+    LZW = 5  # Lempel-Ziv  & Welch
+    OJPEG = 6  # 6.0 JPEG
+    JPEG = 7  # JPEG DCT compression
+    T85 = 9  # TIFF/FX T.85 JBIG compression
+    T43 = 10  # TIFF/FX T.43 colour by layered JBIG compression
+    NEXT = 32766  # NeXT 2-bit RLE
+    CCITTRLEW = 32771  # #1 w/ word alignment
+    PACKBITS = 32773  # Macintosh RLE
+    THUNDERSCAN = 32809  # ThunderScan RLE
+    PIXARFILM = 32908  # companded 10bit LZW
+    PIXARLOG = 32909  # companded 11bit ZIP
+    DEFLATE = 32946  # compression
+    ADOBE_DEFLATE = 8  # compression, as recognized by Adobe
+    DCS = 32947  # DCS encoding
+    JBIG = 34661  # JBIG
+    SGILOG = 34676  # Log Luminance RLE
+    SGILOG24 = 34677  # Log 24-bit packed
+    JP2000 = 34712  # JPEG2000
+    LZMA = 34925  # LZMA2
+
+
+class InkSet(IntEnum):
+    """
+    The set of inks used in a separated (PhotometricInterpretation=5) image.
+    """
+
+    CMYK = 1
+    MULTIINK = 2
+
+
+class JPEGColorMode(IntEnum):
+    """When writing images with photometric interpretation equal to YCbCr and
+    compression equal to JPEG, the pseudo tag JPEGColorMode should usually be
+    set to RGB, unless the image values truly are in YCbCr.
+
+    See Also
+    --------
+    Photometric : The color space of the image data.
+    """
+
+    RAW = 0
+    RGB = 1
+
+
+class PlanarConfig(IntEnum):
+    """How the components of each pixel are stored.
+
+    Writing images with a PlanarConfig value of PlanarConfig.SEPARATE is not
+    currently supported.
+    """
+
+    CONTIG = 1  # single image plane
+    SEPARATE = 2  # separate planes of data
+
+
+class Orientation(IntEnum):
+    """The orientation of the image with respect to the rows and columns."""
+
+    TOPLEFT = 1  # row 0 top, col 0 lhs */
+    TOPRIGHT = 2  # row 0 top, col 0 rhs */
+    BOTRIGHT = 3  # row 0 bottom, col 0 rhs */
+    BOTLEFT = 4  # row 0 bottom, col 0 lhs */
+    LEFTTOP = 5  # row 0 lhs, col 0 top */
+    RIGHTTOP = 6  # row 0 rhs, col 0 top */
+    RIGHTBOT = 7  # row 0 rhs, col 0 bottom */
+    LEFTBOT = 8  # row 0 lhs, col 0 bottom */
+
+
+class Photometric(IntEnum):
+    """The color space of the image data."""
+
+    MINISWHITE = 0  # value is white
+    MINISBLACK = 1  # value is black
+    RGB = 2  # color model
+    PALETTE = 3  # map indexed
+    MASK = 4  # holdout mask
+    SEPARATED = 5  # color separations
+    YCBCR = 6  # CCIR 601
+    CIELAB = 8  # 1976 CIE L*a*b*
+    ICCLAB = 9  # L*a*b* [Adobe TIFF Technote 4]
+    ITULAB = 10  # L*a*b*
+    CFA = 32803  # filter array
+    LOGL = 32844  # Log2(L)
+    LOGLUV = 32845  # Log2(L) (u',v')
+
+
+class SampleFormat(IntEnum):
+    """Specifies how to interpret each data sample in a pixel."""
+
+    UINT = 1
+    INT = 2
+    IEEEFP = 3
+    VOID = 4
+    COMPLEXINT = 5
+    COMPLEXIEEEP = 6
+
+
+def _handle_error(module, fmt, ap):
+    # Use VSPRINTF in the C library to put together the error message.
+    # int vsprintf(char * buffer, const char * restrict format, va_list ap);
+    buffer = ctypes.create_string_buffer(1000)
+
+    argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p]
+    _LIBC.vsprintf.argtypes = argtypes
+    _LIBC.vsprintf.restype = ctypes.c_int32
+    _LIBC.vsprintf(buffer, fmt, ap)
+
+    module = module.decode("utf-8")
+    error_str = buffer.value.decode("utf-8")
+
+    message = f"{module}: {error_str}"
+    EQ.put(message)
+    return None
+
+
+def _handle_warning(module, fmt, ap):
+    # Use VSPRINTF in the C library to put together the warning message.
+    # int vsprintf(char * buffer, const char * restrict format, va_list ap);
+    buffer = ctypes.create_string_buffer(1000)
+
+    argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p]
+    _LIBC.vsprintf.argtypes = argtypes
+    _LIBC.vsprintf.restype = ctypes.c_int32
+    _LIBC.vsprintf(buffer, fmt, ap)
+
+    module = module.decode("utf-8")
+    warning_str = buffer.value.decode("utf-8")
+
+    message = f"{module}: {warning_str}"
+    warnings.warn(message)
+
+
+# Set the function types for the warning handler.
+_WFUNCTYPE = ctypes.CFUNCTYPE(
+    ctypes.c_void_p,  # return type of warning handler, void *
+    ctypes.c_char_p,  # module
+    ctypes.c_char_p,  # fmt
+    ctypes.c_void_p,  # va_list
+)
+
+_ERROR_HANDLER = _WFUNCTYPE(_handle_error)
+_WARNING_HANDLER = _WFUNCTYPE(_handle_warning)
+
+
+def _set_error_warning_handlers():
+    """Setup default python error and warning handlers."""
+    old_warning_handler = setWarningHandler()
+    old_error_handler = setErrorHandler()
+
+    return old_error_handler, old_warning_handler
+
+
+def _reset_error_warning_handlers(old_error_handler, old_warning_handler):
+    """Restore previous error and warning handlers."""
+    setWarningHandler(old_warning_handler)
+    setErrorHandler(old_error_handler)
+
+
+def close(fp):
+    """Corresponds to TIFFClose"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p]
+    _LIBTIFF.TIFFClose.argtypes = ARGTYPES
+    _LIBTIFF.TIFFClose.restype = None
+    _LIBTIFF.TIFFClose(fp)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+
+def computeStrip(fp, row, sample):
+    """Corresponds to TIFFComputeStrip"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint16]
+    _LIBTIFF.TIFFComputeStrip.argtypes = ARGTYPES
+    _LIBTIFF.TIFFComputeStrip.restype = ctypes.c_uint32
+    stripnum = _LIBTIFF.TIFFComputeStrip(fp, row, sample)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return stripnum
+
+
+def computeTile(fp, x, y, z, sample):
+    """Corresponds to TIFFComputeTile"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_uint32,
+        ctypes.c_uint32,
+        ctypes.c_uint16,
+    ]
+    _LIBTIFF.TIFFComputeTile.argtypes = ARGTYPES
+    _LIBTIFF.TIFFComputeTile.restype = ctypes.c_uint32
+    tilenum = _LIBTIFF.TIFFComputeTile(fp, x, y, z, sample)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return tilenum
+
+
+def isTiled(fp):
+    """Corresponds to TIFFIsTiled"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p]
+
+    _LIBTIFF.TIFFIsTiled.argtypes = ARGTYPES
+    _LIBTIFF.TIFFIsTiled.restype = ctypes.c_int
+
+    status = _LIBTIFF.TIFFIsTiled(fp)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return status
+
+
+def numberOfStrips(fp):
+    """Corresponds to TIFFNumberOfStrips."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p]
+    _LIBTIFF.TIFFNumberOfStrips.argtypes = ARGTYPES
+    _LIBTIFF.TIFFNumberOfStrips.restype = ctypes.c_uint32
+
+    numstrips = _LIBTIFF.TIFFNumberOfStrips(fp)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return numstrips
+
+
+def numberOfTiles(fp):
+    """Corresponds to TIFFNumberOfTiles."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p]
+    _LIBTIFF.TIFFNumberOfTiles.argtypes = ARGTYPES
+    _LIBTIFF.TIFFNumberOfTiles.restype = ctypes.c_uint32
+
+    numtiles = _LIBTIFF.TIFFNumberOfTiles(fp)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return numtiles
+
+
+def readEncodedStrip(fp, stripnum, strip, size=-1):
+    """Corresponds to TIFFReadEncodedStrip"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    if size == -1:
+        size = strip.nbytes
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_void_p,
+        ctypes.c_int32
+    ]
+    _LIBTIFF.TIFFReadEncodedStrip.argtypes = ARGTYPES
+    _LIBTIFF.TIFFReadEncodedStrip.restype = check_error
+    _LIBTIFF.TIFFReadEncodedStrip(
+        fp, stripnum, strip.ctypes.data_as(ctypes.c_void_p), size
+    )
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return strip
+
+
+def readEncodedTile(fp, tilenum, tile, size=-1):
+    """Corresponds to TIFFComputeTile"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    if size == -1:
+        size = tile.nbytes
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_void_p,
+        ctypes.c_int32
+    ]
+    _LIBTIFF.TIFFReadEncodedTile.argtypes = ARGTYPES
+    _LIBTIFF.TIFFReadEncodedTile.restype = check_error
+    _LIBTIFF.TIFFReadEncodedTile(
+        fp,
+        tilenum,
+        tile.ctypes.data_as(ctypes.c_void_p),
+        -1
+    )
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return tile
+
+
+def readRGBAStrip(fp, row, strip):
+    """Corresponds to TIFFReadRGBAStrip"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p]
+    _LIBTIFF.TIFFReadRGBAStrip.argtypes = ARGTYPES
+    _LIBTIFF.TIFFReadRGBAStrip.restype = check_error
+    _LIBTIFF.TIFFReadRGBAStrip(fp, row, strip.ctypes.data_as(ctypes.c_void_p))
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return strip
+
+
+def readRGBATile(fp, x, y, tile):
+    """Corresponds to TIFFReadRGBATile"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_uint32,
+        ctypes.c_void_p
+    ]
+    _LIBTIFF.TIFFReadRGBATile.argtypes = ARGTYPES
+    _LIBTIFF.TIFFReadRGBATile.restype = check_error
+    _LIBTIFF.TIFFReadRGBATile(fp, x, y, tile.ctypes.data_as(ctypes.c_void_p))
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return tile
+
+
+def readRGBAImageOriented(
+    fp,
+    width=None,
+    height=None,
+    orientation=Orientation.TOPLEFT
+):
+    """Read an image as if it were RGBA.
+
+    This function corresponds to the TIFFReadRGBAImageOriented function in the
+    libtiff library.
+
+    Parameters
+    ----------
+    fp : ctypes void pointer
+        File pointer returned by libtiff.
+    width, height : int
+        Width and height of the returned image.
+    orientation : int
+        The raster origin position.
+
+    See Also
+    --------
+    Orientation
+    """
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_uint32,
+        ctypes.POINTER(ctypes.c_uint32),
+        ctypes.c_int32,
+        ctypes.c_int32,
+    ]
+
+    _LIBTIFF.TIFFReadRGBAImageOriented.argtypes = ARGTYPES
+    _LIBTIFF.TIFFReadRGBAImageOriented.restype = check_error
+
+    if width is None:
+        width = getFieldDefaulted(fp, "ImageWidth")
+    if height is None:
+        height = getFieldDefaulted(fp, "ImageLength")
+
+    img = np.zeros((height, width, 4), dtype=np.uint8)
+    raster = img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))
+    _LIBTIFF.TIFFReadRGBAImageOriented(
+        fp,
+        width,
+        height,
+        raster,
+        orientation,
+        0
+    )
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return img
+
+
+def writeEncodedStrip(fp, stripnum, stripdata, size=-1):
+    """Corresponds to TIFFWriteEncodedStrip."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_void_p,
+        ctypes.c_uint32
+    ]
+    _LIBTIFF.TIFFWriteEncodedStrip.argtypes = ARGTYPES
+    _LIBTIFF.TIFFWriteEncodedStrip.restype = check_error
+    raster = stripdata.ctypes.data_as(ctypes.c_void_p)
+
+    if size == -1:
+        size = stripdata.nbytes
+
+    _LIBTIFF.TIFFWriteEncodedStrip(fp, stripnum, raster, size)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+
+def writeEncodedTile(fp, tilenum, tiledata, size=-1):
+    """Corresponds to TIFFWriteEncodedTile."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [
+        ctypes.c_void_p,
+        ctypes.c_uint32,
+        ctypes.c_void_p,
+        ctypes.c_uint32
+    ]
+    _LIBTIFF.TIFFWriteEncodedTile.argtypes = ARGTYPES
+    _LIBTIFF.TIFFWriteEncodedTile.restype = check_error
+    raster = tiledata.ctypes.data_as(ctypes.c_void_p)
+
+    if size == -1:
+        size = tiledata.nbytes
+
+    _LIBTIFF.TIFFWriteEncodedTile(fp, tilenum, raster, size)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+
+def RGBAImageOK(fp):
+    """Corresponds to TIFFRGBAImageOK."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    emsg = ctypes.create_string_buffer(1024)
+    ARGTYPES = [ctypes.c_void_p, ctypes.c_char_p]
+    _LIBTIFF.TIFFRGBAImageOK.argtypes = ARGTYPES
+    _LIBTIFF.TIFFRGBAImageOK.restype = ctypes.c_int
+    ok = _LIBTIFF.TIFFRGBAImageOK(fp, emsg)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    if ok:
+        return True
+    else:
+        return False
+
+
+def getFieldDefaulted(fp, tag):
+    """Corresponds to the TIFFGetFieldDefaulted library routine."""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p, ctypes.c_int32]
+
+    tag_num = TAGS[tag]["number"]
+
+    # Append the proper return type for the tag.
+    tag_type = TAGS[tag]["type"]
+    ARGTYPES.append(ctypes.POINTER(TAGS[tag]["type"]))
+    _LIBTIFF.TIFFGetFieldDefaulted.argtypes = ARGTYPES
+
+    _LIBTIFF.TIFFGetFieldDefaulted.restype = check_error
+
+    # instantiate the tag value
+    item = tag_type()
+    _LIBTIFF.TIFFGetFieldDefaulted(fp, tag_num, ctypes.byref(item))
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return item.value
+
+
+def getVersion():
+    """Corresponds to the TIFFGetVersion library routine."""
+    try:
+        _LIBTIFF.TIFFGetVersion.restype = ctypes.c_char_p
+    except AttributeError:
+        # libtiff not installed
+        return "0.0.0"
+
+    v = _LIBTIFF.TIFFGetVersion().decode("utf-8")
+
+    # v would be something like
+    #
+    # LIBTIFF, Version 4.3.0
+    # Copyright (c) 1988-1996 Sam Leffler
+    # Copyright (c) 1991-1996 Silicon Graphics, Inc.
+    #
+    # All we want is the '4.3.0'
+    m = re.search(r"(?P<version>\d+\.\d+\.\d+)", v)
+    return m.group("version")
+
+
+def open(filename, mode="r"):
+    """Corresponds to TIFFOpen
+
+    Parameters
+    ----------
+    filename : path or str
+        Path to TIFF
+    """
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    filename = str(filename)
+
+    ARGTYPES = [ctypes.c_char_p, ctypes.c_char_p]
+    _LIBTIFF.TIFFOpen.argtypes = ARGTYPES
+    _LIBTIFF.TIFFOpen.restype = ctypes.c_void_p
+    file_argument = ctypes.c_char_p(filename.encode())
+    mode_argument = ctypes.c_char_p(mode.encode())
+    fp = _LIBTIFF.TIFFOpen(file_argument, mode_argument)
+    check_error(fp)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+    return fp
+
+
+def setErrorHandler(func=_ERROR_HANDLER):
+    # The signature of the error handler is
+    #     const char *module, const char *fmt, va_list ap
+    #
+    # The return type is void *
+    _LIBTIFF.TIFFSetErrorHandler.argtypes = [_WFUNCTYPE]
+    _LIBTIFF.TIFFSetErrorHandler.restype = _WFUNCTYPE
+    old_error_handler = _LIBTIFF.TIFFSetErrorHandler(func)
+    return old_error_handler
+
+
+def setField(fp, tag, *value):
+    """Corresponds to TIFFSetField"""
+    err_handler, warn_handler = _set_error_warning_handlers()
+
+    ARGTYPES = [ctypes.c_void_p, ctypes.c_int32]
+
+    # Append the proper return type for the tag.
+    tag_num = TAGS[tag]["number"]
+    tag_type = TAGS[tag]["type"]
+
+    try:
+        for ttype in tag_type:
+            ARGTYPES.append(ttype)
+    except TypeError:
+        ARGTYPES.append(tag_type)
+
+    _LIBTIFF.TIFFSetField.argtypes = ARGTYPES
+    _LIBTIFF.TIFFSetField.restype = check_error
+
+    if len(value) == 1 and tag_type == ctypes.c_char_p:
+        _LIBTIFF.TIFFSetField(fp, tag_num, ctypes.c_char_p(value[0].encode()))
+    elif len(value) == 1:
+        _LIBTIFF.TIFFSetField(fp, tag_num, value[0])
+    else:
+        _LIBTIFF.TIFFSetField(fp, tag_num, *value)
+
+    _reset_error_warning_handlers(err_handler, warn_handler)
+
+
+def setWarningHandler(func=_WARNING_HANDLER):
+    # The signature of the warning handler is
+    #     const char *module, const char *fmt, va_list ap
+    #
+    # The return type is void *
+    _LIBTIFF.TIFFSetWarningHandler.argtypes = [_WFUNCTYPE]
+    _LIBTIFF.TIFFSetWarningHandler.restype = _WFUNCTYPE
+    old_warning_handler = _LIBTIFF.TIFFSetWarningHandler(func)
+    return old_warning_handler
+
+
+def check_error(status):
+    """Set a generic function as the restype attribute of all TIFF
+    functions that return a int value.  This way we do not have to check
+    for error status in each wrapping function and an exception will always be
+    appropriately raised.
+    """
+    msg = ""
+    while not EQ.empty():
+        msg = EQ.get()
+        raise LibTIFFError(msg)
+
+    if status == 0:
+        raise RuntimeError("failed")
+
+
+TAGS = {
+    "GPSVersionID": {
+        "number": 0,
+        "type": ctypes.c_char_p,
+    },
+    "GPSLatitudeRef": {
+        "number": 1,
+        "type": ctypes.c_char_p,
+    },
+    "GPSLatitude": {
+        "number": 2,
+        "type": ctypes.c_char_p,
+    },
+    "GPSLongitudeRef": {
+        "number": 3,
+        "type": ctypes.c_char_p,
+    },
+    "GPSLongitude": {
+        "number": 4,
+        "type": ctypes.c_char_p,
+    },
+    "GPSAltitudeRef": {
+        "number": 5,
+        "type": ctypes.c_char_p,
+    },
+    "GPSAltitude": {
+        "number": 6,
+        "type": ctypes.c_char_p,
+    },
+    "GPSTimestamp": {
+        "number": 7,
+        "type": ctypes.c_char_p,
+    },
+    "GPSSatellites": {
+        "number": 8,
+        "type": ctypes.c_char_p,
+    },
+    "GPSStatus": {
+        "number": 9,
+        "type": ctypes.c_char_p,
+    },
+    "GPSMeasureMode": {
+        "number": 10,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDOP": {
+        "number": 11,
+        "type": ctypes.c_char_p,
+    },
+    "GPSSpeedRef": {
+        "number": 12,
+        "type": ctypes.c_char_p,
+    },
+    "GPSSpeed": {
+        "number": 13,
+        "type": ctypes.c_char_p,
+    },
+    "GPSTrackRef": {
+        "number": 14,
+        "type": ctypes.c_char_p,
+    },
+    "GPSTrack": {
+        "number": 15,
+        "type": ctypes.c_char_p,
+    },
+    "GPSImgDirectionRef": {
+        "number": 16,
+        "type": ctypes.c_char_p,
+    },
+    "GPSImgDirection": {
+        "number": 17,
+        "type": ctypes.c_char_p,
+    },
+    "GPSMapDatum": {
+        "number": 18,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestLatitudeRef": {
+        "number": 19,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestLatitude": {
+        "number": 20,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestLongitudeRef": {
+        "number": 21,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestLongitude": {
+        "number": 22,
+        "type": ctypes.c_char_p,
+    },
+    "GPSBearingRef": {
+        "number": 23,
+        "type": ctypes.c_char_p,
+    },
+    "GPSBearing": {
+        "number": 24,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestDistanceRef": {
+        "number": 25,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDestDistance": {
+        "number": 26,
+        "type": ctypes.c_int16,
+    },
+    "GPSProcessingMethod": {
+        "number": 27,
+        "type": ctypes.c_char_p,
+    },
+    "GPSAreaInformation": {
+        "number": 28,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDateStamp": {
+        "number": 29,
+        "type": ctypes.c_char_p,
+    },
+    "GPSDifferential": {
+        "number": 30,
+        "type": ctypes.c_char_p,
+    },
+    "GPSHPositioningError": {
+        "number": 31,
+        "type": ctypes.c_int16,
+    },
+    "SubFileType": {
+        "number": 254,
+        "type": ctypes.c_int16,
+    },
+    "OSubFileType": {
+        "number": 255,
+        "type": ctypes.c_int16,
+    },
+    "ImageWidth": {
+        "number": 256,
+        "type": ctypes.c_int32,
+    },
+    "ImageLength": {
+        "number": 257,
+        "type": ctypes.c_int32,
+    },
+    "BitsPerSample": {
+        "number": 258,
+        "type": ctypes.c_int16,
+    },
+    "Compression": {
+        "number": 259,
+        "type": ctypes.c_int16,
+    },
+    "Photometric": {
+        "number": 262,
+        "type": ctypes.c_int16,
+    },
+    "Threshholding": {
+        "number": 263,
+        "type": ctypes.c_int16,
+    },
+    "CellWidth": {
+        "number": 264,
+        "type": ctypes.c_int16,
+    },
+    "CellLength": {
+        "number": 265,
+        "type": ctypes.c_int16,
+    },
+    "FillOrder": {
+        "number": 266,
+        "type": ctypes.c_int16,
+    },
+    "DocumentName": {
+        "number": 269,
+        "type": ctypes.c_char_p,
+    },
+    "ImageDescription": {
+        "number": 270,
+        "type": ctypes.c_char_p,
+    },
+    "Make": {
+        "number": 271,
+        "type": ctypes.c_char_p,
+    },
+    "Model": {
+        "number": 272,
+        "type": ctypes.c_char_p,
+    },
+    "StripOffsets": {
+        "number": 273,
+        "type": (ctypes.c_int32, ctypes.c_int64),
+    },
+    "Orientation": {
+        "number": 274,
+        "type": ctypes.c_int16,
+    },
+    "SamplesPerPixel": {
+        "number": 277,
+        "type": ctypes.c_int16,
+    },
+    "RowsPerStrip": {
+        "number": 278,
+        "type": ctypes.c_int16,
+    },
+    "StripByteCounts": {
+        "number": 279,
+        "type": None,
+    },
+    "MinSampleValue": {
+        "number": 280,
+        "type": ctypes.c_int16,
+    },
+    "MaxSampleValue": {
+        "number": 281,
+        "type": ctypes.c_int16,
+    },
+    "XResolution": {
+        "number": 282,
+        "type": ctypes.c_double,
+    },
+    "YResolution": {
+        "number": 283,
+        "type": ctypes.c_double,
+    },
+    "PlanarConfig": {
+        "number": 284,
+        "type": ctypes.c_int16,
+    },
+    "PageName": {
+        "number": 285,
+        "type": ctypes.c_char_p,
+    },
+    "XPosition": {
+        "number": 286,
+        "type": ctypes.c_double,
+    },
+    "YPosition": {
+        "number": 287,
+        "type": ctypes.c_double,
+    },
+    "FreeOffsets": {
+        "number": 288,
+        "type": ctypes.c_int32,
+    },
+    "FreeByteCounts": {
+        "number": 289,
+        "type": ctypes.c_int32,
+    },
+    "GrayResponseUnit": {
+        "number": 290,
+        "type": ctypes.c_int16,
+    },
+    "GrayResponseCurve": {
+        "number": 291,
+        "type": None,
+    },
+    "T4Options": {
+        "number": 292,
+        "type": None,
+    },
+    "T6Options": {
+        "number": 293,
+        "type": None,
+    },
+    "ResolutionUnit": {
+        "number": 296,
+        "type": ctypes.c_int16,
+    },
+    "PageNumber": {
+        "number": 297,
+        "type": (ctypes.c_int16, ctypes.c_uint16),
+    },
+    "TransferFunction": {
+        "number": 301,
+        "type": None,
+    },
+    "Software": {
+        "number": 305,
+        "type": ctypes.c_char_p,
+    },
+    "Datetime": {
+        "number": 306,
+        "type": ctypes.c_char_p,
+    },
+    "Artist": {
+        "number": 315,
+        "type": ctypes.c_char_p,
+    },
+    "HostComputer": {
+        "number": 316,
+        "type": ctypes.c_char_p,
+    },
+    "Predictor": {
+        "number": 317,
+        "type": ctypes.c_int16,
+    },
+    "WhitePoint": {
+        "number": 318,
+        "type": ctypes.c_double,
+    },
+    "PrimaryChromaticities": {
+        "number": 319,
+        "type": None,
+    },
+    "ColorMap": {
+        "number": 320,
+        "type": (ctypes.c_int16, ctypes.c_uint16),
+    },
+    "HalfToneHints": {
+        "number": 321,
+        "type": ctypes.c_int16,
+    },
+    "TileWidth": {
+        "number": 322,
+        "type": ctypes.c_int32,
+    },
+    "TileLength": {
+        "number": 323,
+        "type": ctypes.c_int32,
+    },
+    "TileOffsets": {
+        "number": 324,
+        "type": None,
+    },
+    "TileByteCounts": {
+        "number": 325,
+        "type": None,
+    },
+    "BadFaxLines": {
+        "number": 326,
+        "type": None,
+    },
+    "CleanFaxData": {
+        "number": 327,
+        "type": None,
+    },
+    "ConsecutiveBadFaxLines": {
+        "number": 328,
+        "type": None,
+    },
+    "SubIFDs": {
+        "number": 330,
+        "type": None,
+    },
+    "InkSet": {
+        "number": 332,
+        "type": ctypes.c_uint16,
+    },
+    "InkNames": {
+        "number": 333,
+        "type": ctypes.c_char_p,
+    },
+    "NumberOfInks": {
+        "number": 334,
+        "type": ctypes.c_uint16,
+    },
+    "DotRange": {
+        "number": 336,
+        "type": None,
+    },
+    "TargetPrinter": {
+        "number": 337,
+        "type": ctypes.c_uint16,
+    },
+    "ExtraSamples": {
+        "number": 338,
+        "type": ctypes.c_uint16,
+    },
+    "SampleFormat": {
+        "number": 339,
+        "type": ctypes.c_uint16,
+    },
+    "SMinSampleValue": {
+        "number": 340,
+        "type": ctypes.c_double,
+    },
+    "SMaxSampleValue": {
+        "number": 341,
+        "type": ctypes.c_double,
+    },
+    "TransferRange": {
+        "number": 342,
+        "type": None,
+    },
+    "ClipPath": {
+        "number": 343,
+        "type": None,
+    },
+    "XClipPathUnits": {
+        "number": 344,
+        "type": None,
+    },
+    "YClipPathUnits": {
+        "number": 345,
+        "type": None,
+    },
+    "Indexed": {
+        "number": 346,
+        "type": None,
+    },
+    "JPEGTables": {
+        "number": 347,
+        "type": None,
+    },
+    "OPIProxy": {
+        "number": 351,
+        "type": None,
+    },
+    "GlobalParametersIFD": {
+        "number": 400,
+        "type": None,
+    },
+    "ProfileType": {
+        "number": 401,
+        "type": None,
+    },
+    "FaxProfile": {
+        "number": 402,
+        "type": ctypes.c_uint8,
+    },
+    "CodingMethods": {
+        "number": 403,
+        "type": None,
+    },
+    "VersionYear": {
+        "number": 404,
+        "type": None,
+    },
+    "ModeNumber": {
+        "number": 405,
+        "type": None,
+    },
+    "Decode": {
+        "number": 433,
+        "type": None,
+    },
+    "DefaultImageColor": {
+        "number": 434,
+        "type": None,
+    },
+    "JPEGProc": {
+        "number": 512,
+        "type": None,
+    },
+    "JPEGInterchangeFormat": {
+        "number": 513,
+        "type": None,
+    },
+    "JPEGInterchangeFormatLength": {
+        "number": 514,
+        "type": None,
+    },
+    "JPEGRestartInterval": {
+        "number": 515,
+        "type": None,
+    },
+    "JPEGLosslessPredictors": {
+        "number": 517,
+        "type": None,
+    },
+    "JPEGPointTransforms": {
+        "number": 518,
+        "type": None,
+    },
+    "JPEGQTables": {
+        "number": 519,
+        "type": None,
+    },
+    "JPEGDCTables": {
+        "number": 520,
+        "type": None,
+    },
+    "JPEGACTables": {
+        "number": 521,
+        "type": None,
+    },
+    "YCbCrCoefficients": {
+        "number": 529,
+        "type": (ctypes.c_float, ctypes.c_float, ctypes.c_float),
+    },
+    "YCbCrSubsampling": {
+        "number": 530,
+        "type": (ctypes.c_uint16, ctypes.c_uint16),
+    },
+    "YCbCrPositioning": {
+        "number": 531,
+        "type": ctypes.c_uint16,
+    },
+    "ReferenceBlackWhite": {
+        "number": 532,
+        "type": (
+            ctypes.c_float,
+            ctypes.c_float,
+            ctypes.c_float,
+            ctypes.c_float,
+            ctypes.c_float,
+            ctypes.c_float,
+        ),
+    },
+    "StripRowCounts": {
+        "number": 559,
+        "type": None,
+    },
+    "XMLPacket": {
+        "number": 700,
+        "type": ctypes.c_uint8,
+    },
+    "ImageID": {
+        "number": 32781,
+        "type": None,
+    },
+    "Rating": {
+        "number": 18246,
+        "type": ctypes.c_uint16,
+    },
+    "RatingPercent": {
+        "number": 18249,
+        "type": ctypes.c_uint16,
+    },
+    "Datatype": {
+        "number": 32996,
+        "type": None,
+    },
+    "WANGAnnotation": {
+        "number": 32932,
+        "type": None,
+    },
+    "ImageDepth": {
+        "number": 32997,
+        "type": None,
+    },
+    "TileDepth": {
+        "number": 32998,
+        "type": None,
+    },
+    "CFARepeatPatternDim": {
+        "number": 33421,
+        "type": None,
+    },
+    "CFAPattern": {
+        "number": 33422,
+        "type": None,
+    },
+    "BatteryLevel": {
+        "number": 33423,
+        "type": None,
+    },
+    "Copyright": {
+        "number": 33432,
+        "type": ctypes.c_char_p,
+    },
+    "ExposureTime": {
+        "number": 33434,
+        "type": ctypes.c_double,
+    },
+    "FNumber": {
+        "number": 33437,
+        "type": ctypes.c_double,
+    },
+    "MDFile": {
+        "number": 33445,
+        "type": None,
+    },
+    "MDScalePixel": {
+        "number": 33446,
+        "type": None,
+    },
+    "MDColorTable": {
+        "number": 33447,
+        "type": None,
+    },
+    "MDLabName": {
+        "number": 33448,
+        "type": None,
+    },
+    "MDSampleInfo": {
+        "number": 33449,
+        "type": None,
+    },
+    "MdPrepDate": {
+        "number": 33450,
+        "type": None,
+    },
+    "MDPrepTime": {
+        "number": 33451,
+        "type": None,
+    },
+    "MDFileUnits": {
+        "number": 33452,
+        "type": None,
+    },
+    "ModelPixelScale": {
+        "number": 33550,
+        "type": None,
+    },
+    "IPTC": {
+        "number": 33723,
+        "type": None,
+    },
+    "INGRPacketData": {
+        "number": 33918,
+        "type": None,
+    },
+    "INGRFlagRegisters": {
+        "number": 33919,
+        "type": None,
+    },
+    "IRASbTransformationMatrix": {
+        "number": 33920,
+        "type": None,
+    },
+    "ModelTiePoint": {
+        "number": 33922,
+        "type": None,
+    },
+    "ModelTransformation": {
+        "number": 34264,
+        "type": None,
+    },
+    "Photoshop": {
+        "number": 34377,
+        "type": None,
+    },
+    "ExifTag": {
+        "number": 34665,
+        "type": ctypes.c_int32,
+    },
+    "ICCProfile": {
+        "number": 34675,
+        "type": None,
+    },
+    "ImageLayer": {
+        "number": 34732,
+        "type": None,
+    },
+    "GeoKeyDirectory": {
+        "number": 34735,
+        "type": None,
+    },
+    "GeoDoubleParams": {
+        "number": 34736,
+        "type": None,
+    },
+    "GeoAsciiParams": {
+        "number": 34737,
+        "type": None,
+    },
+    "ExposureProgram": {
+        "number": 34850,
+        "type": ctypes.c_uint16,
+    },
+    "SpectralSensitivity": {
+        "number": 34852,
+        "type": ctypes.c_char_p,
+    },
+    "GPSIFD": {
+        "number": 34853,
+        "type": None,
+    },
+    "ISOSpeedRatings": {
+        "number": 34855,
+        "type": ctypes.c_uint16,
+    },
+    "OECF": {
+        "number": 34856,
+        "type": None,
+    },
+    "Interlace": {
+        "number": 34857,
+        "type": None,
+    },
+    "TimeZoneOffset": {
+        "number": 34858,
+        "type": None,
+    },
+    "SelfTimerMode": {
+        "number": 34859,
+        "type": None,
+    },
+    "SensitivityType": {
+        "number": 34864,
+        "type": None,
+    },
+    "StandardOutputSensitivity": {
+        "number": 34865,
+        "type": None,
+    },
+    "RecommendedExposureIndex": {
+        "number": 34866,
+        "type": None,
+    },
+    "ISOSpeed": {
+        "number": 34867,
+        "type": None,
+    },
+    "ISOSpeedLatitudeYYY": {
+        "number": 34868,
+        "type": None,
+    },
+    "ISOSpeedLatitudeZZZ": {
+        "number": 34869,
+        "type": None,
+    },
+    "HYLAFAXRecvParams": {
+        "number": 34908,
+        "type": None,
+    },
+    "HYLAFAXSubAddress": {
+        "number": 34909,
+        "type": None,
+    },
+    "HYLAFAXRecvTime": {
+        "number": 34910,
+        "type": None,
+    },
+    "ExifVersion": {
+        "number": 36864,
+        "type": ctypes.c_uint8,
+    },
+    "DateTimeOriginal": {
+        "number": 36867,
+        "type": None,
+    },
+    "DateTimeDigitized": {
+        "number": 36868,
+        "type": None,
+    },
+    "OffsetTime": {
+        "number": 36880,
+        "type": None,
+    },
+    "OffsetTimeOriginal": {
+        "number": 36881,
+        "type": None,
+    },
+    "OffsetTimeDigitized": {
+        "number": 36882,
+        "type": None,
+    },
+    "ComponentsConfiguration": {"number": 37121, "type": None},
+    "CompressedBitsPerPixel": {
+        "number": 37122,
+        "type": ctypes.c_uint8,
+    },
+    "ShutterSpeedValue": {
+        "number": 37377,
+        "type": ctypes.c_double,
+    },
+    "ApertureValue": {
+        "number": 37378,
+        "type": ctypes.c_double,
+    },
+    "BrightnessValue": {
+        "number": 37379,
+        "type": ctypes.c_double,
+    },
+    "ExposureBiasValue": {
+        "number": 37380,
+        "type": ctypes.c_double,
+    },
+    "MaxApertureValue": {
+        "number": 37381,
+        "type": ctypes.c_double,
+    },
+    "SubjectDistance": {
+        "number": 37382,
+        "type": ctypes.c_double,
+    },
+    "MeteringMode": {
+        "number": 37383,
+        "type": ctypes.c_uint16,
+    },
+    "LightSource": {
+        "number": 37384,
+        "type": ctypes.c_uint16,
+    },
+    "Flash": {
+        "number": 37385,
+        "type": ctypes.c_uint16,
+    },
+    "FocalLength": {
+        "number": 37386,
+        "type": ctypes.c_double,
+    },
+    "Noise": {
+        "number": 37389,
+        "type": None,
+    },
+    "ImageNumber": {
+        "number": 37393,
+        "type": None,
+    },
+    "SecurityClassification": {
+        "number": 37394,
+        "type": None,
+    },
+    "ImageHistory": {
+        "number": 37395,
+        "type": None,
+    },
+    "TIFFEPStandardID": {
+        "number": 37398,
+        "type": None,
+    },
+    "MakerNote": {
+        "number": 37500,
+        "type": ctypes.c_char_p,
+    },
+    "UserComment": {
+        "number": 37510,
+        "type": ctypes.c_char_p,
+    },
+    "SubSecTime": {
+        "number": 37520,
+        "type": ctypes.c_char_p,
+    },
+    "SubSecTimeOriginal": {
+        "number": 37521,
+        "type": ctypes.c_char_p,
+    },
+    "SubSecTimeDigitized": {
+        "number": 37522,
+        "type": ctypes.c_char_p,
+    },
+    "ImageSourceData": {
+        "number": 37724,
+        "type": None,
+    },
+    "Temperature": {
+        "number": 37888,
+        "type": None,
+    },
+    "Humidity": {
+        "number": 37889,
+        "type": None,
+    },
+    "Pressure": {
+        "number": 37890,
+        "type": None,
+    },
+    "WaterDepth": {
+        "number": 37891,
+        "type": None,
+    },
+    "Acceleration": {
+        "number": 37892,
+        "type": None,
+    },
+    "CameraElevationAngle": {
+        "number": 37893,
+        "type": None,
+    },
+    "XPTitle": {
+        "number": 40091,
+        "type": None,
+    },
+    "XPComment": {
+        "number": 40092,
+        "type": None,
+    },
+    "XPAuthor": {
+        "number": 40093,
+        "type": None,
+    },
+    "XPKeywords": {
+        "number": 40094,
+        "type": None,
+    },
+    "XPSubject": {
+        "number": 40095,
+        "type": None,
+    },
+    "FlashPixVersion": {
+        "number": 40960,
+        "type": None,
+    },
+    "ColorSpace": {
+        "number": 40961,
+        "type": ctypes.c_uint16,
+    },
+    "PixelXDimension": {
+        "number": 40962,
+        "type": ctypes.c_uint64,
+    },
+    "PixelYDimension": {
+        "number": 40963,
+        "type": ctypes.c_uint64,
+    },
+    "InteroperabilityIFD": {
+        "number": 40965,
+        "type": None,
+    },
+    "FocalPlaneXResolution": {
+        "number": 41486,
+        "type": ctypes.c_double,
+    },
+    "FocalPlaneYResolution": {
+        "number": 41487,
+        "type": ctypes.c_double,
+    },
+    "FocalPlaneResolutionUnit": {
+        "number": 41488,
+        "type": ctypes.c_uint16,
+    },
+    "ExposureIndex": {
+        "number": 41493,
+        "type": ctypes.c_double,
+    },
+    "SensingMethod": {
+        "number": 41495,
+        "type": ctypes.c_uint16,
+    },
+    "SceneType": {
+        "number": 41729,
+        "type": ctypes.c_uint8,
+    },
+    "FlashEnergy": {"number": 41483, "type": None},
+    "SpatialFrequencyResponse": {"number": 41484, "type": None},
+    "SubjectLocation": {"number": 41492, "type": None},
+    "FileSource": {"number": 41728, "type": None},
+    "ExifCFAPattern": {"number": 41730, "type": None},
+    "CustomRendered": {"number": 41985, "type": None},
+    "ExposureMode": {
+        "number": 41986,
+        "type": ctypes.c_uint16,
+    },
+    "WhiteBalance": {
+        "number": 41987,
+        "type": ctypes.c_uint16,
+    },
+    "DigitalZoomRatio": {
+        "number": 41988,
+        "type": ctypes.c_double,
+    },
+    "FocalLengthIn35mmFilm": {
+        "number": 41989,
+        "type": ctypes.c_uint16,
+    },
+    "SceneCaptureType": {
+        "number": 41990,
+        "type": ctypes.c_uint16,
+    },
+    "GainControl": {
+        "number": 41991,
+        "type": ctypes.c_uint16,
+    },
+    "Contrast": {
+        "number": 41992,
+        "type": ctypes.c_uint16,
+    },
+    "Saturation": {
+        "number": 41993,
+        "type": ctypes.c_uint16,
+    },
+    "Sharpness": {
+        "number": 41994,
+        "type": ctypes.c_uint16,
+    },
+    "DeviceSettingDescription": {
+        "number": 41995,
+        "type": ctypes.c_char_p,
+    },
+    "SubjectDistanceRange": {
+        "number": 41996,
+        "type": ctypes.c_uint16,
+    },
+    "ImageUniqueID": {"number": 42016, "type": None},
+    "CameraOwnerName": {"number": 42032, "type": None},
+    "BodySerialNumber": {"number": 42033, "type": None},
+    "LensSpecification": {"number": 42034, "type": None},
+    "LensMake": {"number": 42035, "type": None},
+    "LensModel": {"number": 42036, "type": None},
+    "LensSerialNumber": {"number": 42037, "type": None},
+    "CompositeImage": {"number": 42080, "type": None},
+    "SourceImageNumberOfCompositeImage": {"number": 42081, "type": None},
+    "SourceExposureTimeOfCompositeImage": {"number": 42082, "type": None},
+    "GDAL_Metadata": {
+        "number": 42112,
+        "type": None,
+    },
+    "GDAL_NoData": {
+        "number": 42113,
+        "type": None,
+    },
+    "Gamma": {
+        "number": 42240,
+        "type": None,
+    },
+    "OCEScanJobDescription": {
+        "number": 50215,
+        "type": None,
+    },
+    "OCEApplicationSelector": {
+        "number": 50216,
+        "type": None,
+    },
+    "OCEIdentificationNumber": {
+        "number": 50217,
+        "type": None,
+    },
+    "OCEImageLogicCharacteristics": {
+        "number": 50218,
+        "type": None,
+    },
+    "PrintImageMatching": {
+        "number": 50341,
+        "type": None,
+    },
+    "DNGVersion": {
+        "number": 50706,
+        "type": None,
+    },
+    "DNGBackwardVersion": {
+        "number": 50707,
+        "type": None,
+    },
+    "UniqueCameraModel": {
+        "number": 50708,
+        "type": None,
+    },
+    "LocalizedCameraModel": {
+        "number": 50709,
+        "type": None,
+    },
+    "CFAPlaneColor": {
+        "number": 50710,
+        "type": None,
+    },
+    "CFALayout": {
+        "number": 50711,
+        "type": None,
+    },
+    "LinearizationTable": {
+        "number": 50712,
+        "type": None,
+    },
+    "BlackLevelRepeatDim": {
+        "number": 50713,
+        "type": None,
+    },
+    "BlackLevel": {
+        "number": 50714,
+        "type": None,
+    },
+    "BlackLevelDeltaH": {
+        "number": 50715,
+        "type": None,
+    },
+    "BlackLevelDeltaV": {
+        "number": 50716,
+        "type": None,
+    },
+    "WhiteLevel": {
+        "number": 50717,
+        "type": None,
+    },
+    "DefaultScale": {
+        "number": 50718,
+        "type": None,
+    },
+    "DefaultCropOrigin": {
+        "number": 50719,
+        "type": None,
+    },
+    "DefaultCropSize": {
+        "number": 50720,
+        "type": None,
+    },
+    "ColorMatrix1": {
+        "number": 50721,
+        "type": None,
+    },
+    "ColorMatrix2": {
+        "number": 50722,
+        "type": None,
+    },
+    "CameraCalibration1": {
+        "number": 50723,
+        "type": None,
+    },
+    "CameraCalibration2": {
+        "number": 50724,
+        "type": None,
+    },
+    "ReductionMatrix1": {
+        "number": 50725,
+        "type": None,
+    },
+    "ReductionMatrix2": {
+        "number": 50726,
+        "type": None,
+    },
+    "AnalogBalance": {
+        "number": 50727,
+        "type": None,
+    },
+    "AsShotNeutral": {
+        "number": 50728,
+        "type": None,
+    },
+    "AsShotWhiteXY": {
+        "number": 50729,
+        "type": None,
+    },
+    "BaselineExposure": {
+        "number": 50730,
+        "type": None,
+    },
+    "BaselineNoise": {
+        "number": 50731,
+        "type": None,
+    },
+    "BaselineSharpness": {
+        "number": 50732,
+        "type": None,
+    },
+    "BayerGreenSplit": {
+        "number": 50733,
+        "type": None,
+    },
+    "LinearResponseLimit": {
+        "number": 50734,
+        "type": None,
+    },
+    "CameraSerialNumber": {
+        "number": 50735,
+        "type": None,
+    },
+    "LensInfo": {
+        "number": 50736,
+        "type": None,
+    },
+    "ChromaBlurRadius": {
+        "number": 50737,
+        "type": None,
+    },
+    "AntiAliasStrength": {
+        "number": 50738,
+        "type": None,
+    },
+    "ShadowScale": {
+        "number": 50739,
+        "type": None,
+    },
+    "DNGPrivateData": {
+        "number": 50740,
+        "type": None,
+    },
+    "MakerNoteSafety": {
+        "number": 50741,
+        "type": None,
+    },
+    "CalibrationIllumintant1": {
+        "number": 50778,
+        "type": None,
+    },
+    "CalibrationIllumintant2": {
+        "number": 50779,
+        "type": None,
+    },
+    "BestQualityScale": {
+        "number": 50780,
+        "type": None,
+    },
+    "RawDataUniqueID": {
+        "number": 50781,
+        "type": None,
+    },
+    "AliasLayerMetadata": {
+        "number": 50784,
+        "type": None,
+    },
+    "OriginalRawFileName": {
+        "number": 50827,
+        "type": None,
+    },
+    "OriginalRawFileData": {
+        "number": 50828,
+        "type": None,
+    },
+    "ActiveArea": {
+        "number": 50829,
+        "type": None,
+    },
+    "MaskedAreas": {
+        "number": 50830,
+        "type": None,
+    },
+    "AsShotICCProfile": {
+        "number": 50831,
+        "type": None,
+    },
+    "AsShotPreProfileMatrix": {
+        "number": 50832,
+        "type": None,
+    },
+    "CurrentICCProfile": {
+        "number": 50833,
+        "type": None,
+    },
+    "CurrentPreProfileMatrix": {
+        "number": 50834,
+        "type": None,
+    },
+    "ColorimetricReference": {
+        "number": 50839,
+        "type": None,
+    },
+    "TIFF_RSID": {
+        "number": 50908,
+        "type": None,
+    },
+    "GEO_Metadata": {
+        "number": 50909,
+        "type": None,
+    },
+    "CameraCalibrationSignature": {
+        "number": 50931,
+        "type": None,
+    },
+    "ProfileCalibrationSignature": {
+        "number": 50932,
+        "type": None,
+    },
+    "AsShotProfileName": {
+        "number": 50934,
+        "type": None,
+    },
+    "NoiseReductionApplied": {
+        "number": 50935,
+        "type": None,
+    },
+    "ProfileName": {
+        "number": 50936,
+        "type": None,
+    },
+    "ProfileHueSatMapDims": {
+        "number": 50937,
+        "type": None,
+    },
+    "ProfileHueSatMapData1": {
+        "number": 50938,
+        "type": None,
+    },
+    "ProfileHueSatMapData2": {
+        "number": 50939,
+        "type": None,
+    },
+    "ProfileToneCurve": {
+        "number": 50940,
+        "type": None,
+    },
+    "ProfileEmbedPolicy": {
+        "number": 50941,
+        "type": None,
+    },
+    "ProfileCopyright": {
+        "number": 50942,
+        "type": None,
+    },
+    "ForwardMatrix1": {
+        "number": 50964,
+        "type": None,
+    },
+    "ForwardMatrix2": {
+        "number": 50965,
+        "type": None,
+    },
+    "PreviewApplicationName": {
+        "number": 50966,
+        "type": None,
+    },
+    "PreviewApplicationVersion": {
+        "number": 50967,
+        "type": None,
+    },
+    "PreviewSettingsName": {
+        "number": 50968,
+        "type": None,
+    },
+    "PreviewSettingsDigest": {
+        "number": 50969,
+        "type": None,
+    },
+    "PreviewColorSpace": {
+        "number": 50970,
+        "type": None,
+    },
+    "PreviewDateTime": {
+        "number": 50971,
+        "type": None,
+    },
+    "RawImageDigest": {
+        "number": 50972,
+        "type": None,
+    },
+    "OriginalRawFileDigest": {
+        "number": 50973,
+        "type": None,
+    },
+    "SubTileBlockSize": {
+        "number": 50974,
+        "type": None,
+    },
+    "RowInterleaveFactor": {
+        "number": 50975,
+        "type": None,
+    },
+    "ProfileLookTableDims": {
+        "number": 50981,
+        "type": None,
+    },
+    "ProfileLookTableData": {
+        "number": 50982,
+        "type": None,
+    },
+    "OpcodeList1": {
+        "number": 51008,
+        "type": None,
+    },
+    "OpcodeList2": {
+        "number": 51009,
+        "type": None,
+    },
+    "OpcodeList3": {
+        "number": 51022,
+        "type": None,
+    },
+    "NoiseProfile": {
+        "number": 51041,
+        "type": None,
+    },
+    "JPEGQuality": {
+        "number": 65537,
+        "type": ctypes.c_int32,
+    },
+    "JPEGColorMode": {
+        "number": 65538,
+        "type": ctypes.c_int32,
+    },
+}
+
+# We need the reverse mapping as well.
+TAGNUM2NAME = {value["number"]: key for key, value in TAGS.items()}
+
+
+def tiff_header(read_buffer):
+    """Interpret the uuid raw data as a tiff header."""
+    # First 8 should be (73, 73, 42, 8) or (77, 77, 42, 8)
+    data = struct.unpack("BB", read_buffer[0:2])
+    if data[0] == 73 and data[1] == 73:
+        # little endian
+        endian = "<"
+    elif data[0] == 77 and data[1] == 77:
+        # big endian
+        endian = ">"
+    else:
+        msg = (
+            f"The byte order indication in the TIFF header "
+            f"({read_buffer[0:2]}) is invalid.  It should be either "
+            f"{bytes([73, 73])} or {bytes([77, 77])}."
+        )
+        raise RuntimeError(msg)
+
+    _, offset = struct.unpack(endian + "HI", read_buffer[2:8])
+
+    # This is the 'Exif Image' portion.
+    return _Ifd(endian, read_buffer, offset).processed_ifd
+
+
+class BadTiffTagDatatype(RuntimeError):
+    """This exception exists soley to better communicate up the stack that the
+    problem exists.
+    """
+
+    pass
+
+
+class _Ifd(object):
+    """Corresponds to TIFF IFD data structure on file.
+
+    Attributes
+    ----------
+    read_buffer : bytes
+        Raw byte stream consisting of the UUID data.
+    endian : str
+        Either '<' for big-endian, or '>' for little-endian.
+    num_tags : int
+        Number of tags in the IFD.
+    raw_ifd : dictionary
+        Maps tag number to "mildly-interpreted" tag value.
+    processed_ifd : dictionary
+        Maps tag name to "mildly-interpreted" tag value.
+    """
+
+    def __init__(self, endian, read_buffer, offset):
+        self.endian = endian
+        self.read_buffer = read_buffer
+        self.processed_ifd = OrderedDict()
+
+        (self.num_tags,) = struct.unpack(
+            endian + "H",
+            read_buffer[offset:offset + 2]
+        )
+
+        fmt = self.endian + "HHII" * self.num_tags
+        ifd_buffer = read_buffer[offset + 2:offset + 2 + self.num_tags * 12]
+        data = struct.unpack(fmt, ifd_buffer)
+        self.raw_ifd = OrderedDict()
+        for j, tag in enumerate(data[0::4]):
+            # The offset to the tag offset/payload is the offset to the IFD
+            # plus 2 bytes for the number of tags plus 12 bytes for each
+            # tag entry plus 8 bytes to the offset/payload itself.
+            toffp = read_buffer[offset + 10 + j * 12:offset + 10 + j * 12 + 4]
+            self.raw_ifd[tag] = self.parse_tag(
+                tag, data[j * 4 + 1], data[j * 4 + 2], toffp
+            )
+
+        self.post_process()
+
+    def parse_tag(self, tag, dtype, count, offset_buf):
+        """Interpret an Exif image tag data payload."""
+
+        try:
+            fmt = DATATYPE2FMT[dtype]["format"] * count
+            payload_size = DATATYPE2FMT[dtype]["nbytes"] * count
+        except KeyError:
+            msg = f"Invalid TIFF tag datatype ({dtype})."
+            raise BadTiffTagDatatype(msg)
+
+        if payload_size <= 4:
+            # Interpret the payload from the 4 bytes in the tag entry.
+            target_buffer = offset_buf[:payload_size]
+        else:
+            # Interpret the payload at the offset specified by the 4 bytes in
+            # the tag entry.
+            (offset,) = struct.unpack(self.endian + "I", offset_buf)
+            target_buffer = self.read_buffer[offset:offset + payload_size]
+
+        if dtype == 2:
+            # ASCII
+            payload = target_buffer.decode("utf-8").rstrip("\x00")
+
+        else:
+            payload = struct.unpack(self.endian + fmt, target_buffer)
+            if dtype == 5 or dtype == 10:
+                # Rational or Signed Rational.  Construct the list of values.
+                rational_payload = []
+                for j in range(count):
+                    try:
+                        value = float(payload[j * 2]) / float(payload[j * 2 + 1])  # noqa : E501
+                    except ZeroDivisionError:
+                        value = np.nan
+                    rational_payload.append(value)
+                payload = np.array(rational_payload)
+            if count == 1:
+                # If just a single value, then return a scalar instead of a
+                # tuple.
+                payload = payload[0]
+            else:
+                payload = np.array(
+                    payload, dtype=DATATYPE2FMT[dtype]["nptype"]
+                )
+
+        return payload
+
+    def post_process(self):
+        """Map the tag name instead of tag number to the tag value."""
+        for tag, value in self.raw_ifd.items():
+            try:
+                tag_name = TAGNUM2NAME[tag]
+            except KeyError:
+                # Ok, we don't recognize this tag.  Just use the numeric id.
+                msg = f"Unrecognized UUID box TIFF tag ({tag})."
+                warnings.warn(msg, UserWarning)
+                tag_name = tag
+
+            if tag_name in ("ExifTag", 'GPSIFD'):
+                # There's an IFD at the offset specified here.
+                ifd = _Ifd(self.endian, self.read_buffer, value)
+                self.processed_ifd[tag_name] = ifd.processed_ifd
+            else:
+                # just a regular tag, treat it as a simple value
+                self.processed_ifd[tag_name] = value
+
+
+# maps the TIFF enumerated datatype to the corresponding structs datatype code,
+# the data width, and the corresponding numpy datatype
+DATATYPE2FMT = {
+    1: {"format": "B", "nbytes": 1, "nptype": np.ubyte},
+    2: {"format": "B", "nbytes": 1, "nptype": str},
+    3: {"format": "H", "nbytes": 2, "nptype": np.uint16},
+    4: {"format": "I", "nbytes": 4, "nptype": np.uint32},
+    5: {"format": "II", "nbytes": 8, "nptype": np.double},
+    6: {"format": "b", "nbytes": 1, "nptype": np.int8},
+    7: {"format": "B", "nbytes": 1, "nptype": np.uint8},
+    8: {"format": "h", "nbytes": 2, "nptype": np.int16},
+    9: {"format": "i", "nbytes": 4, "nptype": np.int32},
+    10: {"format": "ii", "nbytes": 8, "nptype": np.double},
+    11: {"format": "f", "nbytes": 4, "nptype": np.double},
+    12: {"format": "d", "nbytes": 8, "nptype": np.double},
+    13: {"format": "I", "nbytes": 4, "nptype": np.uint32},
+    16: {"format": "Q", "nbytes": 8, "nptype": np.uint64},
+    17: {"format": "q", "nbytes": 8, "nptype": np.int64},
+    18: {"format": "Q", "nbytes": 8, "nptype": np.uint64},
+}


=====================================
glymur/lib/tiff.py
=====================================
@@ -1,2142 +1,10 @@
+"""
+This module is deprecated.  No external use, please.
+"""
 # standard library imports
-from collections import OrderedDict
-import ctypes
-from enum import IntEnum
-import os
-import queue
-import re
-import struct
 import warnings
 
-# 3rd party library imports
-import numpy as np
+from ._tiff import *  # noqa : F401, F403
 
-# Local imports
-from ..config import glymur_config
-
-# The error messages queue
-EQ = queue.Queue()
-
-loader = ctypes.windll.LoadLibrary if os.name == "nt" else ctypes.CDLL
-_LIBTIFF = glymur_config("tiff")
-_LIBC = glymur_config("c")
-
-
-class LibTIFFError(RuntimeError):
-    """Raise this exception if we detect a generic error from libtiff."""
-
-    pass
-
-
-class Compression(IntEnum):
-    """Compression scheme used on the image data.
-
-    See Also
-    --------
-    Photometric : The color space of the image data.
-    """
-
-    NONE = 1
-    CCITTRLE = 2  # CCITT modified Huffman RLE
-    CCITTFAX3 = 3  # CCITT Group 3 fax encoding
-    CCITT_T4 = 3  # CCITT T.4 (TIFF 6 name)
-    CCITTFAX4 = 4  # CCITT Group 4 fax encoding
-    CCITT_T6 = 4  # CCITT T.6 (TIFF 6 name)
-    LZW = 5  # Lempel-Ziv  & Welch
-    OJPEG = 6  # 6.0 JPEG
-    JPEG = 7  # JPEG DCT compression
-    T85 = 9  # TIFF/FX T.85 JBIG compression
-    T43 = 10  # TIFF/FX T.43 colour by layered JBIG compression
-    NEXT = 32766  # NeXT 2-bit RLE
-    CCITTRLEW = 32771  # #1 w/ word alignment
-    PACKBITS = 32773  # Macintosh RLE
-    THUNDERSCAN = 32809  # ThunderScan RLE
-    PIXARFILM = 32908  # companded 10bit LZW
-    PIXARLOG = 32909  # companded 11bit ZIP
-    DEFLATE = 32946  # compression
-    ADOBE_DEFLATE = 8  # compression, as recognized by Adobe
-    DCS = 32947  # DCS encoding
-    JBIG = 34661  # JBIG
-    SGILOG = 34676  # Log Luminance RLE
-    SGILOG24 = 34677  # Log 24-bit packed
-    JP2000 = 34712  # JPEG2000
-    LZMA = 34925  # LZMA2
-
-
-class InkSet(IntEnum):
-    """
-    The set of inks used in a separated (PhotometricInterpretation=5) image.
-    """
-
-    CMYK = 1
-    MULTIINK = 2
-
-
-class JPEGColorMode(IntEnum):
-    """When writing images with photometric interpretation equal to YCbCr and
-    compression equal to JPEG, the pseudo tag JPEGColorMode should usually be
-    set to RGB, unless the image values truly are in YCbCr.
-
-    See Also
-    --------
-    Photometric : The color space of the image data.
-    """
-
-    RAW = 0
-    RGB = 1
-
-
-class PlanarConfig(IntEnum):
-    """How the components of each pixel are stored.
-
-    Writing images with a PlanarConfig value of PlanarConfig.SEPARATE is not
-    currently supported.
-    """
-
-    CONTIG = 1  # single image plane
-    SEPARATE = 2  # separate planes of data
-
-
-class Orientation(IntEnum):
-    """The orientation of the image with respect to the rows and columns."""
-
-    TOPLEFT = 1  # row 0 top, col 0 lhs */
-    TOPRIGHT = 2  # row 0 top, col 0 rhs */
-    BOTRIGHT = 3  # row 0 bottom, col 0 rhs */
-    BOTLEFT = 4  # row 0 bottom, col 0 lhs */
-    LEFTTOP = 5  # row 0 lhs, col 0 top */
-    RIGHTTOP = 6  # row 0 rhs, col 0 top */
-    RIGHTBOT = 7  # row 0 rhs, col 0 bottom */
-    LEFTBOT = 8  # row 0 lhs, col 0 bottom */
-
-
-class Photometric(IntEnum):
-    """The color space of the image data."""
-
-    MINISWHITE = 0  # value is white
-    MINISBLACK = 1  # value is black
-    RGB = 2  # color model
-    PALETTE = 3  # map indexed
-    MASK = 4  # holdout mask
-    SEPARATED = 5  # color separations
-    YCBCR = 6  # CCIR 601
-    CIELAB = 8  # 1976 CIE L*a*b*
-    ICCLAB = 9  # L*a*b* [Adobe TIFF Technote 4]
-    ITULAB = 10  # L*a*b*
-    CFA = 32803  # filter array
-    LOGL = 32844  # Log2(L)
-    LOGLUV = 32845  # Log2(L) (u',v')
-
-
-class SampleFormat(IntEnum):
-    """Specifies how to interpret each data sample in a pixel."""
-
-    UINT = 1
-    INT = 2
-    IEEEFP = 3
-    VOID = 4
-    COMPLEXINT = 5
-    COMPLEXIEEEP = 6
-
-
-def _handle_error(module, fmt, ap):
-    # Use VSPRINTF in the C library to put together the error message.
-    # int vsprintf(char * buffer, const char * restrict format, va_list ap);
-    buffer = ctypes.create_string_buffer(1000)
-
-    argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p]
-    _LIBC.vsprintf.argtypes = argtypes
-    _LIBC.vsprintf.restype = ctypes.c_int32
-    _LIBC.vsprintf(buffer, fmt, ap)
-
-    module = module.decode("utf-8")
-    error_str = buffer.value.decode("utf-8")
-
-    message = f"{module}: {error_str}"
-    EQ.put(message)
-    return None
-
-
-def _handle_warning(module, fmt, ap):
-    # Use VSPRINTF in the C library to put together the warning message.
-    # int vsprintf(char * buffer, const char * restrict format, va_list ap);
-    buffer = ctypes.create_string_buffer(1000)
-
-    argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p]
-    _LIBC.vsprintf.argtypes = argtypes
-    _LIBC.vsprintf.restype = ctypes.c_int32
-    _LIBC.vsprintf(buffer, fmt, ap)
-
-    module = module.decode("utf-8")
-    warning_str = buffer.value.decode("utf-8")
-
-    message = f"{module}: {warning_str}"
-    warnings.warn(message)
-
-
-# Set the function types for the warning handler.
-_WFUNCTYPE = ctypes.CFUNCTYPE(
-    ctypes.c_void_p,  # return type of warning handler, void *
-    ctypes.c_char_p,  # module
-    ctypes.c_char_p,  # fmt
-    ctypes.c_void_p,  # va_list
-)
-
-_ERROR_HANDLER = _WFUNCTYPE(_handle_error)
-_WARNING_HANDLER = _WFUNCTYPE(_handle_warning)
-
-
-def _set_error_warning_handlers():
-    """Setup default python error and warning handlers."""
-    old_warning_handler = setWarningHandler()
-    old_error_handler = setErrorHandler()
-
-    return old_error_handler, old_warning_handler
-
-
-def _reset_error_warning_handlers(old_error_handler, old_warning_handler):
-    """Restore previous error and warning handlers."""
-    setWarningHandler(old_warning_handler)
-    setErrorHandler(old_error_handler)
-
-
-def close(fp):
-    """Corresponds to TIFFClose"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p]
-    _LIBTIFF.TIFFClose.argtypes = ARGTYPES
-    _LIBTIFF.TIFFClose.restype = None
-    _LIBTIFF.TIFFClose(fp)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-
-def computeStrip(fp, row, sample):
-    """Corresponds to TIFFComputeStrip"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_uint16]
-    _LIBTIFF.TIFFComputeStrip.argtypes = ARGTYPES
-    _LIBTIFF.TIFFComputeStrip.restype = ctypes.c_uint32
-    stripnum = _LIBTIFF.TIFFComputeStrip(fp, row, sample)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return stripnum
-
-
-def computeTile(fp, x, y, z, sample):
-    """Corresponds to TIFFComputeTile"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_uint32,
-        ctypes.c_uint32,
-        ctypes.c_uint16,
-    ]
-    _LIBTIFF.TIFFComputeTile.argtypes = ARGTYPES
-    _LIBTIFF.TIFFComputeTile.restype = ctypes.c_uint32
-    tilenum = _LIBTIFF.TIFFComputeTile(fp, x, y, z, sample)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return tilenum
-
-
-def isTiled(fp):
-    """Corresponds to TIFFIsTiled"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p]
-
-    _LIBTIFF.TIFFIsTiled.argtypes = ARGTYPES
-    _LIBTIFF.TIFFIsTiled.restype = ctypes.c_int
-
-    status = _LIBTIFF.TIFFIsTiled(fp)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return status
-
-
-def numberOfStrips(fp):
-    """Corresponds to TIFFNumberOfStrips."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p]
-    _LIBTIFF.TIFFNumberOfStrips.argtypes = ARGTYPES
-    _LIBTIFF.TIFFNumberOfStrips.restype = ctypes.c_uint32
-
-    numstrips = _LIBTIFF.TIFFNumberOfStrips(fp)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return numstrips
-
-
-def numberOfTiles(fp):
-    """Corresponds to TIFFNumberOfTiles."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p]
-    _LIBTIFF.TIFFNumberOfTiles.argtypes = ARGTYPES
-    _LIBTIFF.TIFFNumberOfTiles.restype = ctypes.c_uint32
-
-    numtiles = _LIBTIFF.TIFFNumberOfTiles(fp)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return numtiles
-
-
-def readEncodedStrip(fp, stripnum, strip, size=-1):
-    """Corresponds to TIFFReadEncodedStrip"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    if size == -1:
-        size = strip.nbytes
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_void_p,
-        ctypes.c_int32
-    ]
-    _LIBTIFF.TIFFReadEncodedStrip.argtypes = ARGTYPES
-    _LIBTIFF.TIFFReadEncodedStrip.restype = check_error
-    _LIBTIFF.TIFFReadEncodedStrip(
-        fp, stripnum, strip.ctypes.data_as(ctypes.c_void_p), size
-    )
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return strip
-
-
-def readEncodedTile(fp, tilenum, tile, size=-1):
-    """Corresponds to TIFFComputeTile"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    if size == -1:
-        size = tile.nbytes
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_void_p,
-        ctypes.c_int32
-    ]
-    _LIBTIFF.TIFFReadEncodedTile.argtypes = ARGTYPES
-    _LIBTIFF.TIFFReadEncodedTile.restype = check_error
-    _LIBTIFF.TIFFReadEncodedTile(
-        fp,
-        tilenum,
-        tile.ctypes.data_as(ctypes.c_void_p),
-        -1
-    )
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return tile
-
-
-def readRGBAStrip(fp, row, strip):
-    """Corresponds to TIFFReadRGBAStrip"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p]
-    _LIBTIFF.TIFFReadRGBAStrip.argtypes = ARGTYPES
-    _LIBTIFF.TIFFReadRGBAStrip.restype = check_error
-    _LIBTIFF.TIFFReadRGBAStrip(fp, row, strip.ctypes.data_as(ctypes.c_void_p))
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return strip
-
-
-def readRGBATile(fp, x, y, tile):
-    """Corresponds to TIFFReadRGBATile"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_uint32,
-        ctypes.c_void_p
-    ]
-    _LIBTIFF.TIFFReadRGBATile.argtypes = ARGTYPES
-    _LIBTIFF.TIFFReadRGBATile.restype = check_error
-    _LIBTIFF.TIFFReadRGBATile(fp, x, y, tile.ctypes.data_as(ctypes.c_void_p))
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return tile
-
-
-def readRGBAImageOriented(
-    fp,
-    width=None,
-    height=None,
-    orientation=Orientation.TOPLEFT
-):
-    """Read an image as if it were RGBA.
-
-    This function corresponds to the TIFFReadRGBAImageOriented function in the
-    libtiff library.
-
-    Parameters
-    ----------
-    fp : ctypes void pointer
-        File pointer returned by libtiff.
-    width, height : int
-        Width and height of the returned image.
-    orientation : int
-        The raster origin position.
-
-    See Also
-    --------
-    Orientation
-    """
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_uint32,
-        ctypes.POINTER(ctypes.c_uint32),
-        ctypes.c_int32,
-        ctypes.c_int32,
-    ]
-
-    _LIBTIFF.TIFFReadRGBAImageOriented.argtypes = ARGTYPES
-    _LIBTIFF.TIFFReadRGBAImageOriented.restype = check_error
-
-    if width is None:
-        width = getFieldDefaulted(fp, "ImageWidth")
-    if height is None:
-        height = getFieldDefaulted(fp, "ImageLength")
-
-    img = np.zeros((height, width, 4), dtype=np.uint8)
-    raster = img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))
-    _LIBTIFF.TIFFReadRGBAImageOriented(
-        fp,
-        width,
-        height,
-        raster,
-        orientation,
-        0
-    )
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return img
-
-
-def writeEncodedStrip(fp, stripnum, stripdata, size=-1):
-    """Corresponds to TIFFWriteEncodedStrip."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_void_p,
-        ctypes.c_uint32
-    ]
-    _LIBTIFF.TIFFWriteEncodedStrip.argtypes = ARGTYPES
-    _LIBTIFF.TIFFWriteEncodedStrip.restype = check_error
-    raster = stripdata.ctypes.data_as(ctypes.c_void_p)
-
-    if size == -1:
-        size = stripdata.nbytes
-
-    _LIBTIFF.TIFFWriteEncodedStrip(fp, stripnum, raster, size)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-
-def writeEncodedTile(fp, tilenum, tiledata, size=-1):
-    """Corresponds to TIFFWriteEncodedTile."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [
-        ctypes.c_void_p,
-        ctypes.c_uint32,
-        ctypes.c_void_p,
-        ctypes.c_uint32
-    ]
-    _LIBTIFF.TIFFWriteEncodedTile.argtypes = ARGTYPES
-    _LIBTIFF.TIFFWriteEncodedTile.restype = check_error
-    raster = tiledata.ctypes.data_as(ctypes.c_void_p)
-
-    if size == -1:
-        size = tiledata.nbytes
-
-    _LIBTIFF.TIFFWriteEncodedTile(fp, tilenum, raster, size)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-
-def RGBAImageOK(fp):
-    """Corresponds to TIFFRGBAImageOK."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    emsg = ctypes.create_string_buffer(1024)
-    ARGTYPES = [ctypes.c_void_p, ctypes.c_char_p]
-    _LIBTIFF.TIFFRGBAImageOK.argtypes = ARGTYPES
-    _LIBTIFF.TIFFRGBAImageOK.restype = ctypes.c_int
-    ok = _LIBTIFF.TIFFRGBAImageOK(fp, emsg)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    if ok:
-        return True
-    else:
-        return False
-
-
-def getFieldDefaulted(fp, tag):
-    """Corresponds to the TIFFGetFieldDefaulted library routine."""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p, ctypes.c_int32]
-
-    tag_num = TAGS[tag]["number"]
-
-    # Append the proper return type for the tag.
-    tag_type = TAGS[tag]["type"]
-    ARGTYPES.append(ctypes.POINTER(TAGS[tag]["type"]))
-    _LIBTIFF.TIFFGetFieldDefaulted.argtypes = ARGTYPES
-
-    _LIBTIFF.TIFFGetFieldDefaulted.restype = check_error
-
-    # instantiate the tag value
-    item = tag_type()
-    _LIBTIFF.TIFFGetFieldDefaulted(fp, tag_num, ctypes.byref(item))
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return item.value
-
-
-def getVersion():
-    """Corresponds to the TIFFGetVersion library routine."""
-    try:
-        _LIBTIFF.TIFFGetVersion.restype = ctypes.c_char_p
-    except AttributeError:
-        # libtiff not installed
-        return "0.0.0"
-
-    v = _LIBTIFF.TIFFGetVersion().decode("utf-8")
-
-    # v would be something like
-    #
-    # LIBTIFF, Version 4.3.0
-    # Copyright (c) 1988-1996 Sam Leffler
-    # Copyright (c) 1991-1996 Silicon Graphics, Inc.
-    #
-    # All we want is the '4.3.0'
-    m = re.search(r"(?P<version>\d+\.\d+\.\d+)", v)
-    return m.group("version")
-
-
-def open(filename, mode="r"):
-    """Corresponds to TIFFOpen
-
-    Parameters
-    ----------
-    filename : path or str
-        Path to TIFF
-    """
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    filename = str(filename)
-
-    ARGTYPES = [ctypes.c_char_p, ctypes.c_char_p]
-    _LIBTIFF.TIFFOpen.argtypes = ARGTYPES
-    _LIBTIFF.TIFFOpen.restype = ctypes.c_void_p
-    file_argument = ctypes.c_char_p(filename.encode())
-    mode_argument = ctypes.c_char_p(mode.encode())
-    fp = _LIBTIFF.TIFFOpen(file_argument, mode_argument)
-    check_error(fp)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-    return fp
-
-
-def setErrorHandler(func=_ERROR_HANDLER):
-    # The signature of the error handler is
-    #     const char *module, const char *fmt, va_list ap
-    #
-    # The return type is void *
-    _LIBTIFF.TIFFSetErrorHandler.argtypes = [_WFUNCTYPE]
-    _LIBTIFF.TIFFSetErrorHandler.restype = _WFUNCTYPE
-    old_error_handler = _LIBTIFF.TIFFSetErrorHandler(func)
-    return old_error_handler
-
-
-def setField(fp, tag, *value):
-    """Corresponds to TIFFSetField"""
-    err_handler, warn_handler = _set_error_warning_handlers()
-
-    ARGTYPES = [ctypes.c_void_p, ctypes.c_int32]
-
-    # Append the proper return type for the tag.
-    tag_num = TAGS[tag]["number"]
-    tag_type = TAGS[tag]["type"]
-
-    try:
-        for ttype in tag_type:
-            ARGTYPES.append(ttype)
-    except TypeError:
-        ARGTYPES.append(tag_type)
-
-    _LIBTIFF.TIFFSetField.argtypes = ARGTYPES
-    _LIBTIFF.TIFFSetField.restype = check_error
-
-    if len(value) == 1 and tag_type == ctypes.c_char_p:
-        _LIBTIFF.TIFFSetField(fp, tag_num, ctypes.c_char_p(value[0].encode()))
-    elif len(value) == 1:
-        _LIBTIFF.TIFFSetField(fp, tag_num, value[0])
-    else:
-        _LIBTIFF.TIFFSetField(fp, tag_num, *value)
-
-    _reset_error_warning_handlers(err_handler, warn_handler)
-
-
-def setWarningHandler(func=_WARNING_HANDLER):
-    # The signature of the warning handler is
-    #     const char *module, const char *fmt, va_list ap
-    #
-    # The return type is void *
-    _LIBTIFF.TIFFSetWarningHandler.argtypes = [_WFUNCTYPE]
-    _LIBTIFF.TIFFSetWarningHandler.restype = _WFUNCTYPE
-    old_warning_handler = _LIBTIFF.TIFFSetWarningHandler(func)
-    return old_warning_handler
-
-
-def check_error(status):
-    """Set a generic function as the restype attribute of all TIFF
-    functions that return a int value.  This way we do not have to check
-    for error status in each wrapping function and an exception will always be
-    appropriately raised.
-    """
-    msg = ""
-    while not EQ.empty():
-        msg = EQ.get()
-        raise LibTIFFError(msg)
-
-    if status == 0:
-        raise RuntimeError("failed")
-
-
-TAGS = {
-    "GPSVersionID": {
-        "number": 0,
-        "type": ctypes.c_char_p,
-    },
-    "GPSLatitudeRef": {
-        "number": 1,
-        "type": ctypes.c_char_p,
-    },
-    "GPSLatitude": {
-        "number": 2,
-        "type": ctypes.c_char_p,
-    },
-    "GPSLongitudeRef": {
-        "number": 3,
-        "type": ctypes.c_char_p,
-    },
-    "GPSLongitude": {
-        "number": 4,
-        "type": ctypes.c_char_p,
-    },
-    "GPSAltitudeRef": {
-        "number": 5,
-        "type": ctypes.c_char_p,
-    },
-    "GPSAltitude": {
-        "number": 6,
-        "type": ctypes.c_char_p,
-    },
-    "GPSTimestamp": {
-        "number": 7,
-        "type": ctypes.c_char_p,
-    },
-    "GPSSatellites": {
-        "number": 8,
-        "type": ctypes.c_char_p,
-    },
-    "GPSStatus": {
-        "number": 9,
-        "type": ctypes.c_char_p,
-    },
-    "GPSMeasureMode": {
-        "number": 10,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDOP": {
-        "number": 11,
-        "type": ctypes.c_char_p,
-    },
-    "GPSSpeedRef": {
-        "number": 12,
-        "type": ctypes.c_char_p,
-    },
-    "GPSSpeed": {
-        "number": 13,
-        "type": ctypes.c_char_p,
-    },
-    "GPSTrackRef": {
-        "number": 14,
-        "type": ctypes.c_char_p,
-    },
-    "GPSTrack": {
-        "number": 15,
-        "type": ctypes.c_char_p,
-    },
-    "GPSImgDirectionRef": {
-        "number": 16,
-        "type": ctypes.c_char_p,
-    },
-    "GPSImgDirection": {
-        "number": 17,
-        "type": ctypes.c_char_p,
-    },
-    "GPSMapDatum": {
-        "number": 18,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestLatitudeRef": {
-        "number": 19,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestLatitude": {
-        "number": 20,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestLongitudeRef": {
-        "number": 21,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestLongitude": {
-        "number": 22,
-        "type": ctypes.c_char_p,
-    },
-    "GPSBearingRef": {
-        "number": 23,
-        "type": ctypes.c_char_p,
-    },
-    "GPSBearing": {
-        "number": 24,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestDistanceRef": {
-        "number": 25,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDestDistance": {
-        "number": 26,
-        "type": ctypes.c_int16,
-    },
-    "GPSProcessingMethod": {
-        "number": 27,
-        "type": ctypes.c_char_p,
-    },
-    "GPSAreaInformation": {
-        "number": 28,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDateStamp": {
-        "number": 29,
-        "type": ctypes.c_char_p,
-    },
-    "GPSDifferential": {
-        "number": 30,
-        "type": ctypes.c_char_p,
-    },
-    "GPSHPositioningError": {
-        "number": 31,
-        "type": ctypes.c_int16,
-    },
-    "SubFileType": {
-        "number": 254,
-        "type": ctypes.c_int16,
-    },
-    "OSubFileType": {
-        "number": 255,
-        "type": ctypes.c_int16,
-    },
-    "ImageWidth": {
-        "number": 256,
-        "type": ctypes.c_int32,
-    },
-    "ImageLength": {
-        "number": 257,
-        "type": ctypes.c_int32,
-    },
-    "BitsPerSample": {
-        "number": 258,
-        "type": ctypes.c_int16,
-    },
-    "Compression": {
-        "number": 259,
-        "type": ctypes.c_int16,
-    },
-    "Photometric": {
-        "number": 262,
-        "type": ctypes.c_int16,
-    },
-    "Threshholding": {
-        "number": 263,
-        "type": ctypes.c_int16,
-    },
-    "CellWidth": {
-        "number": 264,
-        "type": ctypes.c_int16,
-    },
-    "CellLength": {
-        "number": 265,
-        "type": ctypes.c_int16,
-    },
-    "FillOrder": {
-        "number": 266,
-        "type": ctypes.c_int16,
-    },
-    "DocumentName": {
-        "number": 269,
-        "type": ctypes.c_char_p,
-    },
-    "ImageDescription": {
-        "number": 270,
-        "type": ctypes.c_char_p,
-    },
-    "Make": {
-        "number": 271,
-        "type": ctypes.c_char_p,
-    },
-    "Model": {
-        "number": 272,
-        "type": ctypes.c_char_p,
-    },
-    "StripOffsets": {
-        "number": 273,
-        "type": (ctypes.c_int32, ctypes.c_int64),
-    },
-    "Orientation": {
-        "number": 274,
-        "type": ctypes.c_int16,
-    },
-    "SamplesPerPixel": {
-        "number": 277,
-        "type": ctypes.c_int16,
-    },
-    "RowsPerStrip": {
-        "number": 278,
-        "type": ctypes.c_int16,
-    },
-    "StripByteCounts": {
-        "number": 279,
-        "type": None,
-    },
-    "MinSampleValue": {
-        "number": 280,
-        "type": ctypes.c_int16,
-    },
-    "MaxSampleValue": {
-        "number": 281,
-        "type": ctypes.c_int16,
-    },
-    "XResolution": {
-        "number": 282,
-        "type": ctypes.c_double,
-    },
-    "YResolution": {
-        "number": 283,
-        "type": ctypes.c_double,
-    },
-    "PlanarConfig": {
-        "number": 284,
-        "type": ctypes.c_int16,
-    },
-    "PageName": {
-        "number": 285,
-        "type": ctypes.c_char_p,
-    },
-    "XPosition": {
-        "number": 286,
-        "type": ctypes.c_double,
-    },
-    "YPosition": {
-        "number": 287,
-        "type": ctypes.c_double,
-    },
-    "FreeOffsets": {
-        "number": 288,
-        "type": ctypes.c_int32,
-    },
-    "FreeByteCounts": {
-        "number": 289,
-        "type": ctypes.c_int32,
-    },
-    "GrayResponseUnit": {
-        "number": 290,
-        "type": ctypes.c_int16,
-    },
-    "GrayResponseCurve": {
-        "number": 291,
-        "type": None,
-    },
-    "T4Options": {
-        "number": 292,
-        "type": None,
-    },
-    "T6Options": {
-        "number": 293,
-        "type": None,
-    },
-    "ResolutionUnit": {
-        "number": 296,
-        "type": ctypes.c_int16,
-    },
-    "PageNumber": {
-        "number": 297,
-        "type": (ctypes.c_int16, ctypes.c_uint16),
-    },
-    "TransferFunction": {
-        "number": 301,
-        "type": None,
-    },
-    "Software": {
-        "number": 305,
-        "type": ctypes.c_char_p,
-    },
-    "Datetime": {
-        "number": 306,
-        "type": ctypes.c_char_p,
-    },
-    "Artist": {
-        "number": 315,
-        "type": ctypes.c_char_p,
-    },
-    "HostComputer": {
-        "number": 316,
-        "type": ctypes.c_char_p,
-    },
-    "Predictor": {
-        "number": 317,
-        "type": ctypes.c_int16,
-    },
-    "WhitePoint": {
-        "number": 318,
-        "type": ctypes.c_double,
-    },
-    "PrimaryChromaticities": {
-        "number": 319,
-        "type": None,
-    },
-    "ColorMap": {
-        "number": 320,
-        "type": (ctypes.c_int16, ctypes.c_uint16),
-    },
-    "HalfToneHints": {
-        "number": 321,
-        "type": ctypes.c_int16,
-    },
-    "TileWidth": {
-        "number": 322,
-        "type": ctypes.c_int32,
-    },
-    "TileLength": {
-        "number": 323,
-        "type": ctypes.c_int32,
-    },
-    "TileOffsets": {
-        "number": 324,
-        "type": None,
-    },
-    "TileByteCounts": {
-        "number": 325,
-        "type": None,
-    },
-    "BadFaxLines": {
-        "number": 326,
-        "type": None,
-    },
-    "CleanFaxData": {
-        "number": 327,
-        "type": None,
-    },
-    "ConsecutiveBadFaxLines": {
-        "number": 328,
-        "type": None,
-    },
-    "SubIFDs": {
-        "number": 330,
-        "type": None,
-    },
-    "InkSet": {
-        "number": 332,
-        "type": ctypes.c_uint16,
-    },
-    "InkNames": {
-        "number": 333,
-        "type": ctypes.c_char_p,
-    },
-    "NumberOfInks": {
-        "number": 334,
-        "type": ctypes.c_uint16,
-    },
-    "DotRange": {
-        "number": 336,
-        "type": None,
-    },
-    "TargetPrinter": {
-        "number": 337,
-        "type": ctypes.c_uint16,
-    },
-    "ExtraSamples": {
-        "number": 338,
-        "type": ctypes.c_uint16,
-    },
-    "SampleFormat": {
-        "number": 339,
-        "type": ctypes.c_uint16,
-    },
-    "SMinSampleValue": {
-        "number": 340,
-        "type": ctypes.c_double,
-    },
-    "SMaxSampleValue": {
-        "number": 341,
-        "type": ctypes.c_double,
-    },
-    "TransferRange": {
-        "number": 342,
-        "type": None,
-    },
-    "ClipPath": {
-        "number": 343,
-        "type": None,
-    },
-    "XClipPathUnits": {
-        "number": 344,
-        "type": None,
-    },
-    "YClipPathUnits": {
-        "number": 345,
-        "type": None,
-    },
-    "Indexed": {
-        "number": 346,
-        "type": None,
-    },
-    "JPEGTables": {
-        "number": 347,
-        "type": None,
-    },
-    "OPIProxy": {
-        "number": 351,
-        "type": None,
-    },
-    "GlobalParametersIFD": {
-        "number": 400,
-        "type": None,
-    },
-    "ProfileType": {
-        "number": 401,
-        "type": None,
-    },
-    "FaxProfile": {
-        "number": 402,
-        "type": ctypes.c_uint8,
-    },
-    "CodingMethods": {
-        "number": 403,
-        "type": None,
-    },
-    "VersionYear": {
-        "number": 404,
-        "type": None,
-    },
-    "ModeNumber": {
-        "number": 405,
-        "type": None,
-    },
-    "Decode": {
-        "number": 433,
-        "type": None,
-    },
-    "DefaultImageColor": {
-        "number": 434,
-        "type": None,
-    },
-    "JPEGProc": {
-        "number": 512,
-        "type": None,
-    },
-    "JPEGInterchangeFormat": {
-        "number": 513,
-        "type": None,
-    },
-    "JPEGInterchangeFormatLength": {
-        "number": 514,
-        "type": None,
-    },
-    "JPEGRestartInterval": {
-        "number": 515,
-        "type": None,
-    },
-    "JPEGLosslessPredictors": {
-        "number": 517,
-        "type": None,
-    },
-    "JPEGPointTransforms": {
-        "number": 518,
-        "type": None,
-    },
-    "JPEGQTables": {
-        "number": 519,
-        "type": None,
-    },
-    "JPEGDCTables": {
-        "number": 520,
-        "type": None,
-    },
-    "JPEGACTables": {
-        "number": 521,
-        "type": None,
-    },
-    "YCbCrCoefficients": {
-        "number": 529,
-        "type": (ctypes.c_float, ctypes.c_float, ctypes.c_float),
-    },
-    "YCbCrSubsampling": {
-        "number": 530,
-        "type": (ctypes.c_uint16, ctypes.c_uint16),
-    },
-    "YCbCrPositioning": {
-        "number": 531,
-        "type": ctypes.c_uint16,
-    },
-    "ReferenceBlackWhite": {
-        "number": 532,
-        "type": (
-            ctypes.c_float,
-            ctypes.c_float,
-            ctypes.c_float,
-            ctypes.c_float,
-            ctypes.c_float,
-            ctypes.c_float,
-        ),
-    },
-    "StripRowCounts": {
-        "number": 559,
-        "type": None,
-    },
-    "XMLPacket": {
-        "number": 700,
-        "type": ctypes.c_uint8,
-    },
-    "ImageID": {
-        "number": 32781,
-        "type": None,
-    },
-    "Rating": {
-        "number": 18246,
-        "type": ctypes.c_uint16,
-    },
-    "RatingPercent": {
-        "number": 18249,
-        "type": ctypes.c_uint16,
-    },
-    "Datatype": {
-        "number": 32996,
-        "type": None,
-    },
-    "WANGAnnotation": {
-        "number": 32932,
-        "type": None,
-    },
-    "ImageDepth": {
-        "number": 32997,
-        "type": None,
-    },
-    "TileDepth": {
-        "number": 32998,
-        "type": None,
-    },
-    "CFARepeatPatternDim": {
-        "number": 33421,
-        "type": None,
-    },
-    "CFAPattern": {
-        "number": 33422,
-        "type": None,
-    },
-    "BatteryLevel": {
-        "number": 33423,
-        "type": None,
-    },
-    "Copyright": {
-        "number": 33432,
-        "type": ctypes.c_char_p,
-    },
-    "ExposureTime": {
-        "number": 33434,
-        "type": ctypes.c_double,
-    },
-    "FNumber": {
-        "number": 33437,
-        "type": ctypes.c_double,
-    },
-    "MDFile": {
-        "number": 33445,
-        "type": None,
-    },
-    "MDScalePixel": {
-        "number": 33446,
-        "type": None,
-    },
-    "MDColorTable": {
-        "number": 33447,
-        "type": None,
-    },
-    "MDLabName": {
-        "number": 33448,
-        "type": None,
-    },
-    "MDSampleInfo": {
-        "number": 33449,
-        "type": None,
-    },
-    "MdPrepDate": {
-        "number": 33450,
-        "type": None,
-    },
-    "MDPrepTime": {
-        "number": 33451,
-        "type": None,
-    },
-    "MDFileUnits": {
-        "number": 33452,
-        "type": None,
-    },
-    "ModelPixelScale": {
-        "number": 33550,
-        "type": None,
-    },
-    "IPTC": {
-        "number": 33723,
-        "type": None,
-    },
-    "INGRPacketData": {
-        "number": 33918,
-        "type": None,
-    },
-    "INGRFlagRegisters": {
-        "number": 33919,
-        "type": None,
-    },
-    "IRASbTransformationMatrix": {
-        "number": 33920,
-        "type": None,
-    },
-    "ModelTiePoint": {
-        "number": 33922,
-        "type": None,
-    },
-    "ModelTransformation": {
-        "number": 34264,
-        "type": None,
-    },
-    "Photoshop": {
-        "number": 34377,
-        "type": None,
-    },
-    "ExifTag": {
-        "number": 34665,
-        "type": ctypes.c_int32,
-    },
-    "ICCProfile": {
-        "number": 34675,
-        "type": None,
-    },
-    "ImageLayer": {
-        "number": 34732,
-        "type": None,
-    },
-    "GeoKeyDirectory": {
-        "number": 34735,
-        "type": None,
-    },
-    "GeoDoubleParams": {
-        "number": 34736,
-        "type": None,
-    },
-    "GeoAsciiParams": {
-        "number": 34737,
-        "type": None,
-    },
-    "ExposureProgram": {
-        "number": 34850,
-        "type": ctypes.c_uint16,
-    },
-    "SpectralSensitivity": {
-        "number": 34852,
-        "type": ctypes.c_char_p,
-    },
-    "GPSIFD": {
-        "number": 34853,
-        "type": None,
-    },
-    "ISOSpeedRatings": {
-        "number": 34855,
-        "type": ctypes.c_uint16,
-    },
-    "OECF": {
-        "number": 34856,
-        "type": None,
-    },
-    "Interlace": {
-        "number": 34857,
-        "type": None,
-    },
-    "TimeZoneOffset": {
-        "number": 34858,
-        "type": None,
-    },
-    "SelfTimerMode": {
-        "number": 34859,
-        "type": None,
-    },
-    "SensitivityType": {
-        "number": 34864,
-        "type": None,
-    },
-    "StandardOutputSensitivity": {
-        "number": 34865,
-        "type": None,
-    },
-    "RecommendedExposureIndex": {
-        "number": 34866,
-        "type": None,
-    },
-    "ISOSpeed": {
-        "number": 34867,
-        "type": None,
-    },
-    "ISOSpeedLatitudeYYY": {
-        "number": 34868,
-        "type": None,
-    },
-    "ISOSpeedLatitudeZZZ": {
-        "number": 34869,
-        "type": None,
-    },
-    "HYLAFAXRecvParams": {
-        "number": 34908,
-        "type": None,
-    },
-    "HYLAFAXSubAddress": {
-        "number": 34909,
-        "type": None,
-    },
-    "HYLAFAXRecvTime": {
-        "number": 34910,
-        "type": None,
-    },
-    "ExifVersion": {
-        "number": 36864,
-        "type": ctypes.c_uint8,
-    },
-    "DateTimeOriginal": {
-        "number": 36867,
-        "type": None,
-    },
-    "DateTimeDigitized": {
-        "number": 36868,
-        "type": None,
-    },
-    "OffsetTime": {
-        "number": 36880,
-        "type": None,
-    },
-    "OffsetTimeOriginal": {
-        "number": 36881,
-        "type": None,
-    },
-    "OffsetTimeDigitized": {
-        "number": 36882,
-        "type": None,
-    },
-    "ComponentsConfiguration": {"number": 37121, "type": None},
-    "CompressedBitsPerPixel": {
-        "number": 37122,
-        "type": ctypes.c_uint8,
-    },
-    "ShutterSpeedValue": {
-        "number": 37377,
-        "type": ctypes.c_double,
-    },
-    "ApertureValue": {
-        "number": 37378,
-        "type": ctypes.c_double,
-    },
-    "BrightnessValue": {
-        "number": 37379,
-        "type": ctypes.c_double,
-    },
-    "ExposureBiasValue": {
-        "number": 37380,
-        "type": ctypes.c_double,
-    },
-    "MaxApertureValue": {
-        "number": 37381,
-        "type": ctypes.c_double,
-    },
-    "SubjectDistance": {
-        "number": 37382,
-        "type": ctypes.c_double,
-    },
-    "MeteringMode": {
-        "number": 37383,
-        "type": ctypes.c_uint16,
-    },
-    "LightSource": {
-        "number": 37384,
-        "type": ctypes.c_uint16,
-    },
-    "Flash": {
-        "number": 37385,
-        "type": ctypes.c_uint16,
-    },
-    "FocalLength": {
-        "number": 37386,
-        "type": ctypes.c_double,
-    },
-    "Noise": {
-        "number": 37389,
-        "type": None,
-    },
-    "ImageNumber": {
-        "number": 37393,
-        "type": None,
-    },
-    "SecurityClassification": {
-        "number": 37394,
-        "type": None,
-    },
-    "ImageHistory": {
-        "number": 37395,
-        "type": None,
-    },
-    "TIFFEPStandardID": {
-        "number": 37398,
-        "type": None,
-    },
-    "MakerNote": {
-        "number": 37500,
-        "type": ctypes.c_char_p,
-    },
-    "UserComment": {
-        "number": 37510,
-        "type": ctypes.c_char_p,
-    },
-    "SubSecTime": {
-        "number": 37520,
-        "type": ctypes.c_char_p,
-    },
-    "SubSecTimeOriginal": {
-        "number": 37521,
-        "type": ctypes.c_char_p,
-    },
-    "SubSecTimeDigitized": {
-        "number": 37522,
-        "type": ctypes.c_char_p,
-    },
-    "ImageSourceData": {
-        "number": 37724,
-        "type": None,
-    },
-    "Temperature": {
-        "number": 37888,
-        "type": None,
-    },
-    "Humidity": {
-        "number": 37889,
-        "type": None,
-    },
-    "Pressure": {
-        "number": 37890,
-        "type": None,
-    },
-    "WaterDepth": {
-        "number": 37891,
-        "type": None,
-    },
-    "Acceleration": {
-        "number": 37892,
-        "type": None,
-    },
-    "CameraElevationAngle": {
-        "number": 37893,
-        "type": None,
-    },
-    "XPTitle": {
-        "number": 40091,
-        "type": None,
-    },
-    "XPComment": {
-        "number": 40092,
-        "type": None,
-    },
-    "XPAuthor": {
-        "number": 40093,
-        "type": None,
-    },
-    "XPKeywords": {
-        "number": 40094,
-        "type": None,
-    },
-    "XPSubject": {
-        "number": 40095,
-        "type": None,
-    },
-    "FlashPixVersion": {
-        "number": 40960,
-        "type": None,
-    },
-    "ColorSpace": {
-        "number": 40961,
-        "type": ctypes.c_uint16,
-    },
-    "PixelXDimension": {
-        "number": 40962,
-        "type": ctypes.c_uint64,
-    },
-    "PixelYDimension": {
-        "number": 40963,
-        "type": ctypes.c_uint64,
-    },
-    "InteroperabilityIFD": {
-        "number": 40965,
-        "type": None,
-    },
-    "FocalPlaneXResolution": {
-        "number": 41486,
-        "type": ctypes.c_double,
-    },
-    "FocalPlaneYResolution": {
-        "number": 41487,
-        "type": ctypes.c_double,
-    },
-    "FocalPlaneResolutionUnit": {
-        "number": 41488,
-        "type": ctypes.c_uint16,
-    },
-    "ExposureIndex": {
-        "number": 41493,
-        "type": ctypes.c_double,
-    },
-    "SensingMethod": {
-        "number": 41495,
-        "type": ctypes.c_uint16,
-    },
-    "SceneType": {
-        "number": 41729,
-        "type": ctypes.c_uint8,
-    },
-    "FlashEnergy": {"number": 41483, "type": None},
-    "SpatialFrequencyResponse": {"number": 41484, "type": None},
-    "SubjectLocation": {"number": 41492, "type": None},
-    "FileSource": {"number": 41728, "type": None},
-    "ExifCFAPattern": {"number": 41730, "type": None},
-    "CustomRendered": {"number": 41985, "type": None},
-    "ExposureMode": {
-        "number": 41986,
-        "type": ctypes.c_uint16,
-    },
-    "WhiteBalance": {
-        "number": 41987,
-        "type": ctypes.c_uint16,
-    },
-    "DigitalZoomRatio": {
-        "number": 41988,
-        "type": ctypes.c_double,
-    },
-    "FocalLengthIn35mmFilm": {
-        "number": 41989,
-        "type": ctypes.c_uint16,
-    },
-    "SceneCaptureType": {
-        "number": 41990,
-        "type": ctypes.c_uint16,
-    },
-    "GainControl": {
-        "number": 41991,
-        "type": ctypes.c_uint16,
-    },
-    "Contrast": {
-        "number": 41992,
-        "type": ctypes.c_uint16,
-    },
-    "Saturation": {
-        "number": 41993,
-        "type": ctypes.c_uint16,
-    },
-    "Sharpness": {
-        "number": 41994,
-        "type": ctypes.c_uint16,
-    },
-    "DeviceSettingDescription": {
-        "number": 41995,
-        "type": ctypes.c_char_p,
-    },
-    "SubjectDistanceRange": {
-        "number": 41996,
-        "type": ctypes.c_uint16,
-    },
-    "ImageUniqueID": {"number": 42016, "type": None},
-    "CameraOwnerName": {"number": 42032, "type": None},
-    "BodySerialNumber": {"number": 42033, "type": None},
-    "LensSpecification": {"number": 42034, "type": None},
-    "LensMake": {"number": 42035, "type": None},
-    "LensModel": {"number": 42036, "type": None},
-    "LensSerialNumber": {"number": 42037, "type": None},
-    "CompositeImage": {"number": 42080, "type": None},
-    "SourceImageNumberOfCompositeImage": {"number": 42081, "type": None},
-    "SourceExposureTimeOfCompositeImage": {"number": 42082, "type": None},
-    "GDAL_Metadata": {
-        "number": 42112,
-        "type": None,
-    },
-    "GDAL_NoData": {
-        "number": 42113,
-        "type": None,
-    },
-    "Gamma": {
-        "number": 42240,
-        "type": None,
-    },
-    "OCEScanJobDescription": {
-        "number": 50215,
-        "type": None,
-    },
-    "OCEApplicationSelector": {
-        "number": 50216,
-        "type": None,
-    },
-    "OCEIdentificationNumber": {
-        "number": 50217,
-        "type": None,
-    },
-    "OCEImageLogicCharacteristics": {
-        "number": 50218,
-        "type": None,
-    },
-    "PrintImageMatching": {
-        "number": 50341,
-        "type": None,
-    },
-    "DNGVersion": {
-        "number": 50706,
-        "type": None,
-    },
-    "DNGBackwardVersion": {
-        "number": 50707,
-        "type": None,
-    },
-    "UniqueCameraModel": {
-        "number": 50708,
-        "type": None,
-    },
-    "LocalizedCameraModel": {
-        "number": 50709,
-        "type": None,
-    },
-    "CFAPlaneColor": {
-        "number": 50710,
-        "type": None,
-    },
-    "CFALayout": {
-        "number": 50711,
-        "type": None,
-    },
-    "LinearizationTable": {
-        "number": 50712,
-        "type": None,
-    },
-    "BlackLevelRepeatDim": {
-        "number": 50713,
-        "type": None,
-    },
-    "BlackLevel": {
-        "number": 50714,
-        "type": None,
-    },
-    "BlackLevelDeltaH": {
-        "number": 50715,
-        "type": None,
-    },
-    "BlackLevelDeltaV": {
-        "number": 50716,
-        "type": None,
-    },
-    "WhiteLevel": {
-        "number": 50717,
-        "type": None,
-    },
-    "DefaultScale": {
-        "number": 50718,
-        "type": None,
-    },
-    "DefaultCropOrigin": {
-        "number": 50719,
-        "type": None,
-    },
-    "DefaultCropSize": {
-        "number": 50720,
-        "type": None,
-    },
-    "ColorMatrix1": {
-        "number": 50721,
-        "type": None,
-    },
-    "ColorMatrix2": {
-        "number": 50722,
-        "type": None,
-    },
-    "CameraCalibration1": {
-        "number": 50723,
-        "type": None,
-    },
-    "CameraCalibration2": {
-        "number": 50724,
-        "type": None,
-    },
-    "ReductionMatrix1": {
-        "number": 50725,
-        "type": None,
-    },
-    "ReductionMatrix2": {
-        "number": 50726,
-        "type": None,
-    },
-    "AnalogBalance": {
-        "number": 50727,
-        "type": None,
-    },
-    "AsShotNeutral": {
-        "number": 50728,
-        "type": None,
-    },
-    "AsShotWhiteXY": {
-        "number": 50729,
-        "type": None,
-    },
-    "BaselineExposure": {
-        "number": 50730,
-        "type": None,
-    },
-    "BaselineNoise": {
-        "number": 50731,
-        "type": None,
-    },
-    "BaselineSharpness": {
-        "number": 50732,
-        "type": None,
-    },
-    "BayerGreenSplit": {
-        "number": 50733,
-        "type": None,
-    },
-    "LinearResponseLimit": {
-        "number": 50734,
-        "type": None,
-    },
-    "CameraSerialNumber": {
-        "number": 50735,
-        "type": None,
-    },
-    "LensInfo": {
-        "number": 50736,
-        "type": None,
-    },
-    "ChromaBlurRadius": {
-        "number": 50737,
-        "type": None,
-    },
-    "AntiAliasStrength": {
-        "number": 50738,
-        "type": None,
-    },
-    "ShadowScale": {
-        "number": 50739,
-        "type": None,
-    },
-    "DNGPrivateData": {
-        "number": 50740,
-        "type": None,
-    },
-    "MakerNoteSafety": {
-        "number": 50741,
-        "type": None,
-    },
-    "CalibrationIllumintant1": {
-        "number": 50778,
-        "type": None,
-    },
-    "CalibrationIllumintant2": {
-        "number": 50779,
-        "type": None,
-    },
-    "BestQualityScale": {
-        "number": 50780,
-        "type": None,
-    },
-    "RawDataUniqueID": {
-        "number": 50781,
-        "type": None,
-    },
-    "AliasLayerMetadata": {
-        "number": 50784,
-        "type": None,
-    },
-    "OriginalRawFileName": {
-        "number": 50827,
-        "type": None,
-    },
-    "OriginalRawFileData": {
-        "number": 50828,
-        "type": None,
-    },
-    "ActiveArea": {
-        "number": 50829,
-        "type": None,
-    },
-    "MaskedAreas": {
-        "number": 50830,
-        "type": None,
-    },
-    "AsShotICCProfile": {
-        "number": 50831,
-        "type": None,
-    },
-    "AsShotPreProfileMatrix": {
-        "number": 50832,
-        "type": None,
-    },
-    "CurrentICCProfile": {
-        "number": 50833,
-        "type": None,
-    },
-    "CurrentPreProfileMatrix": {
-        "number": 50834,
-        "type": None,
-    },
-    "ColorimetricReference": {
-        "number": 50839,
-        "type": None,
-    },
-    "TIFF_RSID": {
-        "number": 50908,
-        "type": None,
-    },
-    "GEO_Metadata": {
-        "number": 50909,
-        "type": None,
-    },
-    "CameraCalibrationSignature": {
-        "number": 50931,
-        "type": None,
-    },
-    "ProfileCalibrationSignature": {
-        "number": 50932,
-        "type": None,
-    },
-    "AsShotProfileName": {
-        "number": 50934,
-        "type": None,
-    },
-    "NoiseReductionApplied": {
-        "number": 50935,
-        "type": None,
-    },
-    "ProfileName": {
-        "number": 50936,
-        "type": None,
-    },
-    "ProfileHueSatMapDims": {
-        "number": 50937,
-        "type": None,
-    },
-    "ProfileHueSatMapData1": {
-        "number": 50938,
-        "type": None,
-    },
-    "ProfileHueSatMapData2": {
-        "number": 50939,
-        "type": None,
-    },
-    "ProfileToneCurve": {
-        "number": 50940,
-        "type": None,
-    },
-    "ProfileEmbedPolicy": {
-        "number": 50941,
-        "type": None,
-    },
-    "ProfileCopyright": {
-        "number": 50942,
-        "type": None,
-    },
-    "ForwardMatrix1": {
-        "number": 50964,
-        "type": None,
-    },
-    "ForwardMatrix2": {
-        "number": 50965,
-        "type": None,
-    },
-    "PreviewApplicationName": {
-        "number": 50966,
-        "type": None,
-    },
-    "PreviewApplicationVersion": {
-        "number": 50967,
-        "type": None,
-    },
-    "PreviewSettingsName": {
-        "number": 50968,
-        "type": None,
-    },
-    "PreviewSettingsDigest": {
-        "number": 50969,
-        "type": None,
-    },
-    "PreviewColorSpace": {
-        "number": 50970,
-        "type": None,
-    },
-    "PreviewDateTime": {
-        "number": 50971,
-        "type": None,
-    },
-    "RawImageDigest": {
-        "number": 50972,
-        "type": None,
-    },
-    "OriginalRawFileDigest": {
-        "number": 50973,
-        "type": None,
-    },
-    "SubTileBlockSize": {
-        "number": 50974,
-        "type": None,
-    },
-    "RowInterleaveFactor": {
-        "number": 50975,
-        "type": None,
-    },
-    "ProfileLookTableDims": {
-        "number": 50981,
-        "type": None,
-    },
-    "ProfileLookTableData": {
-        "number": 50982,
-        "type": None,
-    },
-    "OpcodeList1": {
-        "number": 51008,
-        "type": None,
-    },
-    "OpcodeList2": {
-        "number": 51009,
-        "type": None,
-    },
-    "OpcodeList3": {
-        "number": 51022,
-        "type": None,
-    },
-    "NoiseProfile": {
-        "number": 51041,
-        "type": None,
-    },
-    "JPEGQuality": {
-        "number": 65537,
-        "type": ctypes.c_int32,
-    },
-    "JPEGColorMode": {
-        "number": 65538,
-        "type": ctypes.c_int32,
-    },
-}
-
-# We need the reverse mapping as well.
-TAGNUM2NAME = {value["number"]: key for key, value in TAGS.items()}
-
-
-def tiff_header(read_buffer):
-    """Interpret the uuid raw data as a tiff header."""
-    # First 8 should be (73, 73, 42, 8) or (77, 77, 42, 8)
-    data = struct.unpack("BB", read_buffer[0:2])
-    if data[0] == 73 and data[1] == 73:
-        # little endian
-        endian = "<"
-    elif data[0] == 77 and data[1] == 77:
-        # big endian
-        endian = ">"
-    else:
-        msg = (
-            f"The byte order indication in the TIFF header "
-            f"({read_buffer[0:2]}) is invalid.  It should be either "
-            f"{bytes([73, 73])} or {bytes([77, 77])}."
-        )
-        raise RuntimeError(msg)
-
-    _, offset = struct.unpack(endian + "HI", read_buffer[2:8])
-
-    # This is the 'Exif Image' portion.
-    return _Ifd(endian, read_buffer, offset).processed_ifd
-
-
-class BadTiffTagDatatype(RuntimeError):
-    """This exception exists soley to better communicate up the stack that the
-    problem exists.
-    """
-
-    pass
-
-
-class _Ifd(object):
-    """Corresponds to TIFF IFD data structure on file.
-
-    Attributes
-    ----------
-    read_buffer : bytes
-        Raw byte stream consisting of the UUID data.
-    endian : str
-        Either '<' for big-endian, or '>' for little-endian.
-    num_tags : int
-        Number of tags in the IFD.
-    raw_ifd : dictionary
-        Maps tag number to "mildly-interpreted" tag value.
-    processed_ifd : dictionary
-        Maps tag name to "mildly-interpreted" tag value.
-    """
-
-    def __init__(self, endian, read_buffer, offset):
-        self.endian = endian
-        self.read_buffer = read_buffer
-        self.processed_ifd = OrderedDict()
-
-        (self.num_tags,) = struct.unpack(
-            endian + "H",
-            read_buffer[offset:offset + 2]
-        )
-
-        fmt = self.endian + "HHII" * self.num_tags
-        ifd_buffer = read_buffer[offset + 2:offset + 2 + self.num_tags * 12]
-        data = struct.unpack(fmt, ifd_buffer)
-        self.raw_ifd = OrderedDict()
-        for j, tag in enumerate(data[0::4]):
-            # The offset to the tag offset/payload is the offset to the IFD
-            # plus 2 bytes for the number of tags plus 12 bytes for each
-            # tag entry plus 8 bytes to the offset/payload itself.
-            toffp = read_buffer[offset + 10 + j * 12:offset + 10 + j * 12 + 4]
-            self.raw_ifd[tag] = self.parse_tag(
-                tag, data[j * 4 + 1], data[j * 4 + 2], toffp
-            )
-
-        self.post_process()
-
-    def parse_tag(self, tag, dtype, count, offset_buf):
-        """Interpret an Exif image tag data payload."""
-
-        try:
-            fmt = DATATYPE2FMT[dtype]["format"] * count
-            payload_size = DATATYPE2FMT[dtype]["nbytes"] * count
-        except KeyError:
-            msg = f"Invalid TIFF tag datatype ({dtype})."
-            raise BadTiffTagDatatype(msg)
-
-        if payload_size <= 4:
-            # Interpret the payload from the 4 bytes in the tag entry.
-            target_buffer = offset_buf[:payload_size]
-        else:
-            # Interpret the payload at the offset specified by the 4 bytes in
-            # the tag entry.
-            (offset,) = struct.unpack(self.endian + "I", offset_buf)
-            target_buffer = self.read_buffer[offset:offset + payload_size]
-
-        if dtype == 2:
-            # ASCII
-            payload = target_buffer.decode("utf-8").rstrip("\x00")
-
-        else:
-            payload = struct.unpack(self.endian + fmt, target_buffer)
-            if dtype == 5 or dtype == 10:
-                # Rational or Signed Rational.  Construct the list of values.
-                rational_payload = []
-                for j in range(count):
-                    try:
-                        value = float(payload[j * 2]) / float(payload[j * 2 + 1])  # noqa : E501
-                    except ZeroDivisionError:
-                        value = np.nan
-                    rational_payload.append(value)
-                payload = np.array(rational_payload)
-            if count == 1:
-                # If just a single value, then return a scalar instead of a
-                # tuple.
-                payload = payload[0]
-            else:
-                payload = np.array(
-                    payload, dtype=DATATYPE2FMT[dtype]["nptype"]
-                )
-
-        return payload
-
-    def post_process(self):
-        """Map the tag name instead of tag number to the tag value."""
-        for tag, value in self.raw_ifd.items():
-            try:
-                tag_name = TAGNUM2NAME[tag]
-            except KeyError:
-                # Ok, we don't recognize this tag.  Just use the numeric id.
-                msg = f"Unrecognized UUID box TIFF tag ({tag})."
-                warnings.warn(msg, UserWarning)
-                tag_name = tag
-
-            if tag_name in ("ExifTag", 'GPSIFD'):
-                # There's an IFD at the offset specified here.
-                ifd = _Ifd(self.endian, self.read_buffer, value)
-                self.processed_ifd[tag_name] = ifd.processed_ifd
-            else:
-                # just a regular tag, treat it as a simple value
-                self.processed_ifd[tag_name] = value
-
-
-# maps the TIFF enumerated datatype to the corresponding structs datatype code,
-# the data width, and the corresponding numpy datatype
-DATATYPE2FMT = {
-    1: {"format": "B", "nbytes": 1, "nptype": np.ubyte},
-    2: {"format": "B", "nbytes": 1, "nptype": str},
-    3: {"format": "H", "nbytes": 2, "nptype": np.uint16},
-    4: {"format": "I", "nbytes": 4, "nptype": np.uint32},
-    5: {"format": "II", "nbytes": 8, "nptype": np.double},
-    6: {"format": "b", "nbytes": 1, "nptype": np.int8},
-    7: {"format": "B", "nbytes": 1, "nptype": np.uint8},
-    8: {"format": "h", "nbytes": 2, "nptype": np.int16},
-    9: {"format": "i", "nbytes": 4, "nptype": np.int32},
-    10: {"format": "ii", "nbytes": 8, "nptype": np.double},
-    11: {"format": "f", "nbytes": 4, "nptype": np.double},
-    12: {"format": "d", "nbytes": 8, "nptype": np.double},
-    13: {"format": "I", "nbytes": 4, "nptype": np.uint32},
-    16: {"format": "Q", "nbytes": 8, "nptype": np.uint64},
-    17: {"format": "q", "nbytes": 8, "nptype": np.int64},
-    18: {"format": "Q", "nbytes": 8, "nptype": np.uint64},
-}
+msg = "glymur.lib.tiff is for internal use only.  Please do not use it."
+warnings.warn(msg, DeprecationWarning)


=====================================
glymur/tiff.py
=====================================
@@ -14,7 +14,7 @@ import numpy as np
 from glymur import Jp2k, set_option
 from glymur.core import SRGB
 from ._core_converter import _2JP2Converter
-from .lib import tiff as libtiff
+from .lib import _tiff as libtiff
 from . import jp2box
 
 # we need a lower case mapping from the tag name to the tag number
@@ -243,7 +243,7 @@ class Tiff2Jp2k(_2JP2Converter):
         temp_filename = str(self.jp2_path) + ".tmp"
         self.jp2.wrap(temp_filename, boxes=self.jp2.box)
         shutil.move(temp_filename, self.jp2_path)
-        self.jp2.parse()
+        self.jp2._parse()
 
     def append_extra_jp2_boxes(self):
         """Copy over the TIFF IFD.  Place it in a UUID box.  Append to the JPEG


=====================================
glymur/version.py
=====================================
@@ -16,11 +16,11 @@ import numpy as np
 
 # Local imports ...
 from .lib import openjp2 as opj2
-from .lib import tiff
+from .lib import _tiff as tiff
 
 # Do not change the format of this next line!  Doing so risks breaking
 # setup.py
-version = "0.14.1"
+version = "0.14.3"
 
 version_tuple = parse(version).release
 


=====================================
pyproject.toml
=====================================
@@ -14,14 +14,14 @@ description = 'Read and write JPEG 2000 files'
 dependencies = [
     'numpy',
     'lxml',
-    'PIL',
+    'pillow',
 ]
 keywords = ['JPEG2000', 'JPEG', '2000', 'imagery']
 license = 'MIT'
 name = 'Glymur'
 readme = 'README.md'
 requires-python = '>=3.11'
-version = '0.14.1'
+version = '0.14.3'
 
 [project.scripts]
 jp2dump = 'glymur.command_line:main'


=====================================
tests/test_callbacks.py
=====================================
@@ -33,7 +33,7 @@ class TestSuite(fixtures.TestCommon):
         with warnings.catch_warnings():
             # Ignore a library warning.
             warnings.simplefilter("ignore")
-            tiledata = j.read(tile=0)
+            tiledata = j._read(tile=0)
 
         with patch("sys.stdout", new=StringIO()) as fake_out:
             glymur.Jp2k(self.temp_j2k_filename, data=tiledata, verbose=True)


=====================================
tests/test_commandline_tiff2jp2.py
=====================================
@@ -428,7 +428,7 @@ class TestSuite(fixtures.TestCommon):
         """
         path = ir.files('tests.data.tiff').joinpath('basn6a08.tif')
         buffer = path.read_bytes()
-        ifd = glymur.lib.tiff.tiff_header(buffer)
+        ifd = glymur.lib._tiff.tiff_header(buffer)
         icc_profile = bytes(ifd['ICCProfile'])
 
         sys.argv = [


=====================================
tests/test_jp2k.py
=====================================
@@ -368,7 +368,7 @@ class TestJp2k(fixtures.TestCommon):
         with warnings.catch_warnings():
             # Suppress the DeprecationWarning
             warnings.simplefilter("ignore")
-            thumbnail1 = j.read(rlevel=-1)
+            thumbnail1 = j._read(rlevel=-1)
         thumbnail2 = j[::32, ::32]
         np.testing.assert_array_equal(thumbnail1, thumbnail2)
         self.assertEqual(thumbnail1.shape, (25, 15, 3))
@@ -975,7 +975,7 @@ class TestVersion(fixtures.TestCommon):
                     with warnings.catch_warnings():
                         # Suppress a deprecation warning for raw read method.
                         warnings.simplefilter("ignore")
-                        glymur.Jp2k(self.jp2file).read()
+                        glymur.Jp2k(self.jp2file)._read()
                 with self.assertRaises(RuntimeError):
                     glymur.Jp2k(self.jp2file)[:]
 


=====================================
tests/test_jp2k_writes.py
=====================================
@@ -1546,7 +1546,8 @@ class TestSuite(fixtures.TestCommon):
     def test_ignore_pclr_cmap_cdef_on_old_read(self):
         """
         The old "read" interface allowed for passing ignore_pclr_cmap_cdef
-        to read a palette dataset "uninterpolated".
+        to read a palette dataset "uninterpolated", but we have to
+        use properties now.
         """
         jpx = Jp2k(self.jpxfile)
         jpx.ignore_pclr_cmap_cdef = True
@@ -1556,7 +1557,8 @@ class TestSuite(fixtures.TestCommon):
         with warnings.catch_warnings():
             # Ignore a deprecation warning.
             warnings.simplefilter('ignore')
-            actual = jpx2.read(ignore_pclr_cmap_cdef=True)
+            jpx2.ignore_pclr_cmap_cdef = True
+            actual = jpx2._read()
 
         np.testing.assert_array_equal(actual, expected)
 


=====================================
tests/test_jp2kr.py
=====================================
@@ -276,7 +276,7 @@ class TestJp2kr(fixtures.TestCommon):
         with warnings.catch_warnings():
             # Suppress the DeprecationWarning
             warnings.simplefilter("ignore")
-            thumbnail1 = j.read(rlevel=-1)
+            thumbnail1 = j._read(rlevel=-1)
         thumbnail2 = j[::32, ::32]
         np.testing.assert_array_equal(thumbnail1, thumbnail2)
         self.assertEqual(thumbnail1.shape, (25, 15, 3))
@@ -894,7 +894,7 @@ class TestVersion(fixtures.TestCommon):
                     with warnings.catch_warnings():
                         # Suppress a deprecation warning for raw read method.
                         warnings.simplefilter("ignore")
-                        glymur.Jp2kr(self.jp2file).read()
+                        glymur.Jp2kr(self.jp2file)._read()
                 with self.assertRaises(RuntimeError):
                     glymur.Jp2kr(self.jp2file)[:]
 


=====================================
tests/test_libtiff.py
=====================================
@@ -12,7 +12,7 @@ import skimage
 
 # local imports
 from . import fixtures
-from glymur.lib import tiff as libtiff
+from glymur.lib import _tiff as libtiff
 
 
 @unittest.skipIf(


=====================================
tests/test_printing.py
=====================================
@@ -1673,16 +1673,17 @@ class TestJp2dump(fixtures.TestCommon):
         with patch('sys.stdout', new=StringIO()) as fake_out:
             print(icpt)
             actual = fake_out.getvalue().strip()
-        expected = ("<class 'glymur.lib.openjp2.ImageComptParmType'>:\n"
-                    "    dx: 0\n"
-                    "    dy: 0\n"
-                    "    w: 0\n"
-                    "    h: 0\n"
-                    "    x0: 0\n"
-                    "    y0: 0\n"
-                    "    prec: 0\n"
-                    "    bpp: 0\n"
-                    "    sgnd: 0")
+        expected = (
+            "<class 'glymur.lib.openjp2.ImageComptParmType'>:\n"
+            "    dx: 0\n"
+            "    dy: 0\n"
+            "    w: 0\n"
+            "    h: 0\n"
+            "    x0: 0\n"
+            "    y0: 0\n"
+            "    prec: 0\n"
+            "    bpp: 0\n"
+            "    sgnd: 0")
         self.assertEqual(actual, expected)
 
     def test_default_image_type(self):
@@ -1693,14 +1694,16 @@ class TestJp2dump(fixtures.TestCommon):
             actual = fake_out.getvalue().strip()
 
         expected = (
-            "<class 'glymur.lib.openjp2.ImageType'>:\n"
+            "<class 'glymur\\.lib\\.openjp2\\.ImageType'>:\n"
             "    x0: 0\n"
             "    y0: 0\n"
             "    x1: 0\n"
             "    y1: 0\n"
             "    numcomps: 0\n"
             "    color_space: 0\n"
-            "    icc_profile_buf: <(glymur.lib.openjp2|ctypes.wintypes).LP_c_ubyte object at 0x[0-9A-Fa-f]*>\n"  # noqa : E501
+            "    icc_profile_buf: "
+            "<(glymur\\.lib\\.openjp2|ctypes(\\.wintypes)?)\\.LP_c_ubyte "
+            "object at 0x[0-9A-Fa-f]*>\n"
             "    icc_profile_len: 0")
         self.assertRegex(actual, expected)
 
@@ -1709,22 +1712,22 @@ class TestJp2dump(fixtures.TestCommon):
         obj = opj2.ImageCompType()
         actual = str(obj)
         expected = (
-            r'''<class 'glymur.lib.openjp2.ImageCompType'>:\n'''
-            '''    dx: 0\n'''
-            '''    dy: 0\n'''
-            '''    w: 0\n'''
-            '''    h: 0\n'''
-            '''    x0: 0\n'''
-            '''    y0: 0\n'''
-            '''    prec: 0\n'''
-            '''    bpp: 0\n'''
-            '''    sgnd: 0\n'''
-            '''    resno_decoded: 0\n'''
-            '''    factor: 0\n'''
-            '''    data: '''
-            '''<(glymur.lib.openjp2|ctypes.wintypes).LP_c_(int|long) '''
-            '''object at 0x[a-fA-F0-9]+>\n'''
-            '''    alpha: 0\n'''
+            "<class 'glymur\\.lib\\.openjp2\\.ImageCompType'>:\n"
+            "    dx: 0\n"
+            "    dy: 0\n"
+            "    w: 0\n"
+            "    h: 0\n"
+            "    x0: 0\n"
+            "    y0: 0\n"
+            "    prec: 0\n"
+            "    bpp: 0\n"
+            "    sgnd: 0\n"
+            "    resno_decoded: 0\n"
+            "    factor: 0\n"
+            "    data: "
+            "<(glymur\\.lib\\.openjp2|ctypes(\\.wintypes)?)\\.LP_c_(int|long) "
+            "object at 0x[a-fA-F0-9]+>\n"
+            "    alpha: 0\n"
         )
         self.assertRegex(actual, expected)
 


=====================================
tests/test_tiff2jp2.py
=====================================
@@ -1290,7 +1290,7 @@ class TestSuite(fixtures.TestCommon):
         """
         path = ir.files('tests.data.tiff').joinpath('basn6a08.tif')
         buffer = path.read_bytes()
-        ifd = glymur.lib.tiff.tiff_header(buffer)
+        ifd = glymur.lib._tiff.tiff_header(buffer)
         icc_profile = bytes(ifd['ICCProfile'])
 
         with Tiff2Jp2k(


=====================================
tests/test_warnings.py
=====================================
@@ -601,12 +601,6 @@ class TestSuite(fixtures.TestCommon):
             with self.assertWarns(UserWarning):
                 glymur.Jp2k(tfile.name)
 
-    @unittest.skipIf(OPENJPEG_NOT_AVAILABLE, OPENJPEG_NOT_AVAILABLE_MSG)
-    def test_warn_if_using_read_method(self):
-        """Should warn if deprecated read method is called"""
-        with self.assertWarns(DeprecationWarning):
-            Jp2k(self.jp2file).read()
-
     def test_bad_rsiz(self):
         """
         SCENARIO:  The SIZ value parsed from the SIZ segment is invalid.



View it on GitLab: https://salsa.debian.org/debian-gis-team/glymur/-/compare/34631eaf65215e9f3480b4c1765967188d56c569...a5b27e9b3d0c2f9153047ecd5f3740086f0b0f16

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/glymur/-/compare/34631eaf65215e9f3480b4c1765967188d56c569...a5b27e9b3d0c2f9153047ecd5f3740086f0b0f16
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/20250810/a0b1cf3b/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list