[Git][debian-gis-team/pylibtiff][master] 5 commits: New upstream version 0.7.0

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Sat Oct 4 10:32:16 BST 2025



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


Commits:
10608b0c by Antonio Valentino at 2025-10-04T09:07:39+00:00
New upstream version 0.7.0
- - - - -
288f0689 by Antonio Valentino at 2025-10-04T09:07:39+00:00
Update upstream source from tag 'upstream/0.7.0'

Update to upstream version '0.7.0'
with Debian dir 884fa08b09326b69ef76d2aa108e30fa6de93492
- - - - -
6441d9c6 by Antonio Valentino at 2025-10-04T09:08:27+00:00
New upstream release

- - - - -
57cf57a4 by Antonio Valentino at 2025-10-04T09:24:03+00:00
Refresh all patches

- - - - -
3e8dcfcc by Antonio Valentino at 2025-10-04T09:26:23+00:00
Set distribution to unstable

- - - - -


21 changed files:

- .git_archival.txt
- .github/workflows/ci.yaml
- .github/workflows/deploy-sdist.yaml
- debian/changelog
- debian/patches/0001-Disable-bittools-extension.patch
- debian/patches/0002-Robust-definition-list-generation.patch
- − debian/patches/0003-Compatibility-with-numpy2.patch
- + debian/patches/0003-numpy-2.3-compat.patch
- − debian/patches/0004-numpy-2.3-compat.patch
- debian/patches/series
- libtiff/libtiff_ctypes.py
- libtiff/lsm.py
- libtiff/lzw.py
- libtiff/test_bittools.py
- libtiff/tests/test_libtiff_ctypes.py
- libtiff/tiff_file.py
- + libtiff/tiff_h_4_5_1.py
- + libtiff/tiff_h_4_7_0.py
- libtiff/tiff_image.py
- libtiff/utils.py
- pyproject.toml


Changes:

=====================================
.git_archival.txt
=====================================
@@ -1,4 +1,4 @@
-node: 689089d9e7fd03863487463a570c60966c6e74f8
-node-date: 2023-09-21T05:55:44-05:00
-describe-name: v0.6.1
-ref-names: HEAD -> master, tag: v0.6.1
+node: dca4d92070158d9d1cb3e81064254fa6634a1929
+node-date: 2025-10-01T13:48:31-05:00
+describe-name: v0.7.0
+ref-names: tag: v0.7.0


=====================================
.github/workflows/ci.yaml
=====================================
@@ -16,9 +16,9 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout source
-        uses: actions/checkout at v3
+        uses: actions/checkout at v5
       - name: Set up Python
-        uses: actions/setup-python at v4
+        uses: actions/setup-python at v6
         with:
           python-version: "3.10"
       - name: Install dependencies
@@ -40,7 +40,7 @@ jobs:
       fail-fast: true
       matrix:
         os: ["windows-latest", "ubuntu-latest", "macos-latest"]
-        python-version: ["3.8", "3.9", "3.10"]
+        python-version: ["3.9", "3.10", "3.11", "3.12"]
         experimental: [false]
         system-libtiff: [false]
         include:
@@ -61,16 +61,17 @@ jobs:
 
     steps:
       - name: Checkout source
-        uses: actions/checkout at v3
+        uses: actions/checkout at v5
 
       - name: Setup Conda Environment
-        uses: conda-incubator/setup-miniconda at v2
+        uses: conda-incubator/setup-miniconda at v3
         with:
-          miniforge-variant: Mambaforge
           miniforge-version: latest
-          use-mamba: true
+          conda-remove-defaults: true
+          channels: conda-forge
           python-version: ${{ matrix.python-version }}
           activate-environment: pylibtiff
+          channel-priority: strict
 
       - name: Set cache environment variables
         shell: bash -l {0}
@@ -79,14 +80,14 @@ jobs:
           CONDA_PREFIX=$(python -c "import sys; print(sys.prefix)")
           echo "CONDA_PREFIX=$CONDA_PREFIX" >> $GITHUB_ENV
 
-      - uses: actions/cache at v3
+      - uses: actions/cache at v4
         with:
           path: ${{ env.CONDA_PREFIX }}
           key: ${{ matrix.os }}-${{matrix.python-version}}-conda-${{ hashFiles('.conda/environment.yml') }}-${{ env.DATE }}-${{matrix.experimental}}-${{ env.CACHE_NUMBER }}
         id: cache
 
       - name: Update environment
-        run: mamba env update -n pylibtiff -f .conda/environment.yml
+        run: conda env update -n pylibtiff -f .conda/environment.yml
         if: steps.cache.outputs.cache-hit != 'true'
 
       - name: Install unstable dependencies
@@ -106,7 +107,9 @@ jobs:
       - name: Install system libtiff
         if: matrix.system-libtiff == true
         shell: bash -l {0}
-        run: sudo apt-get install -y libtiff-dev
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y libtiff-dev
 
       - name: Install conda libtiff
         if: matrix.system-libtiff == false
@@ -116,13 +119,13 @@ jobs:
       - name: Install pylibtiff
         shell: bash -l {0}
         run: |
-          python -m pip install --no-deps -e .
+          python -m pip install --no-deps -v -e .
 
       - name: Run unit tests
         shell: bash -l {0}
         run: |
           export LD_PRELOAD=${{ env.LD_PRELOAD }};
-          pytest --cov=libtiff libtiff/tests
+          pytest -s --cov=libtiff libtiff/tests
 
       - name: Coveralls Parallel
         uses: AndreMiras/coveralls-python-action at develop


=====================================
.github/workflows/deploy-sdist.yaml
=====================================
@@ -11,7 +11,7 @@ jobs:
 
     steps:
       - name: Checkout source
-        uses: actions/checkout at v3
+        uses: actions/checkout at v5
 
       - name: Create sdist
         shell: bash -l {0}
@@ -21,7 +21,7 @@ jobs:
 
       - name: Publish package to PyPI
         if: github.event.action == 'published'
-        uses: pypa/gh-action-pypi-publish at v1.8.10
+        uses: pypa/gh-action-pypi-publish at v1.13.0
         with:
           user: __token__
           password: ${{ secrets.pypi_password }}


=====================================
debian/changelog
=====================================
@@ -1,10 +1,16 @@
-pylibtiff (0.6.1-4) UNRELEASED; urgency=medium
+pylibtiff (0.7.0-1) unstable; urgency=medium
 
-  * Team upload.
+  [ Bas Couwenberg ]
   * Update lintian overrides.
   * Drop Rules-Requires-Root: no, default since dpkg 1.22.13.
 
- -- Bas Couwenberg <sebastic at debian.org>  Fri, 12 Sep 2025 17:45:20 +0200
+  [ Antonio Valentino ]
+  * New upstream release.
+  * debian/patches:
+    - Drop 0003-Compatibility-with-numpy2.patch.
+    - Refresh and renumber remaining patches.
+
+ -- Antonio Valentino <antonio.valentino at tiscali.it>  Sat, 04 Oct 2025 09:26:05 +0000
 
 pylibtiff (0.6.1-3) unstable; urgency=medium
 


=====================================
debian/patches/0001-Disable-bittools-extension.patch
=====================================
@@ -8,7 +8,7 @@ Forwarded: not-needed
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/libtiff/lzw.py b/libtiff/lzw.py
-index 60dceba..64f2561 100644
+index a703f25..e2e0459 100644
 --- a/libtiff/lzw.py
 +++ b/libtiff/lzw.py
 @@ -7,7 +7,7 @@ This module is obsolete, use tif_lzw extension module instead.


=====================================
debian/patches/0002-Robust-definition-list-generation.patch
=====================================
@@ -8,10 +8,10 @@ Forwarded: not-needed
  1 file changed, 7 insertions(+), 6 deletions(-)
 
 diff --git a/libtiff/libtiff_ctypes.py b/libtiff/libtiff_ctypes.py
-index 4928646..5202747 100644
+index 5f15e15..0761782 100644
 --- a/libtiff/libtiff_ctypes.py
 +++ b/libtiff/libtiff_ctypes.py
-@@ -148,12 +148,13 @@ if tiff_h is None:
+@@ -158,12 +158,13 @@ if tiff_h is None:
          lst.append('%s = %s' % (name, value))
      f.close()
  


=====================================
debian/patches/0003-Compatibility-with-numpy2.patch deleted
=====================================
@@ -1,93 +0,0 @@
-From: Antonio Valentino <antonio.valentino at tiscali.it>
-Date: Tue, 28 Jan 2025 07:25:47 +0000
-Subject: Compatibility with numpy2
-
-Forwarded: https://github.com/pearu/pylibtiff/pull/186
----
- libtiff/libtiff_ctypes.py | 16 ++++++++--------
- libtiff/test_bittools.py  |  4 +++-
- libtiff/tiff_image.py     |  2 +-
- libtiff/utils.py          |  1 +
- 4 files changed, 13 insertions(+), 10 deletions(-)
-
-diff --git a/libtiff/libtiff_ctypes.py b/libtiff/libtiff_ctypes.py
-index 5202747..c776846 100644
---- a/libtiff/libtiff_ctypes.py
-+++ b/libtiff/libtiff_ctypes.py
-@@ -659,13 +659,13 @@ class TIFF(ctypes.c_void_p):
-         compression = self._fix_compression(compression)
- 
-         arr = np.ascontiguousarray(arr)
--        if arr.dtype in np.sctypes['float']:
-+        if np.issubdtype(arr.dtype, np.floating):
-             sample_format = SAMPLEFORMAT_IEEEFP
--        elif arr.dtype in np.sctypes['uint'] + [np.bool_]:
-+        elif np.issubdtype(arr.dtype, np.unsignedinteger) or np.issubdtype(arr.dtype, np.bool_):
-             sample_format = SAMPLEFORMAT_UINT
--        elif arr.dtype in np.sctypes['int']:
-+        elif np.issubdtype(arr.dtype, np.signedinteger):
-             sample_format = SAMPLEFORMAT_INT
--        elif arr.dtype in np.sctypes['complex']:
-+        elif np.issubdtype(arr.dtype, np.complexfloating):
-             sample_format = SAMPLEFORMAT_COMPLEXIEEEFP
-         else:
-             raise NotImplementedError(repr(arr.dtype))
-@@ -746,13 +746,13 @@ class TIFF(ctypes.c_void_p):
-                     compression=None, write_rgb=False):
-         compression = self._fix_compression(compression)
- 
--        if arr.dtype in np.sctypes['float']:
-+        if np.issubdtype(arr.dtype, np.floating):
-             sample_format = SAMPLEFORMAT_IEEEFP
--        elif arr.dtype in np.sctypes['uint'] + [np.bool_]:
-+        elif np.issubdtype(arr.dtype, np.unsignedinteger) or np.issubdtype(arr.dtype, np.bool_):
-             sample_format = SAMPLEFORMAT_UINT
--        elif arr.dtype in np.sctypes['int']:
-+        elif np.issubdtype(arr.dtype, np.signedinteger):
-             sample_format = SAMPLEFORMAT_INT
--        elif arr.dtype in np.sctypes['complex']:
-+        elif np.issubdtype(arr.dtype, np.complexfloating):
-             sample_format = SAMPLEFORMAT_COMPLEXIEEEFP
-         else:
-             raise NotImplementedError(repr(arr.dtype))
-diff --git a/libtiff/test_bittools.py b/libtiff/test_bittools.py
-index a173525..c6cba41 100644
---- a/libtiff/test_bittools.py
-+++ b/libtiff/test_bittools.py
-@@ -19,8 +19,10 @@ def test_setgetbit():
- 
- 
- def test_setgetword():
-+    arange = numpy.arange(-256, 256)
-     for dtype in [numpy.ubyte, numpy.int32, numpy.float64]:
--        arr = numpy.array(list(range(-256, 256)), dtype=dtype)
-+        # arr = numpy.array(list(range(-256, 256)), dtype=dtype)
-+        arr = arange.astype(dtype)
-         arr2 = numpy.zeros(arr.shape, dtype=arr.dtype)
-         for i in range(arr.nbytes):
-             word, next = bittools.getword(arr, i * 8, 8)
-diff --git a/libtiff/tiff_image.py b/libtiff/tiff_image.py
-index 717370a..8e31d0e 100644
---- a/libtiff/tiff_image.py
-+++ b/libtiff/tiff_image.py
-@@ -437,7 +437,7 @@ class TIFFimage:
- 
-         if compressed_data_size != image_data_size:
-             sdiff = image_data_size - compressed_data_size
--            total_size -= sdiff
-+            total_size = int(total_size) - sdiff
-             base = tif._mmap
-             if base is None:
-                 base = tif.base
-diff --git a/libtiff/utils.py b/libtiff/utils.py
-index 7fcfde4..d11d785 100644
---- a/libtiff/utils.py
-+++ b/libtiff/utils.py
-@@ -19,6 +19,7 @@ def isindisk(path):
- 
- def bytes2str(bytes):
-     lst = []
-+    bytes = int(bytes)
-     Pbytes = bytes // 1024**5
-     if Pbytes:
-         lst.append('%sPi' % (Pbytes))


=====================================
debian/patches/0003-numpy-2.3-compat.patch
=====================================
@@ -0,0 +1,22 @@
+From: Antonio Valentino <antonio.valentino at tiscali.it>
+Date: Wed, 10 Sep 2025 06:35:50 +0000
+Subject: numpy-2.3-compat
+
+Forwarded: https://github.com/pearu/pylibtiff/pull/195
+---
+ libtiff/scripts/convert.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libtiff/scripts/convert.py b/libtiff/scripts/convert.py
+index 8ed37ff..574747d 100644
+--- a/libtiff/scripts/convert.py
++++ b/libtiff/scripts/convert.py
+@@ -51,7 +51,7 @@ def runner(parser, options, args):
+     for ifd in tiff.IFD:
+         s = ifd.get('ImageDescription')
+         if s is not None:
+-            description.append(s.value.tostring())
++            description.append(s.value.tobytes())
+     init_description = '\n'.join(description)
+     samples_list, names_list = tiff.get_samples()
+     while samples_list:


=====================================
debian/patches/0004-numpy-2.3-compat.patch deleted
=====================================
@@ -1,67 +0,0 @@
-From: Antonio Valentino <antonio.valentino at tiscali.it>
-Date: Wed, 10 Sep 2025 06:35:50 +0000
-Subject: numpy-2.3-compat
-
----
- libtiff/lzw.py             | 4 ++--
- libtiff/scripts/convert.py | 2 +-
- libtiff/tiff_file.py       | 4 ++--
- 3 files changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/libtiff/lzw.py b/libtiff/lzw.py
-index 64f2561..e2e0459 100644
---- a/libtiff/lzw.py
-+++ b/libtiff/lzw.py
-@@ -39,7 +39,7 @@ def encode_bitarray(seq, max_bits=12):
-     decode_bitarray
-     """
-     if isinstance(seq, numpy.ndarray):
--        seq = seq.tostring()
-+        seq = seq.tobytes()
-     r = bitarray(0, endian='little')
-     write = r.fromword
- 
-@@ -105,7 +105,7 @@ def encode_bittools(seq, max_bits=12):
-     """
-     if isinstance(seq, numpy.ndarray):
-         nbytes = seq.nbytes * 2
--        seq = seq.tostring()
-+        seq = seq.tobytes()
-     else:
-         nbytes = len(seq) * 2
-     r = numpy.zeros((nbytes,), dtype=numpy.ubyte)
-diff --git a/libtiff/scripts/convert.py b/libtiff/scripts/convert.py
-index 8ed37ff..574747d 100644
---- a/libtiff/scripts/convert.py
-+++ b/libtiff/scripts/convert.py
-@@ -51,7 +51,7 @@ def runner(parser, options, args):
-     for ifd in tiff.IFD:
-         s = ifd.get('ImageDescription')
-         if s is not None:
--            description.append(s.value.tostring())
-+            description.append(s.value.tobytes())
-     init_description = '\n'.join(description)
-     samples_list, names_list = tiff.get_samples()
-     while samples_list:
-diff --git a/libtiff/tiff_file.py b/libtiff/tiff_file.py
-index 347fb63..a38b597 100644
---- a/libtiff/tiff_file.py
-+++ b/libtiff/tiff_file.py
-@@ -247,7 +247,7 @@ class TIFFfile(TiffBase):
-             while self.data[offset + i]:
-                 i += 1
-             length = i
--        string = self.get_values(offset, 'BYTE', length).tostring()
-+        string = self.get_values(offset, 'BYTE', length).tobytes()
-         return string
- 
-     def check_memory_usage(self, verbose=True):
-@@ -792,7 +792,7 @@ class IFD:
-                         'DocumentName', 'Model', 'Make', 'PageName',
-                         'DateTime', 'Artist', 'HostComputer']:
-             if value is not None:
--                return value.view('|S{!s}'.format(str(value.nbytes // value.size))).tostring()
-+                return value.view('|S{!s}'.format(str(value.nbytes // value.size))).tobytes()
-         if human:
-             if tag_name == 'Compression':
-                 value = {1: 'Uncompressed', 2: 'CCITT1D', 3: 'Group3Fax',


=====================================
debian/patches/series
=====================================
@@ -1,4 +1,3 @@
 0001-Disable-bittools-extension.patch
 0002-Robust-definition-list-generation.patch
-0003-Compatibility-with-numpy2.patch
-0004-numpy-2.3-compat.patch
+0003-numpy-2.3-compat.patch


=====================================
libtiff/libtiff_ctypes.py
=====================================
@@ -16,12 +16,22 @@ import ctypes
 import ctypes.util
 import struct
 import collections
+import locale
+import warnings
 
 __all__ = ['libtiff', 'TIFF']
 
 cwd = os.getcwd()
 try:
-    os.chdir(os.path.dirname(__file__))
+    try:
+        # Typically, on Windows, the CWD is among the folders searched to locate
+        # a DLL. So change it to the directory containing this module, in case
+        # the libtiff DLL was installed aside it (although that's not typically the case).
+        os.chdir(os.path.dirname(__file__))
+    except FileNotFoundError:
+        # If "frozen" (ie, embedded in an executable), the directory is not real, and chdir fails
+        # => just ignore (and look for the DLL in all the other standard locations)
+        pass
     if os.name == 'nt':
         # assume that the directory of the libtiff DLL is in PATH.
         for lib in ('tiff', 'libtiff', 'libtiff3'):
@@ -227,6 +237,11 @@ class c_thandle_t(ctypes.c_void_p):
 # types defined for creating custom tags
 FIELD_CUSTOM = 65
 
+# Special values for field_readcount & field_writecount
+TIFF_VARIABLE = -1  # The length is variable, this number is passed as an uint16
+TIFFTAG_SPP = -2  # There are as many values as defined in TIFFTAG_SAMPLESPERPIXEL
+TIFF_VARIABLE2 = -3  # The length is variable, this number is passed as an uint32
+
 
 class TIFFDataType(object):
     """Place holder for the enum in C.
@@ -287,8 +302,8 @@ class TIFFFieldInfo(ctypes.Structure):
     """
     typedef struct {
         ttag_t  field_tag;      /* field's tag */
-        short   field_readcount;    /* read count/TIFF_VARIABLE/TIFF_SPP */
-        short   field_writecount;   /* write count/TIFF_VARIABLE */
+        short   field_readcount;    /* read count/TIFF_VARIABLE/TIFF_VARIABLE2/TIFF_SPP */
+        short   field_writecount;   /* write count/TIFF_VARIABLE/TIFF_VARIABLE2*/
         TIFFDataType field_type;    /* type of associated data */
         unsigned short field_bit;   /* bit in fieldsset bit vector */
         unsigned char field_oktochange; /* if true, can change while writing */
@@ -336,23 +351,74 @@ class TIFFExtender(object):
 
 
 def add_tags(tag_list):
+    """
+    Adds support for reading and writing custom tags.
+
+    Parameters
+    ----------
+    tag_list: List of TIFFFieldInfo.
+       The definitions of each new tags to support, as defined by libtiff.
+
+    Returns
+    -------
+        TIFFExtender: the new function that will be used by libtiff to support
+        the new custom tags.
+    """
     tag_list_array = (TIFFFieldInfo * len(tag_list))(*tag_list)
     for field_info in tag_list_array:
-        _name = "TIFFTAG_" + str(field_info.field_name).upper()
-        globals()[_name] = field_info.field_tag
-        if field_info.field_writecount > 1 and field_info.field_type != \
-                TIFFDataType.TIFF_ASCII:
-            tifftags[field_info.field_tag] = (
-                ttype2ctype[
-                    field_info.field_type] * field_info.field_writecount,
-                lambda _d: _d.contents[:])
-        else:
-            tifftags[field_info.field_tag] = (
-                ttype2ctype[field_info.field_type], lambda _d: _d.value)
+        tifftags[field_info.field_tag] = _field_info_to_tifftag(field_info)
+
+        name = "TIFFTAG_" + field_info.field_name.decode("ascii").upper()
+        globals()[name] = field_info.field_tag
 
     return TIFFExtender(tag_list_array)
 
 
+def _field_info_to_tifftag(field_info):
+    """
+    Creates an entry for tifftags based on a field_info.
+
+    Parameters
+    ----------
+    field_info: TIFFFieldInfo
+        The definition of the new tag.
+
+    Returns
+    -------
+       Tuple with: C type of the data (or tuple of C types for the count and data,
+       if it's a variable length field), and a function to convert from the C
+       type to a python type.
+    """
+    data_t = ttype2ctype[field_info.field_type]
+    convert_c_to_py = lambda d: d.value
+
+    # Note: typically field_readcount == field_writecount
+    if field_info.field_readcount != field_info.field_writecount:
+        warnings.warn(f"Unsupported readcount != writecount "
+                      f"({field_info.field_readcount} != {field_info.field_writecount})")
+        # Let's be optimistic and assume it'll work as-is
+
+    # Handle arrays (except for ASCII arrays aka C strings, because they are automatically handled)
+    if (field_info.field_readcount != 1
+        and field_info.field_type != TIFFDataType.TIFF_ASCII
+       ):
+        if field_info.field_readcount > 1:
+            data_t = data_t * field_info.field_readcount
+            convert_c_to_py = lambda d: d.contents[:]
+        elif field_info.field_readcount in (TIFF_VARIABLE, TIFF_VARIABLE2):
+            if field_info.field_readcount == TIFF_VARIABLE:
+                count_t = ctypes.c_uint16
+            else:
+                count_t = ctypes.c_uint32
+            data_t = (count_t, data_t)
+            convert_c_to_py = lambda d: d[1][:d[0]]
+        else:
+            warnings.warn(f"Unsupported readcount {field_info.field_readcount}")
+            # Let's be optimistic and assume the standard behaviour will work
+
+    return (data_t, convert_c_to_py)
+
+
 tifftags = {
 
     # TODO:
@@ -416,7 +482,7 @@ tifftags = {
     TIFFTAG_BITSPERSAMPLE: (ctypes.c_uint16, lambda _d: _d.value),
     TIFFTAG_CLEANFAXDATA: (ctypes.c_uint16, lambda _d: _d.value),
     TIFFTAG_COMPRESSION: (ctypes.c_uint16, lambda _d: _d.value),
-    TIFFTAG_DATATYPE: (ctypes.c_uint16, lambda _d: _d.value),
+    TIFFTAG_DATATYPE: (ctypes.c_uint16, lambda _d: _d.value),  # Obsolete tag replaced by SampleFormat
     TIFFTAG_FILLORDER: (ctypes.c_uint16, lambda _d: _d.value),
     TIFFTAG_INKSET: (ctypes.c_uint16, lambda _d: _d.value),
     TIFFTAG_MATTEING: (ctypes.c_uint16, lambda _d: _d.value),
@@ -432,6 +498,7 @@ tifftags = {
         lambda d: d[1][:d[0]]),  # uint16*, uint16**  count & types array
     TIFFTAG_SAMPLEFORMAT: (ctypes.c_uint16, lambda _d: _d.value),
     TIFFTAG_YCBCRPOSITIONING: (ctypes.c_uint16, lambda _d: _d.value),
+    TIFFTAG_THRESHHOLDING: (ctypes.c_uint16, lambda _d: _d.value),
 
     TIFFTAG_JPEGQUALITY: (ctypes.c_int, lambda _d: _d.value),
     TIFFTAG_JPEGCOLORMODE: (ctypes.c_int, lambda _d: _d.value),
@@ -523,21 +590,34 @@ class TIFF(ctypes.c_void_p):
     @classmethod
     def open(cls, filename, mode='r'):
         """ Open tiff file as TIFF.
+
+        Parameters
+        ----------
+        filename: path-like object (str, bytes, or Path)
+          The path to the file.
+        mode: str
+          Specifies if the file is to be opened for reading ('r'), writing ('w'),
+          or appending ('a'). Optional flags can be passed. See the documentation
+          of TIFFOpen() for the complete list.
         """
-        try:
+        filename = os.fspath(filename)
+
+        if isinstance(filename, str) and hasattr(libtiff, "TIFFOpenW"):
+            # On Windows, the only reliable way to open a file with unicode characters
+            # is to use the *W function.
+            # It needs a str for the argument of type "c_wchar_p"
+            tiff = libtiff.TIFFOpenW(filename, mode.encode('ascii'))
+        else:
+            # It needs bytes for the argument of type "c_char_p"
             try:
-                # Python3: it needs bytes for the arguments of type "c_char_p"
                 filename = os.fsencode(filename)  # no-op if already bytes
-            except AttributeError:
-                # Python2: it needs str for the arguments of type "c_char_p"
-                if isinstance(filename, unicode):  # noqa: F821
-                    filename = filename.encode(sys.getfilesystemencoding())
-        except Exception as ex:
-            # It's probably going to not work, but let it try
-            print('Warning: filename argument is of wrong type or encoding: %s'
-                  % ex)
-
-        tiff = libtiff.TIFFOpen(filename, mode.encode('ascii'))
+            except UnicodeError as ex:
+                # It's probably not going to work, but let's try
+                warnings.warn(f"Warning: filename argument is of wrong type or "
+                              f"encoding for the filesystem: {ex}")
+
+            tiff = libtiff.TIFFOpen(filename, mode.encode('ascii'))
+
         if tiff.value is None:
             raise TypeError('Failed to open file ' + repr(filename))
         return tiff
@@ -658,13 +738,13 @@ class TIFF(ctypes.c_void_p):
         compression = self._fix_compression(compression)
 
         arr = np.ascontiguousarray(arr)
-        if arr.dtype in np.sctypes['float']:
+        if np.issubdtype(arr.dtype, np.floating):
             sample_format = SAMPLEFORMAT_IEEEFP
-        elif arr.dtype in np.sctypes['uint'] + [np.bool_]:
+        elif np.issubdtype(arr.dtype, np.unsignedinteger) or np.issubdtype(arr.dtype, np.bool_):
             sample_format = SAMPLEFORMAT_UINT
-        elif arr.dtype in np.sctypes['int']:
+        elif np.issubdtype(arr.dtype, np.signedinteger):
             sample_format = SAMPLEFORMAT_INT
-        elif arr.dtype in np.sctypes['complex']:
+        elif np.issubdtype(arr.dtype, np.complexfloating):
             sample_format = SAMPLEFORMAT_COMPLEXIEEEFP
         else:
             raise NotImplementedError(repr(arr.dtype))
@@ -745,13 +825,13 @@ class TIFF(ctypes.c_void_p):
                     compression=None, write_rgb=False):
         compression = self._fix_compression(compression)
 
-        if arr.dtype in np.sctypes['float']:
+        if np.issubdtype(arr.dtype, np.floating):
             sample_format = SAMPLEFORMAT_IEEEFP
-        elif arr.dtype in np.sctypes['uint'] + [np.bool_]:
+        elif np.issubdtype(arr.dtype, np.unsignedinteger) or np.issubdtype(arr.dtype, np.bool_):
             sample_format = SAMPLEFORMAT_UINT
-        elif arr.dtype in np.sctypes['int']:
+        elif np.issubdtype(arr.dtype, np.signedinteger):
             sample_format = SAMPLEFORMAT_INT
-        elif arr.dtype in np.sctypes['complex']:
+        elif np.issubdtype(arr.dtype, np.complexfloating):
             sample_format = SAMPLEFORMAT_COMPLEXIEEEFP
         else:
             raise NotImplementedError(repr(arr.dtype))
@@ -1358,17 +1438,19 @@ class TIFF(ctypes.c_void_p):
         tag can be numeric constant TIFFTAG_<tagname> or a
         string containing <tagname>.
         """
+        # Special trick to read extra metadata as text in the ImageDescription
         if tag in ['PixelSizeX', 'PixelSizeY', 'RelativeTime']:
             descr = self.GetField('ImageDescription')
             if not descr:
                 return
-            _i = descr.find(tag)
+            _i = descr.find(tag.encode("ascii"))
             if _i == -1:
                 return
             _value = eval(descr[_i + len(tag):].lstrip().split()[0])
             return _value
+
         if isinstance(tag, str):
-            tag = eval('TIFFTAG_' + tag.upper())
+            tag = globals()['TIFFTAG_' + tag.upper()]
         t = tifftags.get(tag)
         if t is None:
             if not ignore_undefined_tag:
@@ -1447,7 +1529,7 @@ class TIFF(ctypes.c_void_p):
             print("Warning: count argument is deprecated")
 
         if isinstance(tag, str):
-            tag = eval('TIFFTAG_' + tag.upper())
+            tag = globals()['TIFFTAG_' + tag.upper()]
         t = tifftags.get(tag)
         if t is None:
             print('Warning: no tag %r defined' % tag)
@@ -1502,6 +1584,9 @@ class TIFF(ctypes.c_void_p):
             else:
                 data = data_type(_value)
 
+            if issubclass(data_type, ctypes._SimpleCData) and isinstance(data.value, int):
+                data = data.value
+
             if count_type is None:
                 r = libtiff.TIFFSetField(self, c_ttag_t(tag), data)
             else:
@@ -1586,7 +1671,8 @@ class TIFF(ctypes.c_void_p):
                 orig_value = self.GetField(define)
                 if orig_value is None and define not in define_rewrite:
                     continue
-                if _name.endswith('OFFSETS') or _name.endswith('BYTECOUNTS'):
+                if (_name.endswith('OFFSETS') or _name.endswith('BYTECOUNTS')
+                    or define == TIFFTAG_DATATYPE):  # old version of SampleFormat
                     continue
                 if define in define_rewrite:
                     _value = define_rewrite[define]
@@ -1644,36 +1730,18 @@ class TIFF3D(TIFF):
     def open(cls, filename, mode='r'):
         """ just like TIFF.open, except returns a TIFF3D instance.
         """
-        try:
-            try:
-                # Python3: it needs bytes for the arguments of type "c_char_p"
-                filename = os.fsencode(filename)  # no-op if already bytes
-            except AttributeError:
-                # Python2: it needs str for the arguments of type "c_char_p"
-                if isinstance(filename, unicode):  # noqa: F821
-                    filename = filename.encode(sys.getfilesystemencoding())
-        except Exception as ex:
-            # It's probably going to not work, but let it try
-            print('Warning: filename argument is of wrong type or encoding: %s'
-                  % ex)
-        if isinstance(mode, str):
-            mode = mode.encode()
-
         # monkey-patch the restype:
-        old_restype = libtiff.TIFFOpen.restype
         libtiff.TIFFOpen.restype = TIFF3D
+        if hasattr(libtiff, "TIFFOpenW"):
+            libtiff.TIFFOpenW.restype = TIFF3D
+
         try:
-            # actually call the library function:
-            tiff = libtiff.TIFFOpen(filename, mode)
-        except Exception:
-            raise
+            return super().open(filename, mode)
         finally:
             # restore the old restype:
-            libtiff.TIFFOpen.restype = old_restype
-
-        if tiff.value is None:
-            raise TypeError('Failed to open file ' + repr(filename))
-        return tiff
+            libtiff.TIFFOpen.restype = TIFF
+            if hasattr(libtiff, "TIFFOpenW"):
+                libtiff.TIFFOpenW.restype = TIFF
 
     @debug
     def read_image(self, verbose=False, as3d=True):
@@ -1782,6 +1850,10 @@ class CZ_LSMInfo:
 libtiff.TIFFOpen.restype = TIFF
 libtiff.TIFFOpen.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
 
+if hasattr(libtiff, "TIFFOpenW"):  # Windows-only
+    libtiff.TIFFOpenW.restype = TIFF
+    libtiff.TIFFOpenW.argtypes = [ctypes.c_wchar_p, ctypes.c_char_p]
+
 libtiff.TIFFFileName.restype = ctypes.c_char_p
 libtiff.TIFFFileName.argtypes = [TIFF]
 
@@ -1835,8 +1907,13 @@ libtiff.TIFFIsMSB2LSB.argtypes = [TIFF]
 
 # GetField and SetField arguments are dependent on the tag
 libtiff.TIFFGetField.restype = ctypes.c_int
+libtiff.TIFFGetField.argtypes = [TIFF, ctypes.c_uint32]
+
+libtiff.TIFFGetFieldDefaulted.restype = ctypes.c_int
+libtiff.TIFFGetFieldDefaulted.argtypes = [TIFF, ctypes.c_uint32]
 
 libtiff.TIFFSetField.restype = ctypes.c_int
+libtiff.TIFFSetField.argtypes = [TIFF, ctypes.c_uint32]
 
 libtiff.TIFFNumberOfStrips.restype = c_tstrip_t
 libtiff.TIFFNumberOfStrips.argtypes = [TIFF]
@@ -1951,600 +2028,3 @@ def suppress_warnings():
 
 def suppress_errors():
     libtiff.TIFFSetErrorHandler(_null_error_handler)
-
-
-def _test_custom_tags():
-    def _tag_write():
-        a = TIFF.open("/tmp/libtiff_test_custom_tags.tif", "w")
-
-        a.SetField("ARTIST", "MY NAME")
-        a.SetField("LibtiffTestByte", 42)
-        a.SetField("LibtiffTeststr", "FAKE")
-        a.SetField("LibtiffTestuint16", 42)
-        a.SetField("LibtiffTestMultiuint32", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
-        a.SetField("XPOSITION", 42.0)
-        a.SetField("PRIMARYCHROMATICITIES", (1.0, 2, 3, 4, 5, 6))
-
-        arr = np.ones((512, 512), dtype=np.uint8)
-        arr[:, :] = 255
-        a.write_image(arr)
-
-        print("Tag Write: SUCCESS")
-
-    def _tag_read():
-        a = TIFF.open("/tmp/libtiff_test_custom_tags.tif", "r")
-
-        tmp = a.read_image()
-        assert tmp.shape == (
-            512,
-            512), "Image read was wrong shape (%r instead of (512,512))" % (
-            tmp.shape,)
-        tmp = a.GetField("XPOSITION")
-        assert tmp == 42.0, "XPosition was not read as 42.0"
-        tmp = a.GetField("ARTIST")
-        assert tmp == "MY NAME", "Artist was not read as 'MY NAME'"
-        tmp = a.GetField("LibtiffTestByte")
-        assert tmp == 42, "LibtiffTestbyte was not read as 42"
-        tmp = a.GetField("LibtiffTestuint16")
-        assert tmp == 42, "LibtiffTestuint16 was not read as 42"
-        tmp = a.GetField("LibtiffTestMultiuint32")
-        assert tmp == [1, 2, 3, 4, 5, 6, 7, 8, 9,
-                       10], "LibtiffTestMultiuint32 was not read as [1,2,3," \
-                            "4,5,6,7,8,9,10]"
-        tmp = a.GetField("LibtiffTeststr")
-        assert tmp == "FAKE", "LibtiffTeststr was not read as 'FAKE'"
-        tmp = a.GetField("PRIMARYCHROMATICITIES")
-        assert tmp == [1.0, 2.0, 3.0, 4.0, 5.0,
-                       6.0], "PrimaryChromaticities was not read as [1.0," \
-                             "2.0,3.0,4.0,5.0,6.0]"
-        print("Tag Read: SUCCESS")
-
-    # Define a C structure that says how each tag should be used
-    test_tags = [
-        TIFFFieldInfo(40100, 1, 1, TIFFDataType.TIFF_BYTE, FIELD_CUSTOM, True,
-                      False, "LibtiffTestByte"),
-        TIFFFieldInfo(40103, 10, 10, TIFFDataType.TIFF_LONG, FIELD_CUSTOM,
-                      True, False, "LibtiffTestMultiuint32"),
-        TIFFFieldInfo(40102, 1, 1, TIFFDataType.TIFF_SHORT, FIELD_CUSTOM, True,
-                      False, "LibtiffTestuint16"),
-        TIFFFieldInfo(40101, -1, -1, TIFFDataType.TIFF_ASCII, FIELD_CUSTOM,
-                      True, False, "LibtiffTeststr")
-    ]
-
-    # Add tags to the libtiff library
-    # Keep pointer to extender object, no gc:
-    test_extender = add_tags(test_tags)  # noqa: F841
-    _tag_write()
-    _tag_read()
-
-
-def _test_tile_write():
-    a = TIFF.open("/tmp/libtiff_test_tile_write.tiff", "w")
-
-    data_array = np.tile(list(range(500)), (1, 6)).astype(np.uint8)
-    a.SetField("TileWidth", 512)
-    a.SetField("TileLength", 528)
-    # tile_width and tile_height is not set, write_tiles get these values from
-    # TileWidth and TileLength tags
-    assert a.write_tiles(data_array) == (512 * 528) * 6,\
-        "could not write tile images"  # 1D
-    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
-
-    # 2D Arrays
-    data_array = np.tile(list(range(500)), (2500, 6)).astype(np.uint8)
-    assert a.write_tiles(data_array, 512, 528) == (512 * 528) * 5 * 6,\
-        "could not write tile images"  # 2D
-    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
-
-    # 3D Arrays, 3rd dimension as last dimension
-    data_array = np.array(range(2500 * 3000 * 3)).reshape(
-        2500, 3000, 3).astype(np.uint8)
-    assert a.write_tiles(data_array, 512, 528, None, True) \
-        == (512 * 528) * 5 * 6 * 3,\
-        "could not write tile images"  # 3D
-    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
-
-    # 3D Arrays, 3rd dimension as first dimension
-    data_array = np.array(range(2500 * 3000 * 3)).reshape(
-        3, 2500, 3000).astype(np.uint8)
-    assert a.write_tiles(data_array, 512, 528, None, True)\
-        == (512 * 528) * 5 * 6 * 3,\
-        "could not write tile images"  # 3D
-    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
-
-    # Grayscale image with 3 depths
-    data_array = np.array(range(2500 * 3000 * 3)).reshape(
-        3, 2500, 3000).astype(np.uint8)
-    written_bytes = a.write_tiles(data_array, 512, 528)
-    assert written_bytes == 512 * 528 * 5 * 6 * 3,\
-        "could not write tile images, written_bytes: %s" % (written_bytes,)
-    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
-
-    print("Tile Write: SUCCESS")
-
-
-def _test_tile_read(filename="/tmp/libtiff_test_tile_write.tiff"):
-    import sys
-    if filename is None:
-        if len(sys.argv) != 2:
-            print("Run `libtiff.py <filename>` for testing.")
-            return
-        filename = sys.argv[1]
-
-    a = TIFF.open(filename, "r")
-
-    # 1D Arrays (doesn't make much sense to tile)
-    a.SetDirectory(0)
-    # expected tag values for the first image
-    tags = [
-        {"tag": "ImageWidth", "exp_value": 3000},
-        {"tag": "ImageLength", "exp_value": 1},
-        {"tag": "TileWidth", "exp_value": 512},
-        {"tag": "TileLength", "exp_value": 528},
-        {"tag": "BitsPerSample", "exp_value": 8},
-        {"tag": "Compression", "exp_value": 1},
-    ]
-
-    # assert tag values
-    for tag in tags:
-        field_value = a.GetField(tag['tag'])
-        assert field_value == tag['exp_value'],\
-            repr((tag['tag'], tag['exp_value'], field_value))
-
-    data_array = a.read_tiles()
-    print("Tile Read: Read array of shape %r" % (data_array.shape,))
-    assert data_array.shape == (1, 3000), "tile data read was the wrong shape"
-    test_array = np.array(list(range(500)) * 6).astype(np.uint8).flatten()
-    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0,\
-        "tile data read was not the same as the expected data"
-    print("Tile Read: Data is the same as expected from tile write test")
-
-    # 2D Arrays (doesn't make much sense to tile)
-    a.SetDirectory(1)
-    # expected tag values for the second image
-    tags = [
-        {"tag": "ImageWidth", "exp_value": 3000},
-        {"tag": "ImageLength", "exp_value": 2500},
-        {"tag": "TileWidth", "exp_value": 512},
-        {"tag": "TileLength", "exp_value": 528},
-        {"tag": "BitsPerSample", "exp_value": 8},
-        {"tag": "Compression", "exp_value": 1},
-    ]
-
-    # assert tag values
-    for tag in tags:
-        field_value = a.GetField(tag['tag'])
-        assert field_value == tag['exp_value'],\
-            repr((tag['tag'], tag['exp_value'], field_value))
-
-    data_array = a.read_tiles()
-    print("Tile Read: Read array of shape %r" % (data_array.shape,))
-    assert data_array.shape == (2500, 3000),\
-        "tile data read was the wrong shape"
-    test_array = np.tile(list(range(500)),
-                         (2500, 6)).astype(np.uint8).flatten()
-    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0,\
-        "tile data read was not the same as the expected data"
-    print("Tile Read: Data is the same as expected from tile write test")
-
-    # 3D Arrays, 3rd dimension as last dimension
-    a.SetDirectory(2)
-    # expected tag values for the third image
-    tags = [
-        {"tag": "ImageWidth", "exp_value": 3000},
-        {"tag": "ImageLength", "exp_value": 2500},
-        {"tag": "TileWidth", "exp_value": 512},
-        {"tag": "TileLength", "exp_value": 528},
-        {"tag": "BitsPerSample", "exp_value": 8},
-        {"tag": "Compression", "exp_value": 1},
-    ]
-
-    # assert tag values
-    for tag in tags:
-        field_value = a.GetField(tag['tag'])
-        assert field_value == tag['exp_value'],\
-            repr(tag['tag'], tag['exp_value'], field_value)
-
-    data_array = a.read_tiles()
-    print("Tile Read: Read array of shape %r" % (data_array.shape,))
-    assert data_array.shape == (2500, 3000, 3),\
-        "tile data read was the wrong shape"
-    test_array = np.array(range(2500 * 3000 * 3)).reshape(
-        2500, 3000, 3).astype(np.uint8).flatten()
-    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0,\
-        "tile data read was not the same as the expected data"
-    print("Tile Read: Data is the same as expected from tile write test")
-
-    # 3D Arrays, 3rd dimension as first dimension
-    a.SetDirectory(3)
-    # expected tag values for the third image
-    tags = [
-        {"tag": "ImageWidth", "exp_value": 3000},
-        {"tag": "ImageLength", "exp_value": 2500},
-        {"tag": "TileWidth", "exp_value": 512},
-        {"tag": "TileLength", "exp_value": 528},
-        {"tag": "BitsPerSample", "exp_value": 8},
-        {"tag": "Compression", "exp_value": 1},
-    ]
-
-    # assert tag values
-    for tag in tags:
-        field_value = a.GetField(tag['tag'])
-        assert field_value == tag['exp_value'],\
-            repr(tag['tag'], tag['exp_value'], field_value)
-
-    data_array = a.read_tiles()
-    print("Tile Read: Read array of shape %r" % (data_array.shape,))
-    assert data_array.shape == (3, 2500, 3000),\
-        "tile data read was the wrong shape"
-    test_array = np.array(range(2500 * 3000 * 3)).reshape(
-        3, 2500, 3000).astype(np.uint8).flatten()
-    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0,\
-        "tile data read was not the same as the expected data"
-    print("Tile Read: Data is the same as expected from tile write test")
-
-    # Grayscale image with 3 depths
-    a.SetDirectory(4)
-
-    # expected tag values for the third image
-    tags = [
-        {"tag": "ImageWidth", "exp_value": 3000},
-        {"tag": "ImageLength", "exp_value": 2500},
-        {"tag": "TileWidth", "exp_value": 512},
-        {"tag": "TileLength", "exp_value": 528},
-        {"tag": "BitsPerSample", "exp_value": 8},
-        {"tag": "Compression", "exp_value": 1},
-        {"tag": "ImageDepth", "exp_value": 3}
-    ]
-
-    # assert tag values
-    for tag in tags:
-        field_value = a.GetField(tag['tag'])
-        assert field_value == tag['exp_value'],\
-            repr([tag['tag'], tag['exp_value'], field_value])
-
-    data_array = a.read_tiles()
-    print("Tile Read: Read array of shape %r" % (data_array.shape,))
-    assert data_array.shape == (3, 2500, 3000),\
-        "tile data read was the wrong shape"
-    test_array = np.array(range(2500 * 3000 * 3)).reshape(
-        3, 2500, 3000).astype(np.uint8).flatten()
-    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0,\
-        "tile data read was not the same as the expected data"
-    print("Tile Read: Data is the same as expected from tile write test")
-
-    print("Tile Read: SUCCESS")
-
-
-def _test_read_one_tile():
-    filename = "/tmp/libtiff_test_tile_write.tiff"
-    tiff = TIFF.open(filename, "r")
-
-    # the first image is 1 pixel high
-    tile = tiff.read_one_tile(0, 0)
-    assert tile.shape == (1, 512), repr(tile.shape)
-
-    # second image, 3000 x 2500
-    tiff.SetDirectory(1)
-    tile = tiff.read_one_tile(0, 0)
-    assert tile.shape == (528, 512), repr(tile.shape)
-
-    tile = tiff.read_one_tile(512, 528)
-    assert tile.shape == (528, 512), repr(tile.shape)
-
-    # test tile on the right border
-    tile = tiff.read_one_tile(2560, 528)
-    assert tile.shape == (528, 440), repr(tile.shape)
-
-    # test tile on the bottom border
-    tile = tiff.read_one_tile(512, 2112)
-    assert tile.shape == (388, 512), repr(tile.shape)
-
-    # test tile on the right and bottom borders
-    tile = tiff.read_one_tile(2560, 2112)
-    assert tile.shape == (388, 440), repr(tile.shape)
-
-    # test x and y values not multiples of the tile width and height
-    tile = tiff.read_one_tile(530, 600)
-    assert tile[0][0] == 12, tile[0][0]
-
-    # test negative x
-    try:
-        tiff.read_one_tile(-5, 0)
-        raise AssertionError(
-            "An exception must be raised with invalid (x, y) values")
-    except ValueError as inst:
-        assert inst.message == "Invalid x value", repr(inst.message)
-
-    # test y greater than the image height
-    try:
-        tiff.read_one_tile(0, 5000)
-        raise AssertionError(
-            "An exception must be raised with invalid (x, y) values")
-    except ValueError as inst:
-        assert inst.message == "Invalid y value", repr(inst.message)
-
-    # RGB image sized 3000 x 2500, PLANARCONFIG_SEPARATE
-    tiff.SetDirectory(3)
-    tile = tiff.read_one_tile(0, 0)
-    assert tile.shape == (3, 528, 512), repr(tile.shape)
-    # get the tile on the lower bottom corner
-    tile = tiff.read_one_tile(2999, 2499)
-    assert tile.shape == (3, 388, 440), repr(tile.shape)
-
-    # Grayscale image sized 3000 x 2500, 3 depths
-    tiff.SetDirectory(4)
-    tile = tiff.read_one_tile(0, 0)
-    assert tile.shape == (3, 528, 512), repr(tile.shape)
-    # get the tile on the lower bottom corner
-    tile = tiff.read_one_tile(2999, 2499)
-    assert tile.shape == (3, 388, 440), repr(tile.shape)
-
-
-def _test_tiled_image_read(filename="/tmp/libtiff_test_tile_write.tiff"):
-    """
-    Tests opening a tiled image
-    """
-
-    def assert_image_tag(tiff, tag_name, expected_value):
-        value = tiff.GetField(tag_name)
-        assert value == expected_value,\
-            ('%s expected to be %d, but it\'s %d'
-             % (tag_name, expected_value, value))
-
-    # _test_tile_write is called here just to make sure that the image
-    # is saved, even if the order of the tests changed
-    _test_tile_write()
-    tiff = TIFF.open(filename, "r")
-
-    # sets the current image to the second image
-    tiff.SetDirectory(1)
-    # test tag values
-    assert_image_tag(tiff, 'ImageWidth', 3000)
-    assert_image_tag(tiff, 'ImageLength', 2500)
-    assert_image_tag(tiff, 'TileWidth', 512)
-    assert_image_tag(tiff, 'TileLength', 528)
-    assert_image_tag(tiff, 'BitsPerSample', 8)
-    assert_image_tag(tiff, 'Compression', COMPRESSION_NONE)  # noqa: F821
-
-    # read the image to a NumPy array
-    arr = tiff.read_image()
-    # test image NumPy array dimensions
-    assert arr.shape[0] == 2500, \
-        'Image width expected to be 2500, but it\'s %d' % (arr.shape[0])
-    assert arr.shape[1] == 3000, \
-        'Image height expected to be 3000, but it\'s %d' % (arr.shape[1])
-
-    # generates the same array that was generated for the image
-    data_array = np.array(list(range(500)) * 6).astype(np.uint8)
-    # tests if the array from the read image is the same of the original image
-    assert (data_array == arr).all(), \
-        'The read tiled image is different from the generated image'
-
-
-def _test_tags_write():
-    tiff = TIFF.open('/tmp/libtiff_tags_write.tiff', mode='w')
-    tmp = tiff.SetField("Artist", "A Name")
-    assert tmp == 1, "Tag 'Artist' was not written properly"
-    tmp = tiff.SetField("DocumentName", "")
-    assert tmp == 1, "Tag 'DocumentName' with empty string was not written " \
-                     "properly"
-    tmp = tiff.SetField("PrimaryChromaticities", [1, 2, 3, 4, 5, 6])
-    assert tmp == 1, "Tag 'PrimaryChromaticities' was not written properly"
-    tmp = tiff.SetField("BitsPerSample", 8)
-    assert tmp == 1, "Tag 'BitsPerSample' was not written properly"
-    tmp = tiff.SetField("ColorMap", [[x * 256 for x in range(256)]] * 3)
-    assert tmp == 1, "Tag 'ColorMap' was not written properly"
-
-    arr = np.zeros((100, 100), np.uint8)
-    tiff.write_image(arr)
-
-    print("Tag Write: SUCCESS")
-
-
-def _test_tags_read(filename=None):
-    import sys
-    if filename is None:
-        if len(sys.argv) != 2:
-            filename = '/tmp/libtiff_tags_write.tiff'
-            if not os.path.isfile(filename):
-                print('Run `%s <filename>` for testing.' % (__file__))
-                return
-        else:
-            filename = sys.argv[1]
-    tiff = TIFF.open(filename)
-    tmp = tiff.GetField("Artist")
-    assert tmp == "A Name", "Tag 'Artist' did not read the correct value (" \
-        "Got '%s'; Expected 'A Name')" % (tmp,)
-    tmp = tiff.GetField("DocumentName")
-    assert tmp == "", "Tag 'DocumentName' did not read the correct value (" \
-        "Got '%s'; Expected empty string)" % (tmp,)
-    tmp = tiff.GetField("PrimaryChromaticities")
-    assert tmp == [1, 2, 3, 4, 5,
-                   6], "Tag 'PrimaryChromaticities' did not read the " \
-                       "correct value (Got '%r'; Expected '[1,2,3,4,5,6]'" % (
-        tmp,)
-    tmp = tiff.GetField("BitsPerSample")
-    assert tmp == 8, "Tag 'BitsPerSample' did not read the correct value (" \
-                     "Got %s; Expected 8)" % (str(tmp),)
-    tmp = tiff.GetField("ColorMap")
-    try:
-        assert len(
-            tmp) == 3, "Tag 'ColorMap' should be three arrays, found %d" % \
-                       len(tmp)
-        assert len(tmp[
-                       0]) == 256, "Tag 'ColorMap' should be three arrays " \
-                                   "of 256 elements, found %d elements" % \
-                                   len(tmp[0])
-        assert len(tmp[
-                       1]) == 256, "Tag 'ColorMap' should be three arrays " \
-                                   "of 256 elements, found %d elements" % \
-                                   len(tmp[1])
-        assert len(tmp[
-                       2]) == 256, "Tag 'ColorMap' should be three arrays " \
-                                   "of 256 elements, found %d elements" % \
-                                   len(tmp[2])
-    except TypeError:
-        print(
-            "Tag 'ColorMap' has the wrong shape of 3 arrays of 256 elements "
-            "each")
-        return
-
-    print("Tag Read: SUCCESS")
-
-
-def _test_read(filename=None):
-    import sys
-    import time
-    if filename is None:
-        if len(sys.argv) != 2:
-            filename = '/tmp/libtiff_test_write.tiff'
-            if not os.path.isfile(filename):
-                print('Run `libtiff.py <filename>` for testing.')
-                return
-        else:
-            filename = sys.argv[1]
-    print('Trying to open', filename, '...', end=' ')
-    tiff = TIFF.open(filename)
-    print('ok')
-    print('Trying to show info ...\n', '-' * 10)
-    print(tiff.info())
-    print('-' * 10, 'ok')
-    print('Trying show images ...')
-    t = time.time()
-    _i = 0
-    for image in tiff.iter_images(verbose=True):
-        # print image.min(), image.max(), image.mean ()
-        _i += 1
-    print('\tok', (time.time() - t) * 1e3, 'ms', _i, 'images')
-
-
-def _test_write():
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='w')
-    arr = np.zeros((5, 6), np.uint32)
-    for _i in range(arr.shape[0]):
-        for j in range(arr.shape[1]):
-            arr[_i, j] = _i + 10 * j
-    print(arr)
-    tiff.write_image(arr)
-    del tiff
-
-
-def _test_write_float():
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='w')
-    arr = np.zeros((5, 6), np.float64)
-    for _i in range(arr.shape[0]):
-        for j in range(arr.shape[1]):
-            arr[_i, j] = _i + 10 * j
-    print(arr)
-    tiff.write_image(arr)
-    del tiff
-
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='r')
-    print(tiff.info())
-    arr2 = tiff.read_image()
-    print(arr2)
-
-
-def _test_write_rgba():
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='w')
-    arr = np.zeros((5, 6, 4), np.uint8)
-    for i in np.ndindex(*arr.shape):
-        arr[i] = 20 * i[0] + 10 * i[1] + i[2]
-    print(arr)
-    tiff.write_image(arr, write_rgb=True)
-    del tiff
-
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='r')
-    print(tiff.info())
-    arr2 = tiff.read_image()
-    print(arr2)
-
-    np.testing.assert_array_equal(arr, arr2)
-
-
-def _test_tree():
-    # Write a TIFF image with the following tree structure:
-    # Im0 --SubIFD--> Im0,1 ---> Im0,2 ---> Im0,3
-    #  |
-    #  V
-    # Im1
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='w')
-    arr = np.zeros((5, 6), np.uint32)
-    for i in np.ndindex(*arr.shape):
-        arr[i] = i[0] + 20 * i[1]
-    print(arr)
-    n = 3
-    tiff.SetField("SubIFD", [0] * n)
-    tiff.write_image(arr)
-    for i in range(n):
-        arr[0, 0] = i
-        tiff.write_image(arr)
-
-    arr[0, 0] = 255
-    tiff.write_image(arr)
-    del tiff
-
-    tiff = TIFF.open('/tmp/libtiff_test_write.tiff', mode='r')
-    print(tiff.info())
-    n = 0
-    for im in tiff.iter_images(verbose=True):
-        print(im)
-        n += 1
-
-    assert n == 2
-
-
-def _test_copy():
-    tiff = TIFF.open('/tmp/libtiff_test_compression.tiff', mode='w')
-    arr = np.zeros((5, 6), np.uint32)
-    for _i in range(arr.shape[0]):
-        for j in range(arr.shape[1]):
-            arr[_i, j] = 1 + _i + 10 * j
-    # from scipy.stats import poisson
-    # arr = poisson.rvs (arr)
-    tiff.SetField('ImageDescription', 'Hey\nyou')
-    tiff.write_image(arr, compression='lzw')
-    del tiff
-
-    tiff = TIFF.open('/tmp/libtiff_test_compression.tiff', mode='r')
-    print(tiff.info())
-    arr2 = tiff.read_image()
-
-    assert (arr == arr2).all(), 'arrays not equal'
-
-    for compression in ['none', 'lzw', 'deflate']:
-        for sampleformat in ['int', 'uint', 'float']:
-            for bitspersample in [256, 128, 64, 32, 16, 8]:
-                if sampleformat == 'float' and (
-                                bitspersample < 32 or bitspersample > 128):
-                    continue
-                if sampleformat in ['int', 'uint'] and bitspersample > 64:
-                    continue
-                # print compression, sampleformat, bitspersample
-                tiff.copy('/tmp/libtiff_test_copy2.tiff',
-                          compression=compression,
-                          imagedescription='hoo',
-                          sampleformat=sampleformat,
-                          bitspersample=bitspersample)
-                tiff2 = TIFF.open('/tmp/libtiff_test_copy2.tiff', mode='r')
-                arr3 = tiff2.read_image()
-                assert (arr == arr3).all(), 'arrays not equal %r' % (
-                    (compression, sampleformat, bitspersample),)
-    print('test copy ok')
-
-
-if __name__ == '__main__':
-    _test_custom_tags()
-    _test_tile_write()
-    _test_tile_read()
-    _test_read_one_tile()
-    _test_tiled_image_read()
-    _test_tags_write()
-    _test_tags_read()
-    _test_write_float()
-    _test_write_rgba()
-    _test_tree()
-    _test_write()
-    _test_read()
-    _test_copy()


=====================================
libtiff/lsm.py
=====================================
@@ -34,7 +34,6 @@ def IFDEntry_lsm_str_hook(entry):
 def IFDEntry_lsm_init_hook(ifdentry):
     """Make tiff.IFDENTRYEntry CZ_LSM aware.
     """
-    global tiff_module_dict
     if ifdentry.tag == CZ_LSMInfo_tag:
         # replace type,count=(BYTE,500) with (CZ_LSMInfo, 1)
         reserved_bytes = (ifdentry.count - CZ_LSMInfo_dtype_fields_size)


=====================================
libtiff/lzw.py
=====================================
@@ -39,7 +39,7 @@ def encode_bitarray(seq, max_bits=12):
     decode_bitarray
     """
     if isinstance(seq, numpy.ndarray):
-        seq = seq.tostring()
+        seq = seq.tobytes()
     r = bitarray(0, endian='little')
     write = r.fromword
 
@@ -105,7 +105,7 @@ def encode_bittools(seq, max_bits=12):
     """
     if isinstance(seq, numpy.ndarray):
         nbytes = seq.nbytes * 2
-        seq = seq.tostring()
+        seq = seq.tobytes()
     else:
         nbytes = len(seq) * 2
     r = numpy.zeros((nbytes,), dtype=numpy.ubyte)


=====================================
libtiff/test_bittools.py
=====================================
@@ -19,8 +19,10 @@ def test_setgetbit():
 
 
 def test_setgetword():
+    arange = numpy.arange(-256, 256)
     for dtype in [numpy.ubyte, numpy.int32, numpy.float64]:
-        arr = numpy.array(list(range(-256, 256)), dtype=dtype)
+        # arr = numpy.array(list(range(-256, 256)), dtype=dtype)
+        arr = arange.astype(dtype)
         arr2 = numpy.zeros(arr.shape, dtype=arr.dtype)
         for i in range(arr.nbytes):
             word, next = bittools.getword(arr, i * 8, 8)


=====================================
libtiff/tests/test_libtiff_ctypes.py
=====================================
@@ -1,5 +1,7 @@
-import pytest
+import ctypes
 import numpy as np
+import pytest
+import time
 from libtiff import TIFFimage
 
 lt = pytest.importorskip('libtiff.libtiff_ctypes')
@@ -14,3 +16,901 @@ def test_issue69(tmp_path):
     del tif
     tif = lt.TIFF3D.open(fn)
     tif.close()
+
+
+# Hold the extenders created, as dereferencing any of them could cause a crash
+extenders = []
+
+
+def test_custom_tags(tmp_path):
+    def _tag_write():
+        a = lt.TIFF.open(tmp_path / "libtiff_test_custom_tags.tif", "w")
+
+        a.SetField("ARTIST", b"MY NAME")
+        a.SetField("LibtiffTestByte", 42)
+        a.SetField("LibtiffTeststr", b"FAKE")
+        a.SetField("LibtiffTestuint16", 42)
+        a.SetField("LibtiffTestMultiuint32", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+        a.SetField("LibtiffTestBytes", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+        a.SetField("XPOSITION", 42.0)
+        a.SetField("PRIMARYCHROMATICITIES", (1.0, 2, 3, 4, 5, 6))
+
+        arr = np.ones((512, 512), dtype=np.uint8)
+        arr[:, :] = 255
+        a.write_image(arr)
+
+        print("Tag Write: SUCCESS")
+
+    def _tag_read():
+        a = lt.TIFF.open(tmp_path / "libtiff_test_custom_tags.tif", "r")
+
+        tmp = a.read_image()
+        assert tmp.shape == (512, 512), \
+            "Image read was wrong shape (%r instead of (512,512))" % (tmp.shape,)
+        tmp = a.GetField("XPOSITION")
+        assert tmp == 42.0, "XPosition was not read as 42.0"
+        tmp = a.GetField("ARTIST")
+        assert tmp == b"MY NAME", "Artist was not read as 'MY NAME'"
+        tmp = a.GetField("LibtiffTestByte")
+        assert tmp == 42, "LibtiffTestbyte was not read as 42"
+        tmp = a.GetField("LibtiffTestuint16")
+        assert tmp == 42, "LibtiffTestuint16 was not read as 42"
+        tmp = a.GetField("LibtiffTestMultiuint32")
+        assert tmp == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], \
+            "LibtiffTestMultiuint32 was not read as [1,2,3,4,5,6,7,8,9,10]"
+        tmp = a.GetField("LibtiffTeststr")
+        assert tmp == b"FAKE", "LibtiffTeststr was not read as 'FAKE'"
+        tmp = a.GetField("LibtiffTestBytes")
+        assert tmp == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+        tmp = a.GetField("PRIMARYCHROMATICITIES")
+        assert tmp == [1.0, 2.0, 3.0, 4.0, 5.0, 6.0], \
+            "PrimaryChromaticities was not read as [1.0,2.0,3.0,4.0,5.0,6.0]"
+        print("Tag Read: SUCCESS")
+
+    # Define a C structure that says how each tag should be used
+    test_tags = [
+        lt.TIFFFieldInfo(40100, 1, 1, lt.TIFFDataType.TIFF_BYTE, lt.FIELD_CUSTOM,
+                         True, False, b"LibtiffTestByte"),
+        lt.TIFFFieldInfo(40103, 10, 10, lt.TIFFDataType.TIFF_LONG, lt.FIELD_CUSTOM,
+                         True, False, b"LibtiffTestMultiuint32"),
+        lt.TIFFFieldInfo(40102, 1, 1, lt.TIFFDataType.TIFF_SHORT, lt.FIELD_CUSTOM,
+                         True, False, b"LibtiffTestuint16"),
+        lt.TIFFFieldInfo(40101, -1, -1, lt.TIFFDataType.TIFF_ASCII, lt.FIELD_CUSTOM,
+                         True, False, b"LibtiffTeststr"),
+        lt.TIFFFieldInfo(40104, lt.TIFF_VARIABLE2, lt.TIFF_VARIABLE2, lt.TIFFDataType.TIFF_BYTE,
+                         lt.FIELD_CUSTOM, True, True, b"LibtiffTestBytes"),
+    ]
+
+    # Add tags to the libtiff library
+    # Keep pointer to extender object, no gc:
+    test_extender = lt.add_tags(test_tags)  # noqa: F841
+    extenders.append(test_extender)
+    _tag_write()
+    _tag_read()
+
+
+def test_tile_write(tmp_path):
+    a = lt.TIFF.open(tmp_path / "libtiff_test_tile_write.tiff", "w")
+
+    data_array = np.tile(list(range(500)), (1, 6)).astype(np.uint8)
+    a.SetField("TileWidth", 512)
+    a.SetField("TileLength", 528)
+    # tile_width and tile_height is not set, write_tiles get these values from
+    # TileWidth and TileLength tags
+    assert a.write_tiles(data_array) == (512 * 528) * 6, "could not write tile images"  # 1D
+    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
+
+    # 2D Arrays
+    data_array = np.tile(list(range(500)), (2500, 6)).astype(np.uint8)
+    assert a.write_tiles(data_array, 512, 528) == (512 * 528) * 5 * 6, \
+        "could not write tile images"  # 2D
+    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
+
+    # 3D Arrays, 3rd dimension as last dimension
+    data_array = np.array(range(2500 * 3000 * 3))
+    data_array = data_array.reshape(2500, 3000, 3).astype(np.uint8)
+    assert a.write_tiles(data_array, 512, 528, None, True) == (512 * 528) * 5 * 6 * 3, \
+        "could not write tile images"  # 3D
+    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
+
+    # 3D Arrays, 3rd dimension as first dimension
+    data_array = np.array(range(2500 * 3000 * 3)).reshape(
+        3, 2500, 3000).astype(np.uint8)
+    assert a.write_tiles(data_array, 512, 528, None, True) == (512 * 528) * 5 * 6 * 3, \
+        "could not write tile images"  # 3D
+    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
+
+    # Grayscale image with 3 depths
+    data_array = np.array(range(2500 * 3000 * 3)).reshape(
+        3, 2500, 3000).astype(np.uint8)
+    written_bytes = a.write_tiles(data_array, 512, 528)
+    assert written_bytes == 512 * 528 * 5 * 6 * 3, \
+        "could not write tile images, written_bytes: %s" % (written_bytes,)
+    print("Tile Write: Wrote array of shape %r" % (data_array.shape,))
+
+    print("Tile Write: SUCCESS")
+
+
+def test_tile_read(tmp_path):
+    test_tile_write(tmp_path)  # Create file first
+
+    filename = tmp_path / "libtiff_test_tile_write.tiff"
+    a = lt.TIFF.open(filename, "r")
+
+    # 1D Arrays (doesn't make much sense to tile)
+    a.SetDirectory(0)
+    # expected tag values for the first image
+    tags = [
+        {"tag": "ImageWidth", "exp_value": 3000},
+        {"tag": "ImageLength", "exp_value": 1},
+        {"tag": "TileWidth", "exp_value": 512},
+        {"tag": "TileLength", "exp_value": 528},
+        {"tag": "BitsPerSample", "exp_value": 8},
+        {"tag": "Compression", "exp_value": 1},
+    ]
+
+    # assert tag values
+    for tag in tags:
+        field_value = a.GetField(tag['tag'])
+        assert field_value == tag['exp_value'], \
+            repr((tag['tag'], tag['exp_value'], field_value))
+
+    data_array = a.read_tiles()
+    print("Tile Read: Read array of shape %r" % (data_array.shape,))
+    assert data_array.shape == (1, 3000), "tile data read was the wrong shape"
+    test_array = np.array(list(range(500)) * 6).astype(np.uint8).flatten()
+    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0, \
+        "tile data read was not the same as the expected data"
+    print("Tile Read: Data is the same as expected from tile write test")
+
+    # 2D Arrays (doesn't make much sense to tile)
+    a.SetDirectory(1)
+    # expected tag values for the second image
+    tags = [
+        {"tag": "ImageWidth", "exp_value": 3000},
+        {"tag": "ImageLength", "exp_value": 2500},
+        {"tag": "TileWidth", "exp_value": 512},
+        {"tag": "TileLength", "exp_value": 528},
+        {"tag": "BitsPerSample", "exp_value": 8},
+        {"tag": "Compression", "exp_value": 1},
+    ]
+
+    # assert tag values
+    for tag in tags:
+        field_value = a.GetField(tag['tag'])
+        assert field_value == tag['exp_value'], \
+            repr((tag['tag'], tag['exp_value'], field_value))
+
+    data_array = a.read_tiles()
+    print("Tile Read: Read array of shape %r" % (data_array.shape,))
+    assert data_array.shape == (2500, 3000), \
+        "tile data read was the wrong shape"
+    test_array = np.tile(list(range(500)),
+                         (2500, 6)).astype(np.uint8).flatten()
+    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0, \
+        "tile data read was not the same as the expected data"
+    print("Tile Read: Data is the same as expected from tile write test")
+
+    # 3D Arrays, 3rd dimension as last dimension
+    a.SetDirectory(2)
+    # expected tag values for the third image
+    tags = [
+        {"tag": "ImageWidth", "exp_value": 3000},
+        {"tag": "ImageLength", "exp_value": 2500},
+        {"tag": "TileWidth", "exp_value": 512},
+        {"tag": "TileLength", "exp_value": 528},
+        {"tag": "BitsPerSample", "exp_value": 8},
+        {"tag": "Compression", "exp_value": 1},
+    ]
+
+    # assert tag values
+    for tag in tags:
+        field_value = a.GetField(tag['tag'])
+        assert field_value == tag['exp_value'], \
+            repr(tag['tag'], tag['exp_value'], field_value)
+
+    data_array = a.read_tiles()
+    print("Tile Read: Read array of shape %r" % (data_array.shape,))
+    assert data_array.shape == (2500, 3000, 3), \
+        "tile data read was the wrong shape"
+    test_array = np.array(range(2500 * 3000 * 3)).reshape(
+        2500, 3000, 3).astype(np.uint8).flatten()
+    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0, \
+        "tile data read was not the same as the expected data"
+    print("Tile Read: Data is the same as expected from tile write test")
+
+    # 3D Arrays, 3rd dimension as first dimension
+    a.SetDirectory(3)
+    # expected tag values for the third image
+    tags = [
+        {"tag": "ImageWidth", "exp_value": 3000},
+        {"tag": "ImageLength", "exp_value": 2500},
+        {"tag": "TileWidth", "exp_value": 512},
+        {"tag": "TileLength", "exp_value": 528},
+        {"tag": "BitsPerSample", "exp_value": 8},
+        {"tag": "Compression", "exp_value": 1},
+    ]
+
+    # assert tag values
+    for tag in tags:
+        field_value = a.GetField(tag['tag'])
+        assert field_value == tag['exp_value'], \
+            repr(tag['tag'], tag['exp_value'], field_value)
+
+    data_array = a.read_tiles()
+    print("Tile Read: Read array of shape %r" % (data_array.shape,))
+    assert data_array.shape == (3, 2500, 3000), \
+        "tile data read was the wrong shape"
+    test_array = np.array(range(2500 * 3000 * 3))
+    test_array = test_array.reshape(3, 2500, 3000).astype(np.uint8).flatten()
+    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0, \
+        "tile data read was not the same as the expected data"
+    print("Tile Read: Data is the same as expected from tile write test")
+
+    # Grayscale image with 3 depths
+    a.SetDirectory(4)
+
+    # expected tag values for the third image
+    tags = [
+        {"tag": "ImageWidth", "exp_value": 3000},
+        {"tag": "ImageLength", "exp_value": 2500},
+        {"tag": "TileWidth", "exp_value": 512},
+        {"tag": "TileLength", "exp_value": 528},
+        {"tag": "BitsPerSample", "exp_value": 8},
+        {"tag": "Compression", "exp_value": 1},
+        {"tag": "ImageDepth", "exp_value": 3}
+    ]
+
+    # assert tag values
+    for tag in tags:
+        field_value = a.GetField(tag['tag'])
+        assert field_value == tag['exp_value'], \
+            repr([tag['tag'], tag['exp_value'], field_value])
+
+    data_array = a.read_tiles()
+    print("Tile Read: Read array of shape %r" % (data_array.shape,))
+    assert data_array.shape == (3, 2500, 3000), \
+        "tile data read was the wrong shape"
+    test_array = np.array(range(2500 * 3000 * 3)).reshape(
+        3, 2500, 3000).astype(np.uint8).flatten()
+    assert np.nonzero(data_array.flatten() != test_array)[0].shape[0] == 0, \
+        "tile data read was not the same as the expected data"
+    print("Tile Read: Data is the same as expected from tile write test")
+
+    print("Tile Read: SUCCESS")
+
+
+def test_read_one_tile(tmp_path):
+    test_tile_write(tmp_path)  # Create file first
+
+    filename = tmp_path / "libtiff_test_tile_write.tiff"
+    tiff = lt.TIFF.open(filename, "r")
+
+    # the first image is 1 pixel high
+    tile = tiff.read_one_tile(0, 0)
+    assert tile.shape == (1, 512), repr(tile.shape)
+
+    # second image, 3000 x 2500
+    tiff.SetDirectory(1)
+    tile = tiff.read_one_tile(0, 0)
+    assert tile.shape == (528, 512), repr(tile.shape)
+
+    tile = tiff.read_one_tile(512, 528)
+    assert tile.shape == (528, 512), repr(tile.shape)
+
+    # test tile on the right border
+    tile = tiff.read_one_tile(2560, 528)
+    assert tile.shape == (528, 440), repr(tile.shape)
+
+    # test tile on the bottom border
+    tile = tiff.read_one_tile(512, 2112)
+    assert tile.shape == (388, 512), repr(tile.shape)
+
+    # test tile on the right and bottom borders
+    tile = tiff.read_one_tile(2560, 2112)
+    assert tile.shape == (388, 440), repr(tile.shape)
+
+    # test x and y values not multiples of the tile width and height
+    tile = tiff.read_one_tile(530, 600)
+    assert tile[0][0] == 12, tile[0][0]
+
+    # test negative x
+    try:
+        tiff.read_one_tile(-5, 0)
+        raise AssertionError(
+            "An exception must be raised with invalid (x, y) values")
+    except ValueError as inst:
+        assert str(inst) == "Invalid x value", inst
+
+    # test y greater than the image height
+    try:
+        tiff.read_one_tile(0, 5000)
+        raise AssertionError(
+            "An exception must be raised with invalid (x, y) values")
+    except ValueError as inst:
+        assert str(inst) == "Invalid y value", inst
+
+    # RGB image sized 3000 x 2500, PLANARCONFIG_SEPARATE
+    tiff.SetDirectory(3)
+    tile = tiff.read_one_tile(0, 0)
+    assert tile.shape == (3, 528, 512), repr(tile.shape)
+    # get the tile on the lower bottom corner
+    tile = tiff.read_one_tile(2999, 2499)
+    assert tile.shape == (3, 388, 440), repr(tile.shape)
+
+    # Grayscale image sized 3000 x 2500, 3 depths
+    tiff.SetDirectory(4)
+    tile = tiff.read_one_tile(0, 0)
+    assert tile.shape == (3, 528, 512), repr(tile.shape)
+    # get the tile on the lower bottom corner
+    tile = tiff.read_one_tile(2999, 2499)
+    assert tile.shape == (3, 388, 440), repr(tile.shape)
+
+
+def test_tiled_image_read(tmp_path):
+    """
+    Tests opening a tiled image
+    """
+    test_tile_write(tmp_path)  # Create file first
+    filename = tmp_path / "libtiff_test_tile_write.tiff"
+
+    def assert_image_tag(tiff, tag_name, expected_value):
+        value = tiff.GetField(tag_name)
+        assert value == expected_value, \
+            ('%s expected to be %d, but it\'s %d'
+             % (tag_name, expected_value, value))
+
+    tiff = lt.TIFF.open(filename, "r")
+
+    # sets the current image to the second image
+    tiff.SetDirectory(1)
+    # test tag values
+    assert_image_tag(tiff, 'ImageWidth', 3000)
+    assert_image_tag(tiff, 'ImageLength', 2500)
+    assert_image_tag(tiff, 'TileWidth', 512)
+    assert_image_tag(tiff, 'TileLength', 528)
+    assert_image_tag(tiff, 'BitsPerSample', 8)
+    assert_image_tag(tiff, 'Compression', lt.COMPRESSION_NONE)  # noqa: F821
+
+    # read the image to a NumPy array
+    arr = tiff.read_image()
+    # test image NumPy array dimensions
+    assert arr.shape[0] == 2500, \
+        'Image width expected to be 2500, but it\'s %d' % (arr.shape[0])
+    assert arr.shape[1] == 3000, \
+        'Image height expected to be 3000, but it\'s %d' % (arr.shape[1])
+
+    # generates the same array that was generated for the image
+    data_array = np.array(list(range(500)) * 6).astype(np.uint8)
+    # tests if the array from the read image is the same of the original image
+    assert (data_array == arr).all(), \
+        'The read tiled image is different from the generated image'
+
+
+def test_tags_write(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_tags_write.tiff', mode='w')
+    tmp = tiff.SetField("Artist", b"A Name")
+    assert tmp == 1, "Tag 'Artist' was not written properly"
+    tmp = tiff.SetField("DocumentName", b"")
+    assert tmp == 1, "Tag 'DocumentName' with empty string was not written properly"
+    tmp = tiff.SetField("PrimaryChromaticities", [1, 2, 3, 4, 5, 6])
+    assert tmp == 1, "Tag 'PrimaryChromaticities' was not written properly"
+    tmp = tiff.SetField("BitsPerSample", 8)
+    assert tmp == 1, "Tag 'BitsPerSample' was not written properly"
+    tmp = tiff.SetField("ColorMap", [[x * 256 for x in range(256)]] * 3)
+    assert tmp == 1, "Tag 'ColorMap' was not written properly"
+
+    arr = np.zeros((100, 100), np.uint8)
+    tiff.write_image(arr)
+
+    print("Tag Write: SUCCESS")
+
+
+def test_tags_read(tmp_path):
+    test_tags_write(tmp_path)
+
+    filename = tmp_path / 'libtiff_tags_write.tiff'
+    tiff = lt.TIFF.open(filename)
+    tmp = tiff.GetField("Artist")
+    assert tmp == b"A Name", "Tag 'Artist' did not read the correct value (" \
+        "Got '%s'; Expected 'A Name')" % (tmp,)
+    tmp = tiff.GetField("DocumentName")
+    assert tmp == b"", "Tag 'DocumentName' did not read the correct value (" \
+        "Got '%s'; Expected empty string)" % (tmp,)
+    tmp = tiff.GetField("PrimaryChromaticities")
+    assert tmp == [1, 2, 3, 4, 5, 6], \
+        "Tag 'PrimaryChromaticities' did not read the " \
+        "correct value (Got '%r'; Expected '[1,2,3,4,5,6]'" % (tmp,)
+    tmp = tiff.GetField("BitsPerSample")
+    assert tmp == 8, "Tag 'BitsPerSample' did not read the correct value (" \
+                     "Got %s; Expected 8)" % (str(tmp),)
+    tmp = tiff.GetField("ColorMap")
+    try:
+        assert len(tmp) == 3, \
+            f"Tag 'ColorMap' should be three arrays, found {len(tmp)}"
+        assert len(tmp[0]) == 256, \
+            f"Tag 'ColorMap' should be three arrays of 256 elements, found {len(tmp[0])} elements"
+        assert len(tmp[1]) == 256, \
+            f"Tag 'ColorMap' should be three arrays of 256 elements, found {len(tmp[1])} elements"
+        assert len(tmp[2]) == 256, \
+            f"Tag 'ColorMap' should be three arrays of 256 elements, found {len(tmp[2])} elements"
+    except TypeError:
+        print("Tag 'ColorMap' has the wrong shape of 3 arrays of 256 elements each")
+        return
+
+    print("Tag Read: SUCCESS")
+
+
+def test_write(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='w')
+    arr = np.zeros((5, 6), np.uint32)
+    for _i in range(arr.shape[0]):
+        for j in range(arr.shape[1]):
+            arr[_i, j] = _i + 10 * j
+    print(arr)
+    tiff.write_image(arr)
+    del tiff
+
+
+def test_read(tmp_path):
+    test_write(tmp_path)
+
+    filename = tmp_path / 'libtiff_test_write.tiff'
+    print('Trying to open', filename, '...', end=' ')
+    tiff = lt.TIFF.open(filename)
+    print('Trying to show info ...\n', '-' * 10)
+    print(tiff.info())
+    print('-' * 10, 'ok')
+    print('Trying show images ...')
+    t = time.time()
+    i = 0
+    for image in tiff.iter_images(verbose=True):
+        print(image.min(), image.max(), image.mean())
+        i += 1
+    print('\tok', (time.time() - t) * 1e3, 'ms', i, 'images')
+
+
+def test_write_float(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='w')
+    arr = np.zeros((5, 6), np.float64)
+    for i in range(arr.shape[0]):
+        for j in range(arr.shape[1]):
+            arr[i, j] = i + 10 * j
+    print(arr)
+    tiff.write_image(arr)
+    del tiff
+
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='r')
+    print(tiff.info())
+    arr2 = tiff.read_image()
+    print(arr2)
+
+
+def test_write_rgba(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='w')
+    arr = np.zeros((5, 6, 4), np.uint8)
+    for i in np.ndindex(*arr.shape):
+        arr[i] = 20 * i[0] + 10 * i[1] + i[2]
+    print(arr)
+    tiff.write_image(arr, write_rgb=True)
+    del tiff
+
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='r')
+    print(tiff.info())
+    arr2 = tiff.read_image()
+    print(arr2)
+
+    np.testing.assert_array_equal(arr, arr2)
+
+
+def test_tree(tmp_path):
+    # Write a TIFF image with the following tree structure:
+    # Im0 --SubIFD--> Im0,1 ---> Im0,2 ---> Im0,3
+    #  |
+    #  V
+    # Im1
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='w')
+    arr = np.zeros((5, 6), np.uint32)
+    for i in np.ndindex(*arr.shape):
+        arr[i] = i[0] + 20 * i[1]
+    print(arr)
+    n = 3
+    tiff.SetField("SubIFD", [0] * n)
+    tiff.write_image(arr)
+    for i in range(n):
+        arr[0, 0] = i
+        tiff.write_image(arr)
+
+    arr[0, 0] = 255
+    tiff.write_image(arr)
+    del tiff
+
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_write.tiff', mode='r')
+    print(tiff.info())
+    n = 0
+    for im in tiff.iter_images(verbose=True):
+        print(im)
+        n += 1
+
+    assert n == 2
+
+
+def test_copy(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_compression.tiff', mode='w')
+    arr = np.zeros((5, 6), np.uint32)
+    for _i in range(arr.shape[0]):
+        for j in range(arr.shape[1]):
+            arr[_i, j] = 1 + _i + 10 * j
+    # from scipy.stats import poisson
+    # arr = poisson.rvs (arr)
+    tiff.SetField('ImageDescription', b'Hey\nyou')
+    tiff.write_image(arr, compression='lzw')
+    del tiff
+
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_test_compression.tiff', mode='r')
+    print(tiff.info())
+    arr2 = tiff.read_image()
+
+    assert (arr == arr2).all(), 'arrays not equal'
+
+    for compression in ['none', 'lzw', 'deflate']:
+        for sampleformat in ['int', 'uint', 'float']:
+            for bitspersample in [128, 64, 32, 16, 8]:
+                dtype_name = f"{sampleformat}{bitspersample}"
+                if not hasattr(np, dtype_name):  # Skip non existing types
+                    continue
+                print(f"Testing convertion to {dtype_name}")
+                # With compression, less data types supported
+                if compression != 'none' and bitspersample > 32:
+                    continue
+                # print compression, sampleformat, bitspersample
+                tiff.copy(tmp_path / 'libtiff_test_copy2.tiff',
+                          compression=compression,
+                          imagedescription=b'hoo',
+                          sampleformat=sampleformat,
+                          bitspersample=bitspersample)
+                tiff2 = lt.TIFF.open(tmp_path / 'libtiff_test_copy2.tiff', mode='r')
+                arr3 = tiff2.read_image()
+                assert (arr == arr3).all(), 'arrays not equal %r' % (
+                    (compression, sampleformat, bitspersample),)
+    print('test copy ok')
+
+
+def test_set_get_field_lowlevel(tmp_path):
+    ltc = lt.libtiff
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_set_get_field_lowlevel.tiff', mode='w')
+
+    # Store the output of TIFFGetField
+    uint16_data = ctypes.c_uint16(0)
+    p_uint16_data = ctypes.byref(uint16_data)
+    uint32_data = ctypes.c_uint32(0)
+    p_uint32_data = ctypes.byref(uint32_data)
+    float_data = ctypes.c_float(0.0)
+    p_float_data = ctypes.byref(float_data)
+    double_data = ctypes.c_double(0.0)
+    p_double_data = ctypes.byref(double_data)
+    char_p_data = ctypes.c_char_p(b'')
+    p_char_p_data = ctypes.byref(char_p_data)
+
+    # Store the output of TIFFGetFieldDefaulted
+    uint16_data_defaulted = ctypes.c_uint16(0)
+    p_uint16_data_defaulted = ctypes.byref(uint16_data_defaulted)
+    uint32_data_defaulted = ctypes.c_uint32(0)
+    p_uint32_data_defaulted = ctypes.byref(uint32_data_defaulted)
+    float_data_defaulted = ctypes.c_float(0.0)
+    p_float_data_defaulted = ctypes.byref(float_data_defaulted)
+    double_data_defaulted = ctypes.c_double(0.0)
+    p_double_data_defaulted = ctypes.byref(double_data_defaulted)
+    char_p_data_defaulted = ctypes.c_char_p(b'')
+    p_char_p_data_defaulted = ctypes.byref(char_p_data_defaulted)
+
+    # Test uint16 tags
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SAMPLEFORMAT, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.SAMPLEFORMAT_UINT
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SAMPLEFORMAT, lt.SAMPLEFORMAT_INT)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SAMPLEFORMAT, p_uint16_data)
+    assert uint16_data.value == lt.SAMPLEFORMAT_INT
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SAMPLEFORMAT, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.SAMPLEFORMAT_INT
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SAMPLEFORMAT, lt.SAMPLEFORMAT_UINT)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SAMPLEFORMAT, p_uint16_data)
+    assert uint16_data.value == lt.SAMPLEFORMAT_UINT
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SAMPLEFORMAT, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.SAMPLEFORMAT_UINT
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_COMPRESSION, lt.COMPRESSION_LZW)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_COMPRESSION, p_uint16_data)
+    assert uint16_data.value == lt.COMPRESSION_LZW
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_COMPRESSION, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.COMPRESSION_LZW
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_ORIENTATION, lt.ORIENTATION_TOPLEFT)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_ORIENTATION, p_uint16_data)
+    assert uint16_data.value == lt.ORIENTATION_TOPLEFT
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_ORIENTATION, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.ORIENTATION_TOPLEFT
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_THRESHHOLDING, lt.THRESHHOLD_BILEVEL)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_THRESHHOLDING, p_uint16_data)
+    assert uint16_data.value == lt.THRESHHOLD_BILEVEL
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_THRESHHOLDING, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.THRESHHOLD_BILEVEL
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_FILLORDER, lt.FILLORDER_MSB2LSB)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_FILLORDER, p_uint16_data)
+    assert uint16_data.value == lt.FILLORDER_MSB2LSB
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_FILLORDER, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == lt.FILLORDER_MSB2LSB
+
+    # Test uint32 tags
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_IMAGEWIDTH, 256)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_IMAGEWIDTH, p_uint32_data)
+    assert uint32_data.value == 256
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_IMAGEWIDTH, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == 256
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_IMAGELENGTH, 256)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_IMAGELENGTH, p_uint32_data)
+    assert uint32_data.value == 256
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_IMAGELENGTH, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == 256
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SUBFILETYPE, lt.FILETYPE_REDUCEDIMAGE)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SUBFILETYPE, p_uint32_data)
+    assert uint32_data.value == lt.FILETYPE_REDUCEDIMAGE
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SUBFILETYPE, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == lt.FILETYPE_REDUCEDIMAGE
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_TILEWIDTH, 256)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_TILEWIDTH, p_uint32_data)
+    assert uint32_data.value == 256
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_TILEWIDTH, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == 256
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_TILELENGTH, 256)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_TILELENGTH, p_uint32_data)
+    assert uint32_data.value == 256
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_TILELENGTH, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == 256
+
+    # Test float tags
+    # NOTE: some tags are defined as float but can be set as float or double
+    # Using ctypes.c_float instead of ctypes.c_double results in
+    #       "RuntimeError: ffi_prep_cif_var failed"
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_XRESOLUTION, ctypes.c_double(88.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_XRESOLUTION, p_float_data)
+    assert float_data.value == 88.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_XRESOLUTION, p_float_data_defaulted)
+    assert float_data_defaulted.value == 88.0
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_YRESOLUTION, ctypes.c_double(88.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_YRESOLUTION, p_float_data)
+    assert float_data.value == 88.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_YRESOLUTION, p_float_data_defaulted)
+    assert float_data_defaulted.value == 88.0
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_XPOSITION, ctypes.c_double(88.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_XPOSITION, p_float_data)
+    assert float_data.value == 88.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_XPOSITION, p_float_data_defaulted)
+    assert float_data_defaulted.value == 88.0
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_YPOSITION, ctypes.c_double(88.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_YPOSITION, p_float_data)
+    assert float_data.value == 88.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_YPOSITION, p_float_data_defaulted)
+    assert float_data_defaulted.value == 88.0
+
+    # Test double tags
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SMAXSAMPLEVALUE, ctypes.c_double(255.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SMAXSAMPLEVALUE, p_double_data)
+    assert double_data.value == 255.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SMAXSAMPLEVALUE, p_double_data_defaulted)
+    assert double_data_defaulted.value == 255.0
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SMINSAMPLEVALUE, ctypes.c_double(0.0))
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SMINSAMPLEVALUE, p_double_data)
+    assert double_data.value == 0.0
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SMINSAMPLEVALUE, p_double_data_defaulted)
+    assert double_data_defaulted.value == 0.0
+
+    # Test string tags
+    test_string = b"test string"
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_ARTIST, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_ARTIST, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_ARTIST, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_DATETIME, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_DATETIME, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_DATETIME, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_HOSTCOMPUTER, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_HOSTCOMPUTER, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_HOSTCOMPUTER, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_IMAGEDESCRIPTION, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_IMAGEDESCRIPTION, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_IMAGEDESCRIPTION, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_MAKE, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_MAKE, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_MAKE, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_MODEL, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_MODEL, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_MODEL, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_SOFTWARE, test_string)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_SOFTWARE, p_char_p_data)
+    assert char_p_data.value == test_string
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_SOFTWARE, p_char_p_data_defaulted)
+    assert char_p_data_defaulted.value == test_string
+
+    # Test setting a tag with a different data type
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_IMAGEWIDTH, 128)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_IMAGEWIDTH, p_uint32_data)
+    assert uint32_data.value == 128
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_IMAGEWIDTH, p_uint32_data_defaulted)
+    assert uint32_data_defaulted.value == 128
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_BITSPERSAMPLE, 8)
+    assert ltc.TIFFGetField(tiff, lt.TIFFTAG_BITSPERSAMPLE, p_uint16_data)
+    assert uint16_data.value == 8
+    assert ltc.TIFFGetFieldDefaulted(tiff, lt.TIFFTAG_BITSPERSAMPLE, p_uint16_data_defaulted)
+    assert uint16_data_defaulted.value == 8
+
+    # Test tags with count > 1
+    # Create three arrays of 256 16-bit integers
+    colormap_red = (ctypes.c_uint16 * 256)(*range(256))
+    colormap_green = (ctypes.c_uint16 * 256)(*range(256))
+    colormap_blue = (ctypes.c_uint16 * 256)(*range(256))
+
+    # Create pointers to receive colormap data
+    p_colormap_red = ctypes.POINTER(ctypes.c_uint16)()
+    p_colormap_green = ctypes.POINTER(ctypes.c_uint16)()
+    p_colormap_blue = ctypes.POINTER(ctypes.c_uint16)()
+
+    p_colormap_red_defaulted = ctypes.POINTER(ctypes.c_uint16)()
+    p_colormap_green_defaulted = ctypes.POINTER(ctypes.c_uint16)()
+    p_colormap_blue_defaulted = ctypes.POINTER(ctypes.c_uint16)()
+
+    assert ltc.TIFFSetField(tiff, lt.TIFFTAG_COLORMAP, colormap_red, colormap_green, colormap_blue)
+    assert ltc.TIFFGetField(
+        tiff, lt.TIFFTAG_COLORMAP,
+        ctypes.byref(p_colormap_red),
+        ctypes.byref(p_colormap_green),
+        ctypes.byref(p_colormap_blue)
+    )
+    assert ltc.TIFFGetFieldDefaulted(
+        tiff, lt.TIFFTAG_COLORMAP,
+        ctypes.byref(p_colormap_red_defaulted),
+        ctypes.byref(p_colormap_green_defaulted),
+        ctypes.byref(p_colormap_blue_defaulted)
+    )
+
+    # Check that the retrieved values are correct
+    for i in range(256):
+        assert p_colormap_red[i] == i
+        assert p_colormap_green[i] == i
+        assert p_colormap_blue[i] == i
+
+        assert p_colormap_red_defaulted[i] == i
+        assert p_colormap_green_defaulted[i] == i
+        assert p_colormap_blue_defaulted[i] == i
+
+    tiff.close()
+
+
+def test_set_get_field(tmp_path):
+    tiff = lt.TIFF.open(tmp_path / 'libtiff_set_get_field_lowlevel.tiff', mode='w')
+
+    # Test uint16 tags
+    tiff.SetField('SampleFormat', lt.SAMPLEFORMAT_INT)
+    assert tiff.GetField('SampleFormat') == lt.SAMPLEFORMAT_INT
+
+    tiff.SetField('Compression', lt.COMPRESSION_LZW)
+    assert tiff.GetField('Compression') == lt.COMPRESSION_LZW
+
+    tiff.SetField('Orientation', lt.ORIENTATION_TOPLEFT)
+    assert tiff.GetField('Orientation') == lt.ORIENTATION_TOPLEFT
+
+    tiff.SetField('Threshholding', lt.THRESHHOLD_BILEVEL)
+    assert tiff.GetField('Threshholding') == lt.THRESHHOLD_BILEVEL
+
+    tiff.SetField('FillOrder', lt.FILLORDER_MSB2LSB)
+    assert tiff.GetField('FillOrder') == lt.FILLORDER_MSB2LSB
+
+    # Test uint32 tags
+    tiff.SetField('ImageWidth', 256)
+    assert tiff.GetField('ImageWidth') == 256
+
+    tiff.SetField('ImageLength', 256)
+    assert tiff.GetField('ImageLength') == 256
+
+    tiff.SetField('SubfileType', lt.FILETYPE_REDUCEDIMAGE)
+    assert tiff.GetField('SubfileType') == lt.FILETYPE_REDUCEDIMAGE
+
+    tiff.SetField('TileWidth', 256)
+    assert tiff.GetField('TileWidth') == 256
+
+    tiff.SetField('TileLength', 256)
+    assert tiff.GetField('TileLength') == 256
+
+    # Test float tags
+    tiff.SetField('XResolution', 88.0)
+    assert tiff.GetField('XResolution') == 88.0
+
+    tiff.SetField('YResolution', 88.0)
+    assert tiff.GetField('YResolution') == 88.0
+
+    tiff.SetField('XPosition', 88.0)
+    assert tiff.GetField('XPosition') == 88.0
+
+    tiff.SetField('YPosition', 88.0)
+    assert tiff.GetField('YPosition') == 88.0
+
+    # Test double tags
+    tiff.SetField('SMaxSampleValue', 255.0)
+    assert tiff.GetField('SMaxSampleValue') == 255.0
+
+    tiff.SetField('SMinSampleValue', 0.0)
+    assert tiff.GetField('SMinSampleValue') == 0.0
+
+    # Test string tags
+    test_string = b"test string"
+    tiff.SetField('Artist', test_string)
+    assert tiff.GetField('Artist') == test_string
+
+    tiff.SetField('DateTime', test_string)
+    assert tiff.GetField('DateTime') == test_string
+
+    tiff.SetField('HostComputer', test_string)
+    assert tiff.GetField('HostComputer') == test_string
+
+    tiff.SetField('ImageDescription', test_string)
+    assert tiff.GetField('ImageDescription') == test_string
+
+    tiff.SetField('Make', test_string)
+    assert tiff.GetField('Make') == test_string
+
+    tiff.SetField('Model', test_string)
+    assert tiff.GetField('Model') == test_string
+
+    tiff.SetField('Software', test_string)
+    assert tiff.GetField('Software') == test_string
+
+    # Test setting a tag with a different data type
+    tiff.SetField('ImageWidth', 128)
+    assert tiff.GetField('ImageWidth') == 128
+
+    tiff.SetField('BitsPerSample', 8)
+    assert tiff.GetField('BitsPerSample') == 8
+
+    # Test tags with count > 1
+    colormap_red = list(range(256))
+    colormap_green = list(range(256))
+    colormap_blue = list(range(256))
+    tiff.SetField('ColorMap', [colormap_red, colormap_green, colormap_blue])
+    p_colormap_red, p_colormap_green, p_colormap_blue = tiff.GetField('ColorMap')
+
+    # Check that the retrieved values are correct
+    for i in range(256):
+        assert p_colormap_red[i] == i
+        assert p_colormap_green[i] == i
+        assert p_colormap_blue[i] == i
+
+    tiff.close()


=====================================
libtiff/tiff_file.py
=====================================
@@ -247,7 +247,7 @@ class TIFFfile(TiffBase):
             while self.data[offset + i]:
                 i += 1
             length = i
-        string = self.get_values(offset, 'BYTE', length).tostring()
+        string = self.get_values(offset, 'BYTE', length).tobytes()
         return string
 
     def check_memory_usage(self, verbose=True):
@@ -792,7 +792,7 @@ class IFD:
                         'DocumentName', 'Model', 'Make', 'PageName',
                         'DateTime', 'Artist', 'HostComputer']:
             if value is not None:
-                return value.view('|S{!s}'.format(str(value.nbytes // value.size))).tostring()
+                return value.view('|S{!s}'.format(str(value.nbytes // value.size))).tobytes()
         if human:
             if tag_name == 'Compression':
                 value = {1: 'Uncompressed', 2: 'CCITT1D', 3: 'Group3Fax',


=====================================
libtiff/tiff_h_4_5_1.py
=====================================
@@ -0,0 +1,629 @@
+TIFF_VERSION_CLASSIC = 42
+TIFF_VERSION_BIG = 43
+TIFF_BIGENDIAN = 19789
+TIFF_LITTLEENDIAN = 18761
+MDI_LITTLEENDIAN = 20549
+MDI_BIGENDIAN = 17744
+TIFFTAG_SUBFILETYPE = 254
+FILETYPE_REDUCEDIMAGE = 1
+FILETYPE_PAGE = 2
+FILETYPE_MASK = 4
+TIFFTAG_OSUBFILETYPE = 255
+OFILETYPE_IMAGE = 1
+OFILETYPE_REDUCEDIMAGE = 2
+OFILETYPE_PAGE = 3
+TIFFTAG_IMAGEWIDTH = 256
+TIFFTAG_IMAGELENGTH = 257
+TIFFTAG_BITSPERSAMPLE = 258
+TIFFTAG_COMPRESSION = 259
+COMPRESSION_NONE = 1
+COMPRESSION_CCITTRLE = 2
+COMPRESSION_CCITTFAX3 = 3
+COMPRESSION_CCITT_T4 = 3
+COMPRESSION_CCITTFAX4 = 4
+COMPRESSION_CCITT_T6 = 4
+COMPRESSION_LZW = 5
+COMPRESSION_OJPEG = 6
+COMPRESSION_JPEG = 7
+COMPRESSION_T85 = 9
+COMPRESSION_T43 = 10
+COMPRESSION_NEXT = 32766
+COMPRESSION_CCITTRLEW = 32771
+COMPRESSION_PACKBITS = 32773
+COMPRESSION_THUNDERSCAN = 32809
+COMPRESSION_IT8CTPAD = 32895
+COMPRESSION_IT8LW = 32896
+COMPRESSION_IT8MP = 32897
+COMPRESSION_IT8BL = 32898
+COMPRESSION_PIXARFILM = 32908
+COMPRESSION_PIXARLOG = 32909
+COMPRESSION_DEFLATE = 32946
+COMPRESSION_ADOBE_DEFLATE = 8
+COMPRESSION_DCS = 32947
+COMPRESSION_JBIG = 34661
+COMPRESSION_SGILOG = 34676
+COMPRESSION_SGILOG24 = 34677
+COMPRESSION_JP2000 = 34712
+COMPRESSION_LERC = 34887
+COMPRESSION_LZMA = 34925
+COMPRESSION_ZSTD = 50000
+COMPRESSION_WEBP = 50001
+COMPRESSION_JXL = 50002
+TIFFTAG_PHOTOMETRIC = 262
+PHOTOMETRIC_MINISWHITE = 0
+PHOTOMETRIC_MINISBLACK = 1
+PHOTOMETRIC_RGB = 2
+PHOTOMETRIC_PALETTE = 3
+PHOTOMETRIC_MASK = 4
+PHOTOMETRIC_SEPARATED = 5
+PHOTOMETRIC_YCBCR = 6
+PHOTOMETRIC_CIELAB = 8
+PHOTOMETRIC_ICCLAB = 9
+PHOTOMETRIC_ITULAB = 10
+PHOTOMETRIC_CFA = 32803
+PHOTOMETRIC_LOGL = 32844
+PHOTOMETRIC_LOGLUV = 32845
+TIFFTAG_THRESHHOLDING = 263
+THRESHHOLD_BILEVEL = 1
+THRESHHOLD_HALFTONE = 2
+THRESHHOLD_ERRORDIFFUSE = 3
+TIFFTAG_CELLWIDTH = 264
+TIFFTAG_CELLLENGTH = 265
+TIFFTAG_FILLORDER = 266
+FILLORDER_MSB2LSB = 1
+FILLORDER_LSB2MSB = 2
+TIFFTAG_DOCUMENTNAME = 269
+TIFFTAG_IMAGEDESCRIPTION = 270
+TIFFTAG_MAKE = 271
+TIFFTAG_MODEL = 272
+TIFFTAG_STRIPOFFSETS = 273
+TIFFTAG_ORIENTATION = 274
+ORIENTATION_TOPLEFT = 1
+ORIENTATION_TOPRIGHT = 2
+ORIENTATION_BOTRIGHT = 3
+ORIENTATION_BOTLEFT = 4
+ORIENTATION_LEFTTOP = 5
+ORIENTATION_RIGHTTOP = 6
+ORIENTATION_RIGHTBOT = 7
+ORIENTATION_LEFTBOT = 8
+TIFFTAG_SAMPLESPERPIXEL = 277
+TIFFTAG_ROWSPERSTRIP = 278
+TIFFTAG_STRIPBYTECOUNTS = 279
+TIFFTAG_MINSAMPLEVALUE = 280
+TIFFTAG_MAXSAMPLEVALUE = 281
+TIFFTAG_XRESOLUTION = 282
+TIFFTAG_YRESOLUTION = 283
+TIFFTAG_PLANARCONFIG = 284
+PLANARCONFIG_CONTIG = 1
+PLANARCONFIG_SEPARATE = 2
+TIFFTAG_PAGENAME = 285
+TIFFTAG_XPOSITION = 286
+TIFFTAG_YPOSITION = 287
+TIFFTAG_FREEOFFSETS = 288
+TIFFTAG_FREEBYTECOUNTS = 289
+TIFFTAG_GRAYRESPONSEUNIT = 290
+GRAYRESPONSEUNIT_10S = 1
+GRAYRESPONSEUNIT_100S = 2
+GRAYRESPONSEUNIT_1000S = 3
+GRAYRESPONSEUNIT_10000S = 4
+GRAYRESPONSEUNIT_100000S = 5
+TIFFTAG_GRAYRESPONSECURVE = 291
+TIFFTAG_GROUP3OPTIONS = 292
+TIFFTAG_T4OPTIONS = 292
+GROUP3OPT_2DENCODING = 1
+GROUP3OPT_UNCOMPRESSED = 2
+GROUP3OPT_FILLBITS = 4
+TIFFTAG_GROUP4OPTIONS = 293
+TIFFTAG_T6OPTIONS = 293
+GROUP4OPT_UNCOMPRESSED = 2
+TIFFTAG_RESOLUTIONUNIT = 296
+RESUNIT_NONE = 1
+RESUNIT_INCH = 2
+RESUNIT_CENTIMETER = 3
+TIFFTAG_PAGENUMBER = 297
+TIFFTAG_COLORRESPONSEUNIT = 300
+COLORRESPONSEUNIT_10S = 1
+COLORRESPONSEUNIT_100S = 2
+COLORRESPONSEUNIT_1000S = 3
+COLORRESPONSEUNIT_10000S = 4
+COLORRESPONSEUNIT_100000S = 5
+TIFFTAG_TRANSFERFUNCTION = 301
+TIFFTAG_SOFTWARE = 305
+TIFFTAG_DATETIME = 306
+TIFFTAG_ARTIST = 315
+TIFFTAG_HOSTCOMPUTER = 316
+TIFFTAG_PREDICTOR = 317
+PREDICTOR_NONE = 1
+PREDICTOR_HORIZONTAL = 2
+PREDICTOR_FLOATINGPOINT = 3
+TIFFTAG_WHITEPOINT = 318
+TIFFTAG_PRIMARYCHROMATICITIES = 319
+TIFFTAG_COLORMAP = 320
+TIFFTAG_HALFTONEHINTS = 321
+TIFFTAG_TILEWIDTH = 322
+TIFFTAG_TILELENGTH = 323
+TIFFTAG_TILEOFFSETS = 324
+TIFFTAG_TILEBYTECOUNTS = 325
+TIFFTAG_BADFAXLINES = 326
+TIFFTAG_CLEANFAXDATA = 327
+CLEANFAXDATA_CLEAN = 0
+CLEANFAXDATA_REGENERATED = 1
+CLEANFAXDATA_UNCLEAN = 2
+TIFFTAG_CONSECUTIVEBADFAXLINES = 328
+TIFFTAG_SUBIFD = 330
+TIFFTAG_INKSET = 332
+INKSET_CMYK = 1
+INKSET_MULTIINK = 2
+TIFFTAG_INKNAMES = 333
+TIFFTAG_NUMBEROFINKS = 334
+TIFFTAG_DOTRANGE = 336
+TIFFTAG_TARGETPRINTER = 337
+TIFFTAG_EXTRASAMPLES = 338
+EXTRASAMPLE_UNSPECIFIED = 0
+EXTRASAMPLE_ASSOCALPHA = 1
+EXTRASAMPLE_UNASSALPHA = 2
+TIFFTAG_SAMPLEFORMAT = 339
+SAMPLEFORMAT_UINT = 1
+SAMPLEFORMAT_INT = 2
+SAMPLEFORMAT_IEEEFP = 3
+SAMPLEFORMAT_VOID = 4
+SAMPLEFORMAT_COMPLEXINT = 5
+SAMPLEFORMAT_COMPLEXIEEEFP = 6
+TIFFTAG_SMINSAMPLEVALUE = 340
+TIFFTAG_SMAXSAMPLEVALUE = 341
+TIFFTAG_CLIPPATH = 343
+TIFFTAG_XCLIPPATHUNITS = 344
+TIFFTAG_YCLIPPATHUNITS = 345
+TIFFTAG_INDEXED = 346
+TIFFTAG_JPEGTABLES = 347
+TIFFTAG_OPIPROXY = 351
+TIFFTAG_GLOBALPARAMETERSIFD = 400
+TIFFTAG_PROFILETYPE = 401
+PROFILETYPE_UNSPECIFIED = 0
+PROFILETYPE_G3_FAX = 1
+TIFFTAG_FAXPROFILE = 402
+FAXPROFILE_S = 1
+FAXPROFILE_F = 2
+FAXPROFILE_J = 3
+FAXPROFILE_C = 4
+FAXPROFILE_L = 5
+FAXPROFILE_M = 6
+TIFFTAG_CODINGMETHODS = 403
+CODINGMETHODS_T4_1D = 2
+CODINGMETHODS_T4_2D = 4
+CODINGMETHODS_T6 = 8
+CODINGMETHODS_T85 = 16
+CODINGMETHODS_T42 = 32
+CODINGMETHODS_T43 = 64
+TIFFTAG_VERSIONYEAR = 404
+TIFFTAG_MODENUMBER = 405
+TIFFTAG_DECODE = 433
+TIFFTAG_IMAGEBASECOLOR = 434
+TIFFTAG_T82OPTIONS = 435
+TIFFTAG_JPEGPROC = 512
+JPEGPROC_BASELINE = 1
+JPEGPROC_LOSSLESS = 14
+TIFFTAG_JPEGIFOFFSET = 513
+TIFFTAG_JPEGIFBYTECOUNT = 514
+TIFFTAG_JPEGRESTARTINTERVAL = 515
+TIFFTAG_JPEGLOSSLESSPREDICTORS = 517
+TIFFTAG_JPEGPOINTTRANSFORM = 518
+TIFFTAG_JPEGQTABLES = 519
+TIFFTAG_JPEGDCTABLES = 520
+TIFFTAG_JPEGACTABLES = 521
+TIFFTAG_YCBCRCOEFFICIENTS = 529
+TIFFTAG_YCBCRSUBSAMPLING = 530
+TIFFTAG_YCBCRPOSITIONING = 531
+YCBCRPOSITION_CENTERED = 1
+YCBCRPOSITION_COSITED = 2
+TIFFTAG_REFERENCEBLACKWHITE = 532
+TIFFTAG_STRIPROWCOUNTS = 559
+TIFFTAG_XMLPACKET = 700
+TIFFTAG_OPIIMAGEID = 32781
+TIFFTAG_TIFFANNOTATIONDATA = 32932
+TIFFTAG_REFPTS = 32953
+TIFFTAG_REGIONTACKPOINT = 32954
+TIFFTAG_REGIONWARPCORNERS = 32955
+TIFFTAG_REGIONAFFINE = 32956
+TIFFTAG_MATTEING = 32995
+TIFFTAG_DATATYPE = 32996
+TIFFTAG_IMAGEDEPTH = 32997
+TIFFTAG_TILEDEPTH = 32998
+TIFFTAG_PIXAR_IMAGEFULLWIDTH = 33300
+TIFFTAG_PIXAR_IMAGEFULLLENGTH = 33301
+TIFFTAG_PIXAR_TEXTUREFORMAT = 33302
+TIFFTAG_PIXAR_WRAPMODES = 33303
+TIFFTAG_PIXAR_FOVCOT = 33304
+TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN = 33305
+TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA = 33306
+TIFFTAG_WRITERSERIALNUMBER = 33405
+TIFFTAG_CFAREPEATPATTERNDIM = 33421
+TIFFTAG_CFAPATTERN = 33422
+TIFFTAG_BATTERYLEVEL = 33423
+TIFFTAG_COPYRIGHT = 33432
+TIFFTAG_MD_FILETAG = 33445
+TIFFTAG_MD_SCALEPIXEL = 33446
+TIFFTAG_MD_COLORTABLE = 33447
+TIFFTAG_MD_LABNAME = 33448
+TIFFTAG_MD_SAMPLEINFO = 33449
+TIFFTAG_MD_PREPDATE = 33450
+TIFFTAG_MD_PREPTIME = 33451
+TIFFTAG_MD_FILEUNITS = 33452
+TIFFTAG_RICHTIFFIPTC = 33723
+TIFFTAG_INGR_PACKET_DATA_TAG = 33918
+TIFFTAG_INGR_FLAG_REGISTERS = 33919
+TIFFTAG_IRASB_TRANSORMATION_MATRIX = 33920
+TIFFTAG_MODELTIEPOINTTAG = 33922
+TIFFTAG_IT8SITE = 34016
+TIFFTAG_IT8COLORSEQUENCE = 34017
+TIFFTAG_IT8HEADER = 34018
+TIFFTAG_IT8RASTERPADDING = 34019
+TIFFTAG_IT8BITSPERRUNLENGTH = 34020
+TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH = 34021
+TIFFTAG_IT8COLORTABLE = 34022
+TIFFTAG_IT8IMAGECOLORINDICATOR = 34023
+TIFFTAG_IT8BKGCOLORINDICATOR = 34024
+TIFFTAG_IT8IMAGECOLORVALUE = 34025
+TIFFTAG_IT8BKGCOLORVALUE = 34026
+TIFFTAG_IT8PIXELINTENSITYRANGE = 34027
+TIFFTAG_IT8TRANSPARENCYINDICATOR = 34028
+TIFFTAG_IT8COLORCHARACTERIZATION = 34029
+TIFFTAG_IT8HCUSAGE = 34030
+TIFFTAG_IT8TRAPINDICATOR = 34031
+TIFFTAG_IT8CMYKEQUIVALENT = 34032
+TIFFTAG_FRAMECOUNT = 34232
+TIFFTAG_MODELTRANSFORMATIONTAG = 34264
+TIFFTAG_PHOTOSHOP = 34377
+TIFFTAG_EXIFIFD = 34665
+TIFFTAG_ICCPROFILE = 34675
+TIFFTAG_IMAGELAYER = 34732
+TIFFTAG_JBIGOPTIONS = 34750
+TIFFTAG_GPSIFD = 34853
+TIFFTAG_FAXRECVPARAMS = 34908
+TIFFTAG_FAXSUBADDRESS = 34909
+TIFFTAG_FAXRECVTIME = 34910
+TIFFTAG_FAXDCS = 34911
+TIFFTAG_STONITS = 37439
+TIFFTAG_FEDEX_EDR = 34929
+TIFFTAG_IMAGESOURCEDATA = 37724
+TIFFTAG_INTEROPERABILITYIFD = 40965
+TIFFTAG_GDAL_METADATA = 42112
+TIFFTAG_GDAL_NODATA = 42113
+TIFFTAG_OCE_SCANJOB_DESCRIPTION = 50215
+TIFFTAG_OCE_APPLICATION_SELECTOR = 50216
+TIFFTAG_OCE_IDENTIFICATION_NUMBER = 50217
+TIFFTAG_OCE_IMAGELOGIC_CHARACTERISTICS = 50218
+TIFFTAG_LERC_PARAMETERS = 50674
+TIFFTAG_DNGVERSION = 50706
+TIFFTAG_DNGBACKWARDVERSION = 50707
+TIFFTAG_UNIQUECAMERAMODEL = 50708
+TIFFTAG_LOCALIZEDCAMERAMODEL = 50709
+TIFFTAG_CFAPLANECOLOR = 50710
+TIFFTAG_CFALAYOUT = 50711
+TIFFTAG_LINEARIZATIONTABLE = 50712
+TIFFTAG_BLACKLEVELREPEATDIM = 50713
+TIFFTAG_BLACKLEVEL = 50714
+TIFFTAG_BLACKLEVELDELTAH = 50715
+TIFFTAG_BLACKLEVELDELTAV = 50716
+TIFFTAG_WHITELEVEL = 50717
+TIFFTAG_DEFAULTSCALE = 50718
+TIFFTAG_DEFAULTCROPORIGIN = 50719
+TIFFTAG_DEFAULTCROPSIZE = 50720
+TIFFTAG_COLORMATRIX1 = 50721
+TIFFTAG_COLORMATRIX2 = 50722
+TIFFTAG_CAMERACALIBRATION1 = 50723
+TIFFTAG_CAMERACALIBRATION2 = 50724
+TIFFTAG_REDUCTIONMATRIX1 = 50725
+TIFFTAG_REDUCTIONMATRIX2 = 50726
+TIFFTAG_ANALOGBALANCE = 50727
+TIFFTAG_ASSHOTNEUTRAL = 50728
+TIFFTAG_ASSHOTWHITEXY = 50729
+TIFFTAG_BASELINEEXPOSURE = 50730
+TIFFTAG_BASELINENOISE = 50731
+TIFFTAG_BASELINESHARPNESS = 50732
+TIFFTAG_BAYERGREENSPLIT = 50733
+TIFFTAG_LINEARRESPONSELIMIT = 50734
+TIFFTAG_CAMERASERIALNUMBER = 50735
+TIFFTAG_LENSINFO = 50736
+TIFFTAG_CHROMABLURRADIUS = 50737
+TIFFTAG_ANTIALIASSTRENGTH = 50738
+TIFFTAG_SHADOWSCALE = 50739
+TIFFTAG_DNGPRIVATEDATA = 50740
+TIFFTAG_MAKERNOTESAFETY = 50741
+TIFFTAG_CALIBRATIONILLUMINANT1 = 50778
+TIFFTAG_CALIBRATIONILLUMINANT2 = 50779
+TIFFTAG_BESTQUALITYSCALE = 50780
+TIFFTAG_RAWDATAUNIQUEID = 50781
+TIFFTAG_ORIGINALRAWFILENAME = 50827
+TIFFTAG_ORIGINALRAWFILEDATA = 50828
+TIFFTAG_ACTIVEAREA = 50829
+TIFFTAG_MASKEDAREAS = 50830
+TIFFTAG_ASSHOTICCPROFILE = 50831
+TIFFTAG_ASSHOTPREPROFILEMATRIX = 50832
+TIFFTAG_CURRENTICCPROFILE = 50833
+TIFFTAG_CURRENTPREPROFILEMATRIX = 50834
+TIFFTAG_COLORIMETRICREFERENCE = 50879
+TIFFTAG_CAMERACALIBRATIONSIGNATURE = 50931
+TIFFTAG_PROFILECALIBRATIONSIGNATURE = 50932
+TIFFTAG_ASSHOTPROFILENAME = 50934
+TIFFTAG_NOISEREDUCTIONAPPLIED = 50935
+TIFFTAG_PROFILENAME = 50936
+TIFFTAG_PROFILEHUESATMAPDIMS = 50937
+TIFFTAG_PROFILEHUESATMAPDATA1 = 50938
+TIFFTAG_PROFILEHUESATMAPDATA2 = 50939
+TIFFTAG_PROFILETONECURVE = 50940
+TIFFTAG_PROFILEEMBEDPOLICY = 50941
+TIFFTAG_PROFILECOPYRIGHT = 50942
+TIFFTAG_FORWARDMATRIX1 = 50964
+TIFFTAG_FORWARDMATRIX2 = 50965
+TIFFTAG_PREVIEWAPPLICATIONNAME = 50966
+TIFFTAG_PREVIEWAPPLICATIONVERSION = 50967
+TIFFTAG_PREVIEWSETTINGSNAME = 50968
+TIFFTAG_PREVIEWSETTINGSDIGEST = 50969
+TIFFTAG_PREVIEWCOLORSPACE = 50970
+TIFFTAG_PREVIEWDATETIME = 50971
+TIFFTAG_RAWIMAGEDIGEST = 50972
+TIFFTAG_ORIGINALRAWFILEDIGEST = 50973
+TIFFTAG_SUBTILEBLOCKSIZE = 50974
+TIFFTAG_ROWINTERLEAVEFACTOR = 50975
+TIFFTAG_PROFILELOOKTABLEDIMS = 50981
+TIFFTAG_PROFILELOOKTABLEDATA = 50982
+TIFFTAG_OPCODELIST1 = 51008
+TIFFTAG_OPCODELIST2 = 51009
+TIFFTAG_OPCODELIST3 = 51022
+TIFFTAG_NOISEPROFILE = 51041
+TIFFTAG_DEFAULTUSERCROP = 51125
+TIFFTAG_DEFAULTBLACKRENDER = 51110
+TIFFTAG_BASELINEEXPOSUREOFFSET = 51109
+TIFFTAG_PROFILELOOKTABLEENCODING = 51108
+TIFFTAG_PROFILEHUESATMAPENCODING = 51107
+TIFFTAG_ORIGINALDEFAULTFINALSIZE = 51089
+TIFFTAG_ORIGINALBESTQUALITYFINALSIZE = 51090
+TIFFTAG_ORIGINALDEFAULTCROPSIZE = 51091
+TIFFTAG_NEWRAWIMAGEDIGEST = 51111
+TIFFTAG_RAWTOPREVIEWGAIN = 51112
+TIFFTAG_DEPTHFORMAT = 51177
+TIFFTAG_DEPTHNEAR = 51178
+TIFFTAG_DEPTHFAR = 51179
+TIFFTAG_DEPTHUNITS = 51180
+TIFFTAG_DEPTHMEASURETYPE = 51181
+TIFFTAG_ENHANCEPARAMS = 51182
+TIFFTAG_PROFILEGAINTABLEMAP = 52525
+TIFFTAG_SEMANTICNAME = 52526
+TIFFTAG_SEMANTICINSTANCEID = 52528
+TIFFTAG_MASKSUBAREA = 52536
+TIFFTAG_RGBTABLES = 52543
+TIFFTAG_CALIBRATIONILLUMINANT3 = 52529
+TIFFTAG_COLORMATRIX3 = 52531
+TIFFTAG_CAMERACALIBRATION3 = 52530
+TIFFTAG_REDUCTIONMATRIX3 = 52538
+TIFFTAG_PROFILEHUESATMAPDATA3 = 52537
+TIFFTAG_FORWARDMATRIX3 = 52532
+TIFFTAG_ILLUMINANTDATA1 = 52533
+TIFFTAG_ILLUMINANTDATA2 = 52534
+TIFFTAG_ILLUMINANTDATA3 = 53535
+TIFFTAG_EP_CFAREPEATPATTERNDIM = 33421
+TIFFTAG_EP_CFAPATTERN = 33422
+TIFFTAG_EP_BATTERYLEVEL = 33423
+TIFFTAG_EP_INTERLACE = 34857
+TIFFTAG_EP_IPTC_NAA = 33723
+TIFFTAG_EP_TIMEZONEOFFSET = 34858
+TIFFTAG_EP_SELFTIMERMODE = 34859
+TIFFTAG_EP_FLASHENERGY = 37387
+TIFFTAG_EP_SPATIALFREQUENCYRESPONSE = 37388
+TIFFTAG_EP_NOISE = 37389
+TIFFTAG_EP_FOCALPLANEXRESOLUTION = 37390
+TIFFTAG_EP_FOCALPLANEYRESOLUTION = 37391
+TIFFTAG_EP_FOCALPLANERESOLUTIONUNIT = 37392
+TIFFTAG_EP_IMAGENUMBER = 37393
+TIFFTAG_EP_SECURITYCLASSIFICATION = 37394
+TIFFTAG_EP_IMAGEHISTORY = 37395
+TIFFTAG_EP_EXPOSUREINDEX = 37397
+TIFFTAG_EP_STANDARDID = 37398
+TIFFTAG_EP_SENSINGMETHOD = 37399
+TIFFTAG_EP_EXPOSURETIME = 33434
+TIFFTAG_EP_FNUMBER = 33437
+TIFFTAG_EP_EXPOSUREPROGRAM = 34850
+TIFFTAG_EP_SPECTRALSENSITIVITY = 34852
+TIFFTAG_EP_ISOSPEEDRATINGS = 34855
+TIFFTAG_EP_OECF = 34856
+TIFFTAG_EP_DATETIMEORIGINAL = 36867
+TIFFTAG_EP_COMPRESSEDBITSPERPIXEL = 37122
+TIFFTAG_EP_SHUTTERSPEEDVALUE = 37377
+TIFFTAG_EP_APERTUREVALUE = 37378
+TIFFTAG_EP_BRIGHTNESSVALUE = 37379
+TIFFTAG_EP_EXPOSUREBIASVALUE = 37380
+TIFFTAG_EP_MAXAPERTUREVALUE = 37381
+TIFFTAG_EP_SUBJECTDISTANCE = 37382
+TIFFTAG_EP_METERINGMODE = 37383
+TIFFTAG_EP_LIGHTSOURCE = 37384
+TIFFTAG_EP_FLASH = 37385
+TIFFTAG_EP_FOCALLENGTH = 37386
+TIFFTAG_EP_SUBJECTLOCATION = 37396
+TIFFTAG_RPCCOEFFICIENT = 50844
+TIFFTAG_ALIAS_LAYER_METADATA = 50784
+TIFFTAG_TIFF_RSID = 50908
+TIFFTAG_GEO_METADATA = 50909
+TIFFTAG_EXTRACAMERAPROFILES = 50933
+TIFFTAG_DCSHUESHIFTVALUES = 65535
+TIFFTAG_FAXMODE = 65536
+FAXMODE_CLASSIC = 0
+FAXMODE_NORTC = 1
+FAXMODE_NOEOL = 2
+FAXMODE_BYTEALIGN = 4
+FAXMODE_WORDALIGN = 8
+FAXMODE_CLASSF = 1
+TIFFTAG_JPEGQUALITY = 65537
+TIFFTAG_JPEGCOLORMODE = 65538
+JPEGCOLORMODE_RAW = 0
+JPEGCOLORMODE_RGB = 1
+TIFFTAG_JPEGTABLESMODE = 65539
+JPEGTABLESMODE_QUANT = 1
+JPEGTABLESMODE_HUFF = 2
+TIFFTAG_FAXFILLFUNC = 65540
+TIFFTAG_PIXARLOGDATAFMT = 65549
+PIXARLOGDATAFMT_8BIT = 0
+PIXARLOGDATAFMT_8BITABGR = 1
+PIXARLOGDATAFMT_11BITLOG = 2
+PIXARLOGDATAFMT_12BITPICIO = 3
+PIXARLOGDATAFMT_16BIT = 4
+PIXARLOGDATAFMT_FLOAT = 5
+TIFFTAG_DCSIMAGERTYPE = 65550
+DCSIMAGERMODEL_M3 = 0
+DCSIMAGERMODEL_M5 = 1
+DCSIMAGERMODEL_M6 = 2
+DCSIMAGERFILTER_IR = 0
+DCSIMAGERFILTER_MONO = 1
+DCSIMAGERFILTER_CFA = 2
+DCSIMAGERFILTER_OTHER = 3
+TIFFTAG_DCSINTERPMODE = 65551
+DCSINTERPMODE_NORMAL = 0
+DCSINTERPMODE_PREVIEW = 1
+TIFFTAG_DCSBALANCEARRAY = 65552
+TIFFTAG_DCSCORRECTMATRIX = 65553
+TIFFTAG_DCSGAMMA = 65554
+TIFFTAG_DCSTOESHOULDERPTS = 65555
+TIFFTAG_DCSCALIBRATIONFD = 65556
+TIFFTAG_ZIPQUALITY = 65557
+TIFFTAG_PIXARLOGQUALITY = 65558
+TIFFTAG_DCSCLIPRECTANGLE = 65559
+TIFFTAG_SGILOGDATAFMT = 65560
+SGILOGDATAFMT_FLOAT = 0
+SGILOGDATAFMT_16BIT = 1
+SGILOGDATAFMT_RAW = 2
+SGILOGDATAFMT_8BIT = 3
+TIFFTAG_SGILOGENCODE = 65561
+SGILOGENCODE_NODITHER = 0
+SGILOGENCODE_RANDITHER = 1
+TIFFTAG_LZMAPRESET = 65562
+TIFFTAG_PERSAMPLE = 65563
+PERSAMPLE_MERGED = 0
+PERSAMPLE_MULTI = 1
+TIFFTAG_ZSTD_LEVEL = 65564
+TIFFTAG_LERC_VERSION = 65565
+LERC_VERSION_2_4 = 4
+TIFFTAG_LERC_ADD_COMPRESSION = 65566
+LERC_ADD_COMPRESSION_NONE = 0
+LERC_ADD_COMPRESSION_DEFLATE = 1
+LERC_ADD_COMPRESSION_ZSTD = 2
+TIFFTAG_LERC_MAXZERROR = 65567
+TIFFTAG_WEBP_LEVEL = 65568
+TIFFTAG_WEBP_LOSSLESS = 65569
+TIFFTAG_WEBP_LOSSLESS_EXACT = 65571
+TIFFTAG_DEFLATE_SUBCODEC = 65570
+DEFLATE_SUBCODEC_ZLIB = 0
+DEFLATE_SUBCODEC_LIBDEFLATE = 1
+EXIFTAG_EXPOSURETIME = 33434
+EXIFTAG_FNUMBER = 33437
+EXIFTAG_EXPOSUREPROGRAM = 34850
+EXIFTAG_SPECTRALSENSITIVITY = 34852
+EXIFTAG_ISOSPEEDRATINGS = 34855
+EXIFTAG_PHOTOGRAPHICSENSITIVITY = 34855
+EXIFTAG_OECF = 34856
+EXIFTAG_EXIFVERSION = 36864
+EXIFTAG_DATETIMEORIGINAL = 36867
+EXIFTAG_DATETIMEDIGITIZED = 36868
+EXIFTAG_COMPONENTSCONFIGURATION = 37121
+EXIFTAG_COMPRESSEDBITSPERPIXEL = 37122
+EXIFTAG_SHUTTERSPEEDVALUE = 37377
+EXIFTAG_APERTUREVALUE = 37378
+EXIFTAG_BRIGHTNESSVALUE = 37379
+EXIFTAG_EXPOSUREBIASVALUE = 37380
+EXIFTAG_MAXAPERTUREVALUE = 37381
+EXIFTAG_SUBJECTDISTANCE = 37382
+EXIFTAG_METERINGMODE = 37383
+EXIFTAG_LIGHTSOURCE = 37384
+EXIFTAG_FLASH = 37385
+EXIFTAG_FOCALLENGTH = 37386
+EXIFTAG_SUBJECTAREA = 37396
+EXIFTAG_MAKERNOTE = 37500
+EXIFTAG_USERCOMMENT = 37510
+EXIFTAG_SUBSECTIME = 37520
+EXIFTAG_SUBSECTIMEORIGINAL = 37521
+EXIFTAG_SUBSECTIMEDIGITIZED = 37522
+EXIFTAG_FLASHPIXVERSION = 40960
+EXIFTAG_COLORSPACE = 40961
+EXIFTAG_PIXELXDIMENSION = 40962
+EXIFTAG_PIXELYDIMENSION = 40963
+EXIFTAG_RELATEDSOUNDFILE = 40964
+EXIFTAG_FLASHENERGY = 41483
+EXIFTAG_SPATIALFREQUENCYRESPONSE = 41484
+EXIFTAG_FOCALPLANEXRESOLUTION = 41486
+EXIFTAG_FOCALPLANEYRESOLUTION = 41487
+EXIFTAG_FOCALPLANERESOLUTIONUNIT = 41488
+EXIFTAG_SUBJECTLOCATION = 41492
+EXIFTAG_EXPOSUREINDEX = 41493
+EXIFTAG_SENSINGMETHOD = 41495
+EXIFTAG_FILESOURCE = 41728
+EXIFTAG_SCENETYPE = 41729
+EXIFTAG_CFAPATTERN = 41730
+EXIFTAG_CUSTOMRENDERED = 41985
+EXIFTAG_EXPOSUREMODE = 41986
+EXIFTAG_WHITEBALANCE = 41987
+EXIFTAG_DIGITALZOOMRATIO = 41988
+EXIFTAG_FOCALLENGTHIN35MMFILM = 41989
+EXIFTAG_SCENECAPTURETYPE = 41990
+EXIFTAG_GAINCONTROL = 41991
+EXIFTAG_CONTRAST = 41992
+EXIFTAG_SATURATION = 41993
+EXIFTAG_SHARPNESS = 41994
+EXIFTAG_DEVICESETTINGDESCRIPTION = 41995
+EXIFTAG_SUBJECTDISTANCERANGE = 41996
+EXIFTAG_IMAGEUNIQUEID = 42016
+EXIFTAG_SENSITIVITYTYPE = 34864
+EXIFTAG_STANDARDOUTPUTSENSITIVITY = 34865
+EXIFTAG_RECOMMENDEDEXPOSUREINDEX = 34866
+EXIFTAG_ISOSPEED = 34867
+EXIFTAG_ISOSPEEDLATITUDEYYY = 34868
+EXIFTAG_ISOSPEEDLATITUDEZZZ = 34869
+EXIFTAG_OFFSETTIME = 36880
+EXIFTAG_OFFSETTIMEORIGINAL = 36881
+EXIFTAG_OFFSETTIMEDIGITIZED = 36882
+EXIFTAG_TEMPERATURE = 37888
+EXIFTAG_HUMIDITY = 37889
+EXIFTAG_PRESSURE = 37890
+EXIFTAG_WATERDEPTH = 37891
+EXIFTAG_ACCELERATION = 37892
+EXIFTAG_CAMERAELEVATIONANGLE = 37893
+EXIFTAG_CAMERAOWNERNAME = 42032
+EXIFTAG_BODYSERIALNUMBER = 42033
+EXIFTAG_LENSSPECIFICATION = 42034
+EXIFTAG_LENSMAKE = 42035
+EXIFTAG_LENSMODEL = 42036
+EXIFTAG_LENSSERIALNUMBER = 42037
+EXIFTAG_GAMMA = 42240
+EXIFTAG_COMPOSITEIMAGE = 42080
+EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE = 42081
+EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE = 42082
+GPSTAG_VERSIONID = 0
+GPSTAG_LATITUDEREF = 1
+GPSTAG_LATITUDE = 2
+GPSTAG_LONGITUDEREF = 3
+GPSTAG_LONGITUDE = 4
+GPSTAG_ALTITUDEREF = 5
+GPSTAG_ALTITUDE = 6
+GPSTAG_TIMESTAMP = 7
+GPSTAG_SATELLITES = 8
+GPSTAG_STATUS = 9
+GPSTAG_MEASUREMODE = 10
+GPSTAG_DOP = 11
+GPSTAG_SPEEDREF = 12
+GPSTAG_SPEED = 13
+GPSTAG_TRACKREF = 14
+GPSTAG_TRACK = 15
+GPSTAG_IMGDIRECTIONREF = 16
+GPSTAG_IMGDIRECTION = 17
+GPSTAG_MAPDATUM = 18
+GPSTAG_DESTLATITUDEREF = 19
+GPSTAG_DESTLATITUDE = 20
+GPSTAG_DESTLONGITUDEREF = 21
+GPSTAG_DESTLONGITUDE = 22
+GPSTAG_DESTBEARINGREF = 23
+GPSTAG_DESTBEARING = 24
+GPSTAG_DESTDISTANCEREF = 25
+GPSTAG_DESTDISTANCE = 26
+GPSTAG_PROCESSINGMETHOD = 27
+GPSTAG_AREAINFORMATION = 28
+GPSTAG_DATESTAMP = 29
+GPSTAG_DIFFERENTIAL = 30
+GPSTAG_GPSHPOSITIONINGERROR = 31


=====================================
libtiff/tiff_h_4_7_0.py
=====================================
@@ -0,0 +1,629 @@
+TIFF_VERSION_CLASSIC = 42
+TIFF_VERSION_BIG = 43
+TIFF_BIGENDIAN = 19789
+TIFF_LITTLEENDIAN = 18761
+MDI_LITTLEENDIAN = 20549
+MDI_BIGENDIAN = 17744
+TIFFTAG_SUBFILETYPE = 254
+FILETYPE_REDUCEDIMAGE = 1
+FILETYPE_PAGE = 2
+FILETYPE_MASK = 4
+TIFFTAG_OSUBFILETYPE = 255
+OFILETYPE_IMAGE = 1
+OFILETYPE_REDUCEDIMAGE = 2
+OFILETYPE_PAGE = 3
+TIFFTAG_IMAGEWIDTH = 256
+TIFFTAG_IMAGELENGTH = 257
+TIFFTAG_BITSPERSAMPLE = 258
+TIFFTAG_COMPRESSION = 259
+COMPRESSION_NONE = 1
+COMPRESSION_CCITTRLE = 2
+COMPRESSION_CCITTFAX3 = 3
+COMPRESSION_CCITT_T4 = 3
+COMPRESSION_CCITTFAX4 = 4
+COMPRESSION_CCITT_T6 = 4
+COMPRESSION_LZW = 5
+COMPRESSION_OJPEG = 6
+COMPRESSION_JPEG = 7
+COMPRESSION_T85 = 9
+COMPRESSION_T43 = 10
+COMPRESSION_NEXT = 32766
+COMPRESSION_CCITTRLEW = 32771
+COMPRESSION_PACKBITS = 32773
+COMPRESSION_THUNDERSCAN = 32809
+COMPRESSION_IT8CTPAD = 32895
+COMPRESSION_IT8LW = 32896
+COMPRESSION_IT8MP = 32897
+COMPRESSION_IT8BL = 32898
+COMPRESSION_PIXARFILM = 32908
+COMPRESSION_PIXARLOG = 32909
+COMPRESSION_DEFLATE = 32946
+COMPRESSION_ADOBE_DEFLATE = 8
+COMPRESSION_DCS = 32947
+COMPRESSION_JBIG = 34661
+COMPRESSION_SGILOG = 34676
+COMPRESSION_SGILOG24 = 34677
+COMPRESSION_JP2000 = 34712
+COMPRESSION_LERC = 34887
+COMPRESSION_LZMA = 34925
+COMPRESSION_ZSTD = 50000
+COMPRESSION_WEBP = 50001
+COMPRESSION_JXL = 50002
+TIFFTAG_PHOTOMETRIC = 262
+PHOTOMETRIC_MINISWHITE = 0
+PHOTOMETRIC_MINISBLACK = 1
+PHOTOMETRIC_RGB = 2
+PHOTOMETRIC_PALETTE = 3
+PHOTOMETRIC_MASK = 4
+PHOTOMETRIC_SEPARATED = 5
+PHOTOMETRIC_YCBCR = 6
+PHOTOMETRIC_CIELAB = 8
+PHOTOMETRIC_ICCLAB = 9
+PHOTOMETRIC_ITULAB = 10
+PHOTOMETRIC_CFA = 32803
+PHOTOMETRIC_LOGL = 32844
+PHOTOMETRIC_LOGLUV = 32845
+TIFFTAG_THRESHHOLDING = 263
+THRESHHOLD_BILEVEL = 1
+THRESHHOLD_HALFTONE = 2
+THRESHHOLD_ERRORDIFFUSE = 3
+TIFFTAG_CELLWIDTH = 264
+TIFFTAG_CELLLENGTH = 265
+TIFFTAG_FILLORDER = 266
+FILLORDER_MSB2LSB = 1
+FILLORDER_LSB2MSB = 2
+TIFFTAG_DOCUMENTNAME = 269
+TIFFTAG_IMAGEDESCRIPTION = 270
+TIFFTAG_MAKE = 271
+TIFFTAG_MODEL = 272
+TIFFTAG_STRIPOFFSETS = 273
+TIFFTAG_ORIENTATION = 274
+ORIENTATION_TOPLEFT = 1
+ORIENTATION_TOPRIGHT = 2
+ORIENTATION_BOTRIGHT = 3
+ORIENTATION_BOTLEFT = 4
+ORIENTATION_LEFTTOP = 5
+ORIENTATION_RIGHTTOP = 6
+ORIENTATION_RIGHTBOT = 7
+ORIENTATION_LEFTBOT = 8
+TIFFTAG_SAMPLESPERPIXEL = 277
+TIFFTAG_ROWSPERSTRIP = 278
+TIFFTAG_STRIPBYTECOUNTS = 279
+TIFFTAG_MINSAMPLEVALUE = 280
+TIFFTAG_MAXSAMPLEVALUE = 281
+TIFFTAG_XRESOLUTION = 282
+TIFFTAG_YRESOLUTION = 283
+TIFFTAG_PLANARCONFIG = 284
+PLANARCONFIG_CONTIG = 1
+PLANARCONFIG_SEPARATE = 2
+TIFFTAG_PAGENAME = 285
+TIFFTAG_XPOSITION = 286
+TIFFTAG_YPOSITION = 287
+TIFFTAG_FREEOFFSETS = 288
+TIFFTAG_FREEBYTECOUNTS = 289
+TIFFTAG_GRAYRESPONSEUNIT = 290
+GRAYRESPONSEUNIT_10S = 1
+GRAYRESPONSEUNIT_100S = 2
+GRAYRESPONSEUNIT_1000S = 3
+GRAYRESPONSEUNIT_10000S = 4
+GRAYRESPONSEUNIT_100000S = 5
+TIFFTAG_GRAYRESPONSECURVE = 291
+TIFFTAG_GROUP3OPTIONS = 292
+TIFFTAG_T4OPTIONS = 292
+GROUP3OPT_2DENCODING = 1
+GROUP3OPT_UNCOMPRESSED = 2
+GROUP3OPT_FILLBITS = 4
+TIFFTAG_GROUP4OPTIONS = 293
+TIFFTAG_T6OPTIONS = 293
+GROUP4OPT_UNCOMPRESSED = 2
+TIFFTAG_RESOLUTIONUNIT = 296
+RESUNIT_NONE = 1
+RESUNIT_INCH = 2
+RESUNIT_CENTIMETER = 3
+TIFFTAG_PAGENUMBER = 297
+TIFFTAG_COLORRESPONSEUNIT = 300
+COLORRESPONSEUNIT_10S = 1
+COLORRESPONSEUNIT_100S = 2
+COLORRESPONSEUNIT_1000S = 3
+COLORRESPONSEUNIT_10000S = 4
+COLORRESPONSEUNIT_100000S = 5
+TIFFTAG_TRANSFERFUNCTION = 301
+TIFFTAG_SOFTWARE = 305
+TIFFTAG_DATETIME = 306
+TIFFTAG_ARTIST = 315
+TIFFTAG_HOSTCOMPUTER = 316
+TIFFTAG_PREDICTOR = 317
+PREDICTOR_NONE = 1
+PREDICTOR_HORIZONTAL = 2
+PREDICTOR_FLOATINGPOINT = 3
+TIFFTAG_WHITEPOINT = 318
+TIFFTAG_PRIMARYCHROMATICITIES = 319
+TIFFTAG_COLORMAP = 320
+TIFFTAG_HALFTONEHINTS = 321
+TIFFTAG_TILEWIDTH = 322
+TIFFTAG_TILELENGTH = 323
+TIFFTAG_TILEOFFSETS = 324
+TIFFTAG_TILEBYTECOUNTS = 325
+TIFFTAG_BADFAXLINES = 326
+TIFFTAG_CLEANFAXDATA = 327
+CLEANFAXDATA_CLEAN = 0
+CLEANFAXDATA_REGENERATED = 1
+CLEANFAXDATA_UNCLEAN = 2
+TIFFTAG_CONSECUTIVEBADFAXLINES = 328
+TIFFTAG_SUBIFD = 330
+TIFFTAG_INKSET = 332
+INKSET_CMYK = 1
+INKSET_MULTIINK = 2
+TIFFTAG_INKNAMES = 333
+TIFFTAG_NUMBEROFINKS = 334
+TIFFTAG_DOTRANGE = 336
+TIFFTAG_TARGETPRINTER = 337
+TIFFTAG_EXTRASAMPLES = 338
+EXTRASAMPLE_UNSPECIFIED = 0
+EXTRASAMPLE_ASSOCALPHA = 1
+EXTRASAMPLE_UNASSALPHA = 2
+TIFFTAG_SAMPLEFORMAT = 339
+SAMPLEFORMAT_UINT = 1
+SAMPLEFORMAT_INT = 2
+SAMPLEFORMAT_IEEEFP = 3
+SAMPLEFORMAT_VOID = 4
+SAMPLEFORMAT_COMPLEXINT = 5
+SAMPLEFORMAT_COMPLEXIEEEFP = 6
+TIFFTAG_SMINSAMPLEVALUE = 340
+TIFFTAG_SMAXSAMPLEVALUE = 341
+TIFFTAG_CLIPPATH = 343
+TIFFTAG_XCLIPPATHUNITS = 344
+TIFFTAG_YCLIPPATHUNITS = 345
+TIFFTAG_INDEXED = 346
+TIFFTAG_JPEGTABLES = 347
+TIFFTAG_OPIPROXY = 351
+TIFFTAG_GLOBALPARAMETERSIFD = 400
+TIFFTAG_PROFILETYPE = 401
+PROFILETYPE_UNSPECIFIED = 0
+PROFILETYPE_G3_FAX = 1
+TIFFTAG_FAXPROFILE = 402
+FAXPROFILE_S = 1
+FAXPROFILE_F = 2
+FAXPROFILE_J = 3
+FAXPROFILE_C = 4
+FAXPROFILE_L = 5
+FAXPROFILE_M = 6
+TIFFTAG_CODINGMETHODS = 403
+CODINGMETHODS_T4_1D = 2
+CODINGMETHODS_T4_2D = 4
+CODINGMETHODS_T6 = 8
+CODINGMETHODS_T85 = 16
+CODINGMETHODS_T42 = 32
+CODINGMETHODS_T43 = 64
+TIFFTAG_VERSIONYEAR = 404
+TIFFTAG_MODENUMBER = 405
+TIFFTAG_DECODE = 433
+TIFFTAG_IMAGEBASECOLOR = 434
+TIFFTAG_T82OPTIONS = 435
+TIFFTAG_JPEGPROC = 512
+JPEGPROC_BASELINE = 1
+JPEGPROC_LOSSLESS = 14
+TIFFTAG_JPEGIFOFFSET = 513
+TIFFTAG_JPEGIFBYTECOUNT = 514
+TIFFTAG_JPEGRESTARTINTERVAL = 515
+TIFFTAG_JPEGLOSSLESSPREDICTORS = 517
+TIFFTAG_JPEGPOINTTRANSFORM = 518
+TIFFTAG_JPEGQTABLES = 519
+TIFFTAG_JPEGDCTABLES = 520
+TIFFTAG_JPEGACTABLES = 521
+TIFFTAG_YCBCRCOEFFICIENTS = 529
+TIFFTAG_YCBCRSUBSAMPLING = 530
+TIFFTAG_YCBCRPOSITIONING = 531
+YCBCRPOSITION_CENTERED = 1
+YCBCRPOSITION_COSITED = 2
+TIFFTAG_REFERENCEBLACKWHITE = 532
+TIFFTAG_STRIPROWCOUNTS = 559
+TIFFTAG_XMLPACKET = 700
+TIFFTAG_OPIIMAGEID = 32781
+TIFFTAG_TIFFANNOTATIONDATA = 32932
+TIFFTAG_REFPTS = 32953
+TIFFTAG_REGIONTACKPOINT = 32954
+TIFFTAG_REGIONWARPCORNERS = 32955
+TIFFTAG_REGIONAFFINE = 32956
+TIFFTAG_MATTEING = 32995
+TIFFTAG_DATATYPE = 32996
+TIFFTAG_IMAGEDEPTH = 32997
+TIFFTAG_TILEDEPTH = 32998
+TIFFTAG_PIXAR_IMAGEFULLWIDTH = 33300
+TIFFTAG_PIXAR_IMAGEFULLLENGTH = 33301
+TIFFTAG_PIXAR_TEXTUREFORMAT = 33302
+TIFFTAG_PIXAR_WRAPMODES = 33303
+TIFFTAG_PIXAR_FOVCOT = 33304
+TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN = 33305
+TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA = 33306
+TIFFTAG_WRITERSERIALNUMBER = 33405
+TIFFTAG_CFAREPEATPATTERNDIM = 33421
+TIFFTAG_CFAPATTERN = 33422
+TIFFTAG_BATTERYLEVEL = 33423
+TIFFTAG_COPYRIGHT = 33432
+TIFFTAG_MD_FILETAG = 33445
+TIFFTAG_MD_SCALEPIXEL = 33446
+TIFFTAG_MD_COLORTABLE = 33447
+TIFFTAG_MD_LABNAME = 33448
+TIFFTAG_MD_SAMPLEINFO = 33449
+TIFFTAG_MD_PREPDATE = 33450
+TIFFTAG_MD_PREPTIME = 33451
+TIFFTAG_MD_FILEUNITS = 33452
+TIFFTAG_RICHTIFFIPTC = 33723
+TIFFTAG_INGR_PACKET_DATA_TAG = 33918
+TIFFTAG_INGR_FLAG_REGISTERS = 33919
+TIFFTAG_IRASB_TRANSORMATION_MATRIX = 33920
+TIFFTAG_MODELTIEPOINTTAG = 33922
+TIFFTAG_IT8SITE = 34016
+TIFFTAG_IT8COLORSEQUENCE = 34017
+TIFFTAG_IT8HEADER = 34018
+TIFFTAG_IT8RASTERPADDING = 34019
+TIFFTAG_IT8BITSPERRUNLENGTH = 34020
+TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH = 34021
+TIFFTAG_IT8COLORTABLE = 34022
+TIFFTAG_IT8IMAGECOLORINDICATOR = 34023
+TIFFTAG_IT8BKGCOLORINDICATOR = 34024
+TIFFTAG_IT8IMAGECOLORVALUE = 34025
+TIFFTAG_IT8BKGCOLORVALUE = 34026
+TIFFTAG_IT8PIXELINTENSITYRANGE = 34027
+TIFFTAG_IT8TRANSPARENCYINDICATOR = 34028
+TIFFTAG_IT8COLORCHARACTERIZATION = 34029
+TIFFTAG_IT8HCUSAGE = 34030
+TIFFTAG_IT8TRAPINDICATOR = 34031
+TIFFTAG_IT8CMYKEQUIVALENT = 34032
+TIFFTAG_FRAMECOUNT = 34232
+TIFFTAG_MODELTRANSFORMATIONTAG = 34264
+TIFFTAG_PHOTOSHOP = 34377
+TIFFTAG_EXIFIFD = 34665
+TIFFTAG_ICCPROFILE = 34675
+TIFFTAG_IMAGELAYER = 34732
+TIFFTAG_JBIGOPTIONS = 34750
+TIFFTAG_GPSIFD = 34853
+TIFFTAG_FAXRECVPARAMS = 34908
+TIFFTAG_FAXSUBADDRESS = 34909
+TIFFTAG_FAXRECVTIME = 34910
+TIFFTAG_FAXDCS = 34911
+TIFFTAG_STONITS = 37439
+TIFFTAG_FEDEX_EDR = 34929
+TIFFTAG_IMAGESOURCEDATA = 37724
+TIFFTAG_INTEROPERABILITYIFD = 40965
+TIFFTAG_GDAL_METADATA = 42112
+TIFFTAG_GDAL_NODATA = 42113
+TIFFTAG_OCE_SCANJOB_DESCRIPTION = 50215
+TIFFTAG_OCE_APPLICATION_SELECTOR = 50216
+TIFFTAG_OCE_IDENTIFICATION_NUMBER = 50217
+TIFFTAG_OCE_IMAGELOGIC_CHARACTERISTICS = 50218
+TIFFTAG_LERC_PARAMETERS = 50674
+TIFFTAG_DNGVERSION = 50706
+TIFFTAG_DNGBACKWARDVERSION = 50707
+TIFFTAG_UNIQUECAMERAMODEL = 50708
+TIFFTAG_LOCALIZEDCAMERAMODEL = 50709
+TIFFTAG_CFAPLANECOLOR = 50710
+TIFFTAG_CFALAYOUT = 50711
+TIFFTAG_LINEARIZATIONTABLE = 50712
+TIFFTAG_BLACKLEVELREPEATDIM = 50713
+TIFFTAG_BLACKLEVEL = 50714
+TIFFTAG_BLACKLEVELDELTAH = 50715
+TIFFTAG_BLACKLEVELDELTAV = 50716
+TIFFTAG_WHITELEVEL = 50717
+TIFFTAG_DEFAULTSCALE = 50718
+TIFFTAG_DEFAULTCROPORIGIN = 50719
+TIFFTAG_DEFAULTCROPSIZE = 50720
+TIFFTAG_COLORMATRIX1 = 50721
+TIFFTAG_COLORMATRIX2 = 50722
+TIFFTAG_CAMERACALIBRATION1 = 50723
+TIFFTAG_CAMERACALIBRATION2 = 50724
+TIFFTAG_REDUCTIONMATRIX1 = 50725
+TIFFTAG_REDUCTIONMATRIX2 = 50726
+TIFFTAG_ANALOGBALANCE = 50727
+TIFFTAG_ASSHOTNEUTRAL = 50728
+TIFFTAG_ASSHOTWHITEXY = 50729
+TIFFTAG_BASELINEEXPOSURE = 50730
+TIFFTAG_BASELINENOISE = 50731
+TIFFTAG_BASELINESHARPNESS = 50732
+TIFFTAG_BAYERGREENSPLIT = 50733
+TIFFTAG_LINEARRESPONSELIMIT = 50734
+TIFFTAG_CAMERASERIALNUMBER = 50735
+TIFFTAG_LENSINFO = 50736
+TIFFTAG_CHROMABLURRADIUS = 50737
+TIFFTAG_ANTIALIASSTRENGTH = 50738
+TIFFTAG_SHADOWSCALE = 50739
+TIFFTAG_DNGPRIVATEDATA = 50740
+TIFFTAG_MAKERNOTESAFETY = 50741
+TIFFTAG_CALIBRATIONILLUMINANT1 = 50778
+TIFFTAG_CALIBRATIONILLUMINANT2 = 50779
+TIFFTAG_BESTQUALITYSCALE = 50780
+TIFFTAG_RAWDATAUNIQUEID = 50781
+TIFFTAG_ORIGINALRAWFILENAME = 50827
+TIFFTAG_ORIGINALRAWFILEDATA = 50828
+TIFFTAG_ACTIVEAREA = 50829
+TIFFTAG_MASKEDAREAS = 50830
+TIFFTAG_ASSHOTICCPROFILE = 50831
+TIFFTAG_ASSHOTPREPROFILEMATRIX = 50832
+TIFFTAG_CURRENTICCPROFILE = 50833
+TIFFTAG_CURRENTPREPROFILEMATRIX = 50834
+TIFFTAG_COLORIMETRICREFERENCE = 50879
+TIFFTAG_CAMERACALIBRATIONSIGNATURE = 50931
+TIFFTAG_PROFILECALIBRATIONSIGNATURE = 50932
+TIFFTAG_ASSHOTPROFILENAME = 50934
+TIFFTAG_NOISEREDUCTIONAPPLIED = 50935
+TIFFTAG_PROFILENAME = 50936
+TIFFTAG_PROFILEHUESATMAPDIMS = 50937
+TIFFTAG_PROFILEHUESATMAPDATA1 = 50938
+TIFFTAG_PROFILEHUESATMAPDATA2 = 50939
+TIFFTAG_PROFILETONECURVE = 50940
+TIFFTAG_PROFILEEMBEDPOLICY = 50941
+TIFFTAG_PROFILECOPYRIGHT = 50942
+TIFFTAG_FORWARDMATRIX1 = 50964
+TIFFTAG_FORWARDMATRIX2 = 50965
+TIFFTAG_PREVIEWAPPLICATIONNAME = 50966
+TIFFTAG_PREVIEWAPPLICATIONVERSION = 50967
+TIFFTAG_PREVIEWSETTINGSNAME = 50968
+TIFFTAG_PREVIEWSETTINGSDIGEST = 50969
+TIFFTAG_PREVIEWCOLORSPACE = 50970
+TIFFTAG_PREVIEWDATETIME = 50971
+TIFFTAG_RAWIMAGEDIGEST = 50972
+TIFFTAG_ORIGINALRAWFILEDIGEST = 50973
+TIFFTAG_SUBTILEBLOCKSIZE = 50974
+TIFFTAG_ROWINTERLEAVEFACTOR = 50975
+TIFFTAG_PROFILELOOKTABLEDIMS = 50981
+TIFFTAG_PROFILELOOKTABLEDATA = 50982
+TIFFTAG_OPCODELIST1 = 51008
+TIFFTAG_OPCODELIST2 = 51009
+TIFFTAG_OPCODELIST3 = 51022
+TIFFTAG_NOISEPROFILE = 51041
+TIFFTAG_DEFAULTUSERCROP = 51125
+TIFFTAG_DEFAULTBLACKRENDER = 51110
+TIFFTAG_BASELINEEXPOSUREOFFSET = 51109
+TIFFTAG_PROFILELOOKTABLEENCODING = 51108
+TIFFTAG_PROFILEHUESATMAPENCODING = 51107
+TIFFTAG_ORIGINALDEFAULTFINALSIZE = 51089
+TIFFTAG_ORIGINALBESTQUALITYFINALSIZE = 51090
+TIFFTAG_ORIGINALDEFAULTCROPSIZE = 51091
+TIFFTAG_NEWRAWIMAGEDIGEST = 51111
+TIFFTAG_RAWTOPREVIEWGAIN = 51112
+TIFFTAG_DEPTHFORMAT = 51177
+TIFFTAG_DEPTHNEAR = 51178
+TIFFTAG_DEPTHFAR = 51179
+TIFFTAG_DEPTHUNITS = 51180
+TIFFTAG_DEPTHMEASURETYPE = 51181
+TIFFTAG_ENHANCEPARAMS = 51182
+TIFFTAG_PROFILEGAINTABLEMAP = 52525
+TIFFTAG_SEMANTICNAME = 52526
+TIFFTAG_SEMANTICINSTANCEID = 52528
+TIFFTAG_MASKSUBAREA = 52536
+TIFFTAG_RGBTABLES = 52543
+TIFFTAG_CALIBRATIONILLUMINANT3 = 52529
+TIFFTAG_COLORMATRIX3 = 52531
+TIFFTAG_CAMERACALIBRATION3 = 52530
+TIFFTAG_REDUCTIONMATRIX3 = 52538
+TIFFTAG_PROFILEHUESATMAPDATA3 = 52537
+TIFFTAG_FORWARDMATRIX3 = 52532
+TIFFTAG_ILLUMINANTDATA1 = 52533
+TIFFTAG_ILLUMINANTDATA2 = 52534
+TIFFTAG_ILLUMINANTDATA3 = 53535
+TIFFTAG_EP_CFAREPEATPATTERNDIM = 33421
+TIFFTAG_EP_CFAPATTERN = 33422
+TIFFTAG_EP_BATTERYLEVEL = 33423
+TIFFTAG_EP_INTERLACE = 34857
+TIFFTAG_EP_IPTC_NAA = 33723
+TIFFTAG_EP_TIMEZONEOFFSET = 34858
+TIFFTAG_EP_SELFTIMERMODE = 34859
+TIFFTAG_EP_FLASHENERGY = 37387
+TIFFTAG_EP_SPATIALFREQUENCYRESPONSE = 37388
+TIFFTAG_EP_NOISE = 37389
+TIFFTAG_EP_FOCALPLANEXRESOLUTION = 37390
+TIFFTAG_EP_FOCALPLANEYRESOLUTION = 37391
+TIFFTAG_EP_FOCALPLANERESOLUTIONUNIT = 37392
+TIFFTAG_EP_IMAGENUMBER = 37393
+TIFFTAG_EP_SECURITYCLASSIFICATION = 37394
+TIFFTAG_EP_IMAGEHISTORY = 37395
+TIFFTAG_EP_EXPOSUREINDEX = 37397
+TIFFTAG_EP_STANDARDID = 37398
+TIFFTAG_EP_SENSINGMETHOD = 37399
+TIFFTAG_EP_EXPOSURETIME = 33434
+TIFFTAG_EP_FNUMBER = 33437
+TIFFTAG_EP_EXPOSUREPROGRAM = 34850
+TIFFTAG_EP_SPECTRALSENSITIVITY = 34852
+TIFFTAG_EP_ISOSPEEDRATINGS = 34855
+TIFFTAG_EP_OECF = 34856
+TIFFTAG_EP_DATETIMEORIGINAL = 36867
+TIFFTAG_EP_COMPRESSEDBITSPERPIXEL = 37122
+TIFFTAG_EP_SHUTTERSPEEDVALUE = 37377
+TIFFTAG_EP_APERTUREVALUE = 37378
+TIFFTAG_EP_BRIGHTNESSVALUE = 37379
+TIFFTAG_EP_EXPOSUREBIASVALUE = 37380
+TIFFTAG_EP_MAXAPERTUREVALUE = 37381
+TIFFTAG_EP_SUBJECTDISTANCE = 37382
+TIFFTAG_EP_METERINGMODE = 37383
+TIFFTAG_EP_LIGHTSOURCE = 37384
+TIFFTAG_EP_FLASH = 37385
+TIFFTAG_EP_FOCALLENGTH = 37386
+TIFFTAG_EP_SUBJECTLOCATION = 37396
+TIFFTAG_RPCCOEFFICIENT = 50844
+TIFFTAG_ALIAS_LAYER_METADATA = 50784
+TIFFTAG_TIFF_RSID = 50908
+TIFFTAG_GEO_METADATA = 50909
+TIFFTAG_EXTRACAMERAPROFILES = 50933
+TIFFTAG_DCSHUESHIFTVALUES = 65535
+TIFFTAG_FAXMODE = 65536
+FAXMODE_CLASSIC = 0
+FAXMODE_NORTC = 1
+FAXMODE_NOEOL = 2
+FAXMODE_BYTEALIGN = 4
+FAXMODE_WORDALIGN = 8
+FAXMODE_CLASSF = 1
+TIFFTAG_JPEGQUALITY = 65537
+TIFFTAG_JPEGCOLORMODE = 65538
+JPEGCOLORMODE_RAW = 0
+JPEGCOLORMODE_RGB = 1
+TIFFTAG_JPEGTABLESMODE = 65539
+JPEGTABLESMODE_QUANT = 1
+JPEGTABLESMODE_HUFF = 2
+TIFFTAG_FAXFILLFUNC = 65540
+TIFFTAG_PIXARLOGDATAFMT = 65549
+PIXARLOGDATAFMT_8BIT = 0
+PIXARLOGDATAFMT_8BITABGR = 1
+PIXARLOGDATAFMT_11BITLOG = 2
+PIXARLOGDATAFMT_12BITPICIO = 3
+PIXARLOGDATAFMT_16BIT = 4
+PIXARLOGDATAFMT_FLOAT = 5
+TIFFTAG_DCSIMAGERTYPE = 65550
+DCSIMAGERMODEL_M3 = 0
+DCSIMAGERMODEL_M5 = 1
+DCSIMAGERMODEL_M6 = 2
+DCSIMAGERFILTER_IR = 0
+DCSIMAGERFILTER_MONO = 1
+DCSIMAGERFILTER_CFA = 2
+DCSIMAGERFILTER_OTHER = 3
+TIFFTAG_DCSINTERPMODE = 65551
+DCSINTERPMODE_NORMAL = 0
+DCSINTERPMODE_PREVIEW = 1
+TIFFTAG_DCSBALANCEARRAY = 65552
+TIFFTAG_DCSCORRECTMATRIX = 65553
+TIFFTAG_DCSGAMMA = 65554
+TIFFTAG_DCSTOESHOULDERPTS = 65555
+TIFFTAG_DCSCALIBRATIONFD = 65556
+TIFFTAG_ZIPQUALITY = 65557
+TIFFTAG_PIXARLOGQUALITY = 65558
+TIFFTAG_DCSCLIPRECTANGLE = 65559
+TIFFTAG_SGILOGDATAFMT = 65560
+SGILOGDATAFMT_FLOAT = 0
+SGILOGDATAFMT_16BIT = 1
+SGILOGDATAFMT_RAW = 2
+SGILOGDATAFMT_8BIT = 3
+TIFFTAG_SGILOGENCODE = 65561
+SGILOGENCODE_NODITHER = 0
+SGILOGENCODE_RANDITHER = 1
+TIFFTAG_LZMAPRESET = 65562
+TIFFTAG_PERSAMPLE = 65563
+PERSAMPLE_MERGED = 0
+PERSAMPLE_MULTI = 1
+TIFFTAG_ZSTD_LEVEL = 65564
+TIFFTAG_LERC_VERSION = 65565
+LERC_VERSION_2_4 = 4
+TIFFTAG_LERC_ADD_COMPRESSION = 65566
+LERC_ADD_COMPRESSION_NONE = 0
+LERC_ADD_COMPRESSION_DEFLATE = 1
+LERC_ADD_COMPRESSION_ZSTD = 2
+TIFFTAG_LERC_MAXZERROR = 65567
+TIFFTAG_WEBP_LEVEL = 65568
+TIFFTAG_WEBP_LOSSLESS = 65569
+TIFFTAG_WEBP_LOSSLESS_EXACT = 65571
+TIFFTAG_DEFLATE_SUBCODEC = 65570
+DEFLATE_SUBCODEC_ZLIB = 0
+DEFLATE_SUBCODEC_LIBDEFLATE = 1
+EXIFTAG_EXPOSURETIME = 33434
+EXIFTAG_FNUMBER = 33437
+EXIFTAG_EXPOSUREPROGRAM = 34850
+EXIFTAG_SPECTRALSENSITIVITY = 34852
+EXIFTAG_ISOSPEEDRATINGS = 34855
+EXIFTAG_PHOTOGRAPHICSENSITIVITY = 34855
+EXIFTAG_OECF = 34856
+EXIFTAG_EXIFVERSION = 36864
+EXIFTAG_DATETIMEORIGINAL = 36867
+EXIFTAG_DATETIMEDIGITIZED = 36868
+EXIFTAG_COMPONENTSCONFIGURATION = 37121
+EXIFTAG_COMPRESSEDBITSPERPIXEL = 37122
+EXIFTAG_SHUTTERSPEEDVALUE = 37377
+EXIFTAG_APERTUREVALUE = 37378
+EXIFTAG_BRIGHTNESSVALUE = 37379
+EXIFTAG_EXPOSUREBIASVALUE = 37380
+EXIFTAG_MAXAPERTUREVALUE = 37381
+EXIFTAG_SUBJECTDISTANCE = 37382
+EXIFTAG_METERINGMODE = 37383
+EXIFTAG_LIGHTSOURCE = 37384
+EXIFTAG_FLASH = 37385
+EXIFTAG_FOCALLENGTH = 37386
+EXIFTAG_SUBJECTAREA = 37396
+EXIFTAG_MAKERNOTE = 37500
+EXIFTAG_USERCOMMENT = 37510
+EXIFTAG_SUBSECTIME = 37520
+EXIFTAG_SUBSECTIMEORIGINAL = 37521
+EXIFTAG_SUBSECTIMEDIGITIZED = 37522
+EXIFTAG_FLASHPIXVERSION = 40960
+EXIFTAG_COLORSPACE = 40961
+EXIFTAG_PIXELXDIMENSION = 40962
+EXIFTAG_PIXELYDIMENSION = 40963
+EXIFTAG_RELATEDSOUNDFILE = 40964
+EXIFTAG_FLASHENERGY = 41483
+EXIFTAG_SPATIALFREQUENCYRESPONSE = 41484
+EXIFTAG_FOCALPLANEXRESOLUTION = 41486
+EXIFTAG_FOCALPLANEYRESOLUTION = 41487
+EXIFTAG_FOCALPLANERESOLUTIONUNIT = 41488
+EXIFTAG_SUBJECTLOCATION = 41492
+EXIFTAG_EXPOSUREINDEX = 41493
+EXIFTAG_SENSINGMETHOD = 41495
+EXIFTAG_FILESOURCE = 41728
+EXIFTAG_SCENETYPE = 41729
+EXIFTAG_CFAPATTERN = 41730
+EXIFTAG_CUSTOMRENDERED = 41985
+EXIFTAG_EXPOSUREMODE = 41986
+EXIFTAG_WHITEBALANCE = 41987
+EXIFTAG_DIGITALZOOMRATIO = 41988
+EXIFTAG_FOCALLENGTHIN35MMFILM = 41989
+EXIFTAG_SCENECAPTURETYPE = 41990
+EXIFTAG_GAINCONTROL = 41991
+EXIFTAG_CONTRAST = 41992
+EXIFTAG_SATURATION = 41993
+EXIFTAG_SHARPNESS = 41994
+EXIFTAG_DEVICESETTINGDESCRIPTION = 41995
+EXIFTAG_SUBJECTDISTANCERANGE = 41996
+EXIFTAG_IMAGEUNIQUEID = 42016
+EXIFTAG_SENSITIVITYTYPE = 34864
+EXIFTAG_STANDARDOUTPUTSENSITIVITY = 34865
+EXIFTAG_RECOMMENDEDEXPOSUREINDEX = 34866
+EXIFTAG_ISOSPEED = 34867
+EXIFTAG_ISOSPEEDLATITUDEYYY = 34868
+EXIFTAG_ISOSPEEDLATITUDEZZZ = 34869
+EXIFTAG_OFFSETTIME = 36880
+EXIFTAG_OFFSETTIMEORIGINAL = 36881
+EXIFTAG_OFFSETTIMEDIGITIZED = 36882
+EXIFTAG_TEMPERATURE = 37888
+EXIFTAG_HUMIDITY = 37889
+EXIFTAG_PRESSURE = 37890
+EXIFTAG_WATERDEPTH = 37891
+EXIFTAG_ACCELERATION = 37892
+EXIFTAG_CAMERAELEVATIONANGLE = 37893
+EXIFTAG_CAMERAOWNERNAME = 42032
+EXIFTAG_BODYSERIALNUMBER = 42033
+EXIFTAG_LENSSPECIFICATION = 42034
+EXIFTAG_LENSMAKE = 42035
+EXIFTAG_LENSMODEL = 42036
+EXIFTAG_LENSSERIALNUMBER = 42037
+EXIFTAG_GAMMA = 42240
+EXIFTAG_COMPOSITEIMAGE = 42080
+EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE = 42081
+EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE = 42082
+GPSTAG_VERSIONID = 0
+GPSTAG_LATITUDEREF = 1
+GPSTAG_LATITUDE = 2
+GPSTAG_LONGITUDEREF = 3
+GPSTAG_LONGITUDE = 4
+GPSTAG_ALTITUDEREF = 5
+GPSTAG_ALTITUDE = 6
+GPSTAG_TIMESTAMP = 7
+GPSTAG_SATELLITES = 8
+GPSTAG_STATUS = 9
+GPSTAG_MEASUREMODE = 10
+GPSTAG_DOP = 11
+GPSTAG_SPEEDREF = 12
+GPSTAG_SPEED = 13
+GPSTAG_TRACKREF = 14
+GPSTAG_TRACK = 15
+GPSTAG_IMGDIRECTIONREF = 16
+GPSTAG_IMGDIRECTION = 17
+GPSTAG_MAPDATUM = 18
+GPSTAG_DESTLATITUDEREF = 19
+GPSTAG_DESTLATITUDE = 20
+GPSTAG_DESTLONGITUDEREF = 21
+GPSTAG_DESTLONGITUDE = 22
+GPSTAG_DESTBEARINGREF = 23
+GPSTAG_DESTBEARING = 24
+GPSTAG_DESTDISTANCEREF = 25
+GPSTAG_DESTDISTANCE = 26
+GPSTAG_PROCESSINGMETHOD = 27
+GPSTAG_AREAINFORMATION = 28
+GPSTAG_DATESTAMP = 29
+GPSTAG_DIFFERENTIAL = 30
+GPSTAG_GPSHPOSITIONINGERROR = 31


=====================================
libtiff/tiff_image.py
=====================================
@@ -437,7 +437,7 @@ class TIFFimage:
 
         if compressed_data_size != image_data_size:
             sdiff = image_data_size - compressed_data_size
-            total_size -= sdiff
+            total_size = int(total_size) - sdiff
             base = tif._mmap
             if base is None:
                 base = tif.base


=====================================
libtiff/utils.py
=====================================
@@ -19,6 +19,7 @@ def isindisk(path):
 
 def bytes2str(bytes):
     lst = []
+    bytes = int(bytes)
     Pbytes = bytes // 1024**5
     if Pbytes:
         lst.append('%sPi' % (Pbytes))


=====================================
pyproject.toml
=====================================
@@ -1,5 +1,5 @@
 [build-system]
-requires = ["setuptools>=60", "wheel", "setuptools_scm[toml]>=8.0", 'oldest-supported-numpy']
+requires = ["setuptools>=60", "wheel", "setuptools_scm[toml]>=8.0", 'numpy>=2.0.0']
 build-backend = "setuptools.build_meta"
 
 [tool.setuptools_scm]



View it on GitLab: https://salsa.debian.org/debian-gis-team/pylibtiff/-/compare/1f304abce33fc8ffe7199bd7a0858922be4eb198...3e8dcfccebb3f91098769a249efc1d3a71ac7186

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/pylibtiff/-/compare/1f304abce33fc8ffe7199bd7a0858922be4eb198...3e8dcfccebb3f91098769a249efc1d3a71ac7186
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/20251004/b5081928/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list