1# test_tifffile.py
2
3# Copyright (c) 2008-2021, Christoph Gohlke
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are met:
8#
9# 1. Redistributions of source code must retain the above copyright notice,
10#    this list of conditions and the following disclaimer.
11#
12# 2. Redistributions in binary form must reproduce the above copyright notice,
13#    this list of conditions and the following disclaimer in the documentation
14#    and/or other materials provided with the distribution.
15#
16# 3. Neither the name of the copyright holder nor the names of its
17#    contributors may be used to endorse or promote products derived from
18#    this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30# POSSIBILITY OF SUCH DAMAGE.
31
32"""Unittests for the tifffile package.
33
34Public data files can be requested from the author.
35Private data files are not available due to size and copyright restrictions.
36
37:Version: 2021.8.30
38
39"""
40
41import binascii
42import datetime
43import glob
44import json
45import math
46import mmap
47import os
48import pathlib
49import random
50import re
51import struct
52import sys
53import tempfile
54import urllib.request
55import urllib.error
56from io import BytesIO
57
58import fsspec
59import numpy
60import pytest
61import tifffile
62from numpy.testing import (
63    assert_allclose,
64    assert_array_almost_equal,
65    assert_array_equal,
66)
67
68try:
69    from tifffile import *
70
71    STAR_IMPORTED = (
72        TIFF,
73        imwrite,
74        imread,
75        imshow,
76        TiffWriter,
77        TiffReader,
78        TiffFile,
79        TiffFileError,
80        TiffSequence,
81        TiffPage,
82        TiffFrame,
83        FileHandle,
84        FileSequence,
85        Timer,
86        lazyattr,
87        natural_sorted,
88        stripnull,
89        memmap,
90        repeat_nd,
91        format_size,
92        product,
93        create_output,
94        askopenfilename,
95        read_scanimage_metadata,
96        read_micromanager_metadata,
97        OmeXmlError,
98        OmeXml,
99    )
100except NameError:
101    STAR_IMPORTED = None
102
103from tifffile.tifffile import (
104    TIFF,
105    FileCache,
106    FileHandle,
107    FileSequence,
108    OmeXml,
109    OmeXmlError,
110    TiffFile,
111    TiffFileError,
112    TiffFrame,
113    TiffPage,
114    TiffPageSeries,
115    TiffReader,
116    TiffSequence,
117    TiffTag,
118    TiffTags,
119    TiffWriter,
120    ZarrFileSequenceStore,
121    ZarrStore,
122    ZarrTiffStore,
123    apply_colormap,
124    asbool,
125    byteorder_compare,
126    byteorder_isnative,
127    bytes2str,
128    create_output,
129    enumarg,
130    epics_datetime,
131    excel_datetime,
132    fluoview_description_metadata,
133    format_size,
134    hexdump,
135    imagecodecs,
136    imagej_description,
137    imagej_description_metadata,
138    imagej_shape,
139    imread,
140    imshow,
141    imwrite,
142    json_description,
143    json_description_metadata,
144    julian_datetime,
145    lazyattr,
146    lsm2bin,
147    matlabstr2py,
148    memmap,
149    metaseries_description_metadata,
150    natural_sorted,
151    parse_filenames,
152    pformat,
153    pilatus_description_metadata,
154    product,
155    read_scanimage_metadata,
156    repeat_nd,
157    reshape_axes,
158    reshape_nd,
159    scanimage_artist_metadata,
160    scanimage_description_metadata,
161    sequence,
162    snipstr,
163    squeeze_axes,
164    stripascii,
165    stripnull,
166    subresolution,
167    svs_description_metadata,
168    tiffcomment,
169    transpose_axes,
170    unpack_rgb,
171    validate_jhove,
172    xml2dict,
173)
174
175# skip certain tests
176SKIP_LARGE = False  # skip tests requiring large memory
177SKIP_EXTENDED = False
178SKIP_PUBLIC = False  # skip public files
179SKIP_PRIVATE = False  # skip private files
180SKIP_VALIDATE = True  # skip validate written files with jhove
181SKIP_CODECS = False
182SKIP_ZARR = False
183SKIP_DASK = False
184SKIP_HTTP = False
185SKIP_PYPY = 'PyPy' in sys.version
186SKIP_WIN = sys.platform != 'win32'
187SKIP_BE = sys.byteorder == 'big'
188REASON = 'skipped'
189
190if sys.maxsize < 2 ** 32:
191    SKIP_LARGE = True
192
193MINISBLACK = TIFF.PHOTOMETRIC.MINISBLACK
194MINISWHITE = TIFF.PHOTOMETRIC.MINISWHITE
195RGB = TIFF.PHOTOMETRIC.RGB
196CFA = TIFF.PHOTOMETRIC.CFA
197SEPARATED = TIFF.PHOTOMETRIC.SEPARATED
198PALETTE = TIFF.PHOTOMETRIC.PALETTE
199YCBCR = TIFF.PHOTOMETRIC.YCBCR
200CONTIG = TIFF.PLANARCONFIG.CONTIG
201SEPARATE = TIFF.PLANARCONFIG.SEPARATE
202LZW = TIFF.COMPRESSION.LZW
203LZMA = TIFF.COMPRESSION.LZMA
204ZSTD = TIFF.COMPRESSION.ZSTD
205WEBP = TIFF.COMPRESSION.WEBP
206PNG = TIFF.COMPRESSION.PNG
207LERC = TIFF.COMPRESSION.LERC
208JPEGXL = TIFF.COMPRESSION.JPEGXL
209PACKBITS = TIFF.COMPRESSION.PACKBITS
210JPEG = TIFF.COMPRESSION.JPEG
211OJPEG = TIFF.COMPRESSION.OJPEG
212APERIO_JP2000_RGB = TIFF.COMPRESSION.APERIO_JP2000_RGB
213APERIO_JP2000_YCBC = TIFF.COMPRESSION.APERIO_JP2000_YCBC
214ADOBE_DEFLATE = TIFF.COMPRESSION.ADOBE_DEFLATE
215DEFLATE = TIFF.COMPRESSION.DEFLATE
216NONE = TIFF.COMPRESSION.NONE
217LSB2MSB = TIFF.FILLORDER.LSB2MSB
218ASSOCALPHA = TIFF.EXTRASAMPLE.ASSOCALPHA
219UNASSALPHA = TIFF.EXTRASAMPLE.UNASSALPHA
220UNSPECIFIED = TIFF.EXTRASAMPLE.UNSPECIFIED
221HORIZONTAL = TIFF.PREDICTOR.HORIZONTAL
222
223FILE_FLAGS = ['is_' + a for a in TIFF.FILE_FLAGS]
224FILE_FLAGS += [name for name in dir(TiffFile) if name.startswith('is_')]
225PAGE_FLAGS = [name for name in dir(TiffPage) if name.startswith('is_')]
226
227HERE = os.path.dirname(__file__)
228# HERE = os.path.join(HERE, 'tests')
229TEMP_DIR = os.path.join(HERE, '_tmp')
230PRIVATE_DIR = os.path.join(HERE, 'data', 'private')
231PUBLIC_DIR = os.path.join(HERE, 'data', 'public')
232
233URL = 'http://localhost:8181/'  # TEMP_DIR
234
235if not SKIP_HTTP:
236    try:
237        urllib.request.urlopen(URL, timeout=0.2)
238    except urllib.error.URLError:
239        SKIP_HTTP = False
240
241if not os.path.exists(TEMP_DIR):
242    TEMP_DIR = tempfile.gettempdir()
243
244if not os.path.exists(PUBLIC_DIR):
245    SKIP_PUBLIC = True
246
247if not os.path.exists(PRIVATE_DIR):
248    SKIP_PRIVATE = True
249
250if not SKIP_CODECS:
251    SKIP_CODECS = imagecodecs is None
252
253if SKIP_ZARR:
254    zarr = None
255else:
256    try:
257        import zarr
258    except ImportError:
259        zarr = None
260        SKIP_ZARR = True
261
262if SKIP_DASK:
263    dask = None
264else:
265    try:
266        import dask
267    except ImportError:
268        dask = None
269        SKIP_DASK = True
270
271
272def config():
273    """Return test configuration."""
274    this = sys.modules[__name__]
275    return ' | '.join(
276        a for a in dir(this) if a.startswith('SKIP_') and getattr(this, a)
277    )
278
279
280def data_file(pathname, base, expand=True):
281    """Return path to test file(s)."""
282    path = os.path.join(base, *pathname.split('/'))
283    if expand and any(i in path for i in '*?'):
284        return glob.glob(path)
285    return path
286
287
288def private_file(pathname, base=PRIVATE_DIR, expand=True):
289    """Return path to private test file(s)."""
290    return data_file(pathname, base, expand=expand)
291
292
293def public_file(pathname, base=PUBLIC_DIR, expand=True):
294    """Return path to public test file(s)."""
295    return data_file(pathname, base, expand=expand)
296
297
298def random_data(dtype, shape):
299    """Return random numpy array."""
300    # TODO: use nd noise
301    if dtype == '?':
302        return numpy.random.rand(*shape) < 0.5
303    data = numpy.random.rand(*shape) * 255
304    data = data.astype(dtype)
305    return data
306
307
308def assert_file_flags(tiff_file):
309    """Access all flags of TiffFile."""
310    for flag in FILE_FLAGS:
311        getattr(tiff_file, flag)
312
313
314def assert_page_flags(tiff_page):
315    """Access all flags of TiffPage."""
316    for flag in PAGE_FLAGS:
317        getattr(tiff_page, flag)
318
319
320def assert__str__(tif, detail=3):
321    """Call the TiffFile.__str__ function."""
322    for i in range(detail + 1):
323        TiffFile.__str__(tif, detail=i)
324
325
326def assert_valid_omexml(omexml):
327    """Validate OME-XML schema."""
328    OmeXml.validate(omexml, assert_=True)
329
330
331def assert_valid_tiff(filename, *args, **kwargs):
332    """Validate TIFF file using jhove script."""
333    if SKIP_VALIDATE:
334        return
335    validate_jhove(filename, 'jhove.cmd', *args, **kwargs)
336
337
338def assert_decode_method(page, image=None):
339    """Call TiffPage.decode on all segments and compare to TiffPage.asarray."""
340    fh = page.parent.filehandle
341    if page.is_tiled:
342        offsets = page.tags['TileOffsets'].value
343        bytecounts = page.tags['TileByteCounts'].value
344    else:
345        offsets = page.tags['StripOffsets'].value
346        bytecounts = page.tags['StripByteCounts'].value
347    if image is None:
348        image = page.asarray()
349    for i, (o, b) in enumerate(zip(offsets, bytecounts)):
350        fh.seek(o)
351        strile = fh.read(b)
352        strile, index, shape = page.decode(strile, i)
353        assert image.reshape(page.shaped)[index] == strile[0, 0, 0, 0]
354
355
356def assert_aszarr_method(obj, image=None, chunkmode=None, **kwargs):
357    """Assert aszarr returns same data as asarray."""
358    if SKIP_ZARR:
359        return
360    if image is None:
361        image = obj.asarray(**kwargs)
362    with obj.aszarr(chunkmode=chunkmode, **kwargs) as store:
363        data = zarr.open(store, mode='r')
364        if isinstance(data, zarr.Group):
365            data = data[0]
366        assert_array_equal(data, image)
367        del data
368
369
370class TempFileName:
371    """Temporary file name context manager."""
372
373    def __init__(self, name=None, ext='.tif', remove=False):
374        self.remove = remove or TEMP_DIR == tempfile.gettempdir()
375        if not name:
376            fh = tempfile.NamedTemporaryFile(prefix='test_')
377            self.name = fh.named
378            fh.close()
379        else:
380            self.name = os.path.join(TEMP_DIR, f'test_{name}{ext}')
381
382    def __enter__(self):
383        return self.name
384
385    def __exit__(self, exc_type, exc_value, traceback):
386        if self.remove:
387            try:
388                os.remove(self.name)
389            except Exception:
390                pass
391
392
393numpy.set_printoptions(suppress=True, precision=5)
394
395
396###############################################################################
397
398# Tests for specific issues
399
400
401def test_issue_star_import():
402    """Test from tifffile import *."""
403    assert STAR_IMPORTED is not None
404    assert lsm2bin not in STAR_IMPORTED
405
406
407def test_issue_version_mismatch():
408    """Test 'tifffile.__version__' matches docstrings."""
409    ver = ':Version: ' + tifffile.__version__
410    assert ver in __doc__
411    assert ver in tifffile.__doc__
412
413
414def test_issue_deprecated_import():
415    """Test deprecated functions can still be imported."""
416    from tifffile import imsave  # noqa
417
418    # from tifffile import decodelzw
419    # from tifffile import decode_lzw
420
421
422def test_issue_imread_kwargs():
423    """Test that is_flags are handled by imread."""
424    data = random_data(numpy.uint16, (5, 63, 95))
425    with TempFileName('issue_imread_kwargs') as fname:
426        with TiffWriter(fname) as tif:
427            for image in data:
428                tif.write(image)  # create 5 series
429        assert_valid_tiff(fname)
430        image = imread(fname, pattern=None)  # reads first series
431        assert_array_equal(image, data[0])
432        image = imread(fname, is_shaped=False)  # reads all pages
433        assert_array_equal(image, data)
434
435
436def test_issue_imread_kwargs_legacy():
437    """Test legacy arguments still work in some cases.
438
439    Specifying 'fastij', 'movie', 'multifile', 'multifile_close', or
440    'pages' raises DeprecationWarning.
441    Specifying 'key' and 'pages' raises TypeError.
442    Specifying 'pages' in TiffFile constructor raises TypeError.
443
444    """
445    data = random_data(numpy.uint8, (3, 21, 31))
446    with TempFileName('issue_imread_kwargs_legacy') as fname:
447        imwrite(fname, data, photometric=MINISBLACK)
448        with pytest.warns(DeprecationWarning):
449            image = imread(
450                fname,
451                fastij=True,
452                movie=True,
453                multifile=True,
454                multifile_close=True,
455            )
456        assert_array_equal(image, data)
457        with pytest.warns(DeprecationWarning):
458            with TiffFile(
459                fname, fastij=True, multifile=True, multifile_close=True
460            ) as tif:
461                assert_array_equal(tif.asarray(), data)
462        with pytest.raises(TypeError):
463            imread(fname, key=0, pages=[1, 2])
464        with pytest.raises(TypeError):
465            with TiffFile(fname, pages=[1, 2]) as tif:
466                pass
467
468
469@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
470def test_issue_infinite_loop():
471    """Test infinite loop reading more than two tags of same code in IFD."""
472    # Reported by D. Hughes on 2019.7.26
473    # the test file is corrupted but should not cause infinite loop
474    fname = private_file('gdk-pixbuf/bug784903-overflow-dimensions.tiff')
475    with TiffFile(fname) as tif:
476        page = tif.pages[0]
477        assert page.compression == 0  # invalid
478        assert__str__(tif)
479
480
481@pytest.mark.skipif(
482    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
483)
484def test_issue_jpeg_ia():
485    """Test JPEG compressed intensity image with alpha channel."""
486    # no extrasamples!
487    fname = private_file('issues/jpeg_ia.tiff')
488    with TiffFile(fname) as tif:
489        page = tif.pages[0]
490        assert page.compression == JPEG
491        assert_array_equal(
492            page.asarray(),
493            numpy.array([[[0, 0], [255, 255]]], dtype=numpy.uint8),
494        )
495        assert__str__(tif)
496
497
498@pytest.mark.skipif(
499    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
500)
501def test_issue_jpeg_palette():
502    """Test invalid JPEG compressed intensity image with palette."""
503    # https://forum.image.sc/t/viv-and-avivator/45999/24
504    fname = private_file('issues/FL_cells.ome.tif')
505    with TiffFile(fname) as tif:
506        page = tif.pages[0]
507        assert page.compression == JPEG
508        assert page.colormap is not None
509        data = tif.asarray()
510        assert data.shape == (4, 1024, 1024)
511        assert data.dtype == numpy.uint8
512        assert data[2, 512, 512] == 10
513        assert_aszarr_method(tif, data)
514        assert__str__(tif)
515
516
517def test_issue_specific_pages():
518    """Test read second page."""
519    data = random_data(numpy.uint8, (3, 21, 31))
520    with TempFileName('specific_pages') as fname:
521        imwrite(fname, data, photometric=MINISBLACK)
522        image = imread(fname)
523        assert image.shape == (3, 21, 31)
524        # UserWarning: can not reshape (21, 31) to (3, 21, 31)
525        image = imread(fname, key=1)
526        assert image.shape == (21, 31)
527        assert_array_equal(image, data[1])
528    with TempFileName('specific_pages_bigtiff') as fname:
529        imwrite(fname, data, bigtiff=True, photometric=MINISBLACK)
530        image = imread(fname)
531        assert image.shape == (3, 21, 31)
532        # UserWarning: can not reshape (21, 31) to (3, 21, 31)
533        image = imread(fname, key=1)
534        assert image.shape == (21, 31)
535        assert_array_equal(image, data[1])
536
537
538@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
539def test_issue_circular_ifd():
540    """Test circular IFD raises error."""
541    fname = public_file('Tiff-Library-4J/IFD struct/Circular E.tif')
542    with pytest.raises(TiffFileError):
543        imread(fname)
544
545
546@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
547def test_issue_bad_description(caplog):
548    """Test page.description is empty when ImageDescription is not ASCII."""
549    # ImageDescription is not ASCII but bytes
550    fname = private_file('stk/cells in the eye2.stk')
551    with TiffFile(fname) as tif:
552        page = tif.pages[0]
553        assert page.description == ''
554        assert__str__(tif)
555    assert 'coercing invalid ASCII to bytes' in caplog.text
556
557
558@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
559def test_issue_bad_ascii(caplog):
560    """Test coercing invalid ASCII to bytes."""
561    # ImageID is not ASCII but bytes
562    # https://github.com/blink1073/tifffile/pull/38
563    fname = private_file('issues/tifffile_013_tagfail.tif')
564    with TiffFile(fname) as tif:
565        tags = tif.pages[0].tags
566        assert tags['ImageID'].value[-8:] == b'rev 2893'
567        assert__str__(tif)
568    assert 'coercing invalid ASCII to bytes' in caplog.text
569
570
571def test_issue_sampleformat():
572    """Test write correct number of SampleFormat values."""
573    # https://github.com/ngageoint/geopackage-tiff-java/issues/5
574    data = random_data(numpy.int16, (256, 256, 4))
575    with TempFileName('sampleformat') as fname:
576        imwrite(fname, data, photometric=RGB)
577        with TiffFile(fname) as tif:
578            tags = tif.pages[0].tags
579            assert tags['SampleFormat'].value == (2, 2, 2, 2)
580            assert tags['ExtraSamples'].value == (2,)
581            assert__str__(tif)
582
583
584def test_issue_sampleformat_default():
585    """Test SampleFormat are not written for UINT."""
586    data = random_data(numpy.uint8, (256, 256, 4))
587    with TempFileName('sampleformat_default') as fname:
588        imwrite(fname, data, photometric=RGB)
589        with TiffFile(fname) as tif:
590            tags = tif.pages[0].tags
591            'SampleFormat' not in tags
592            assert tags['ExtraSamples'].value == (2,)
593            assert__str__(tif)
594
595
596@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
597def test_issue_palette_with_extrasamples():
598    """Test read palette with extra samples."""
599    # https://github.com/python-pillow/Pillow/issues/1597
600    fname = private_file('issues/palette_with_extrasamples.tif')
601    with TiffFile(fname) as tif:
602        assert len(tif.pages) == 1
603        page = tif.pages[0]
604        assert page.photometric == PALETTE
605        assert page.compression == LZW
606        assert page.imagewidth == 518
607        assert page.imagelength == 556
608        assert page.bitspersample == 8
609        assert page.samplesperpixel == 2
610        # assert data
611        image = page.asrgb()
612        assert image.shape == (556, 518, 3)
613        assert image.dtype == numpy.uint16
614        image = tif.asarray()
615        # self.assertEqual(image.shape[-3:], (556, 518, 2))
616        assert image.shape == (556, 518, 2)
617        assert image.dtype == numpy.uint8
618        assert_aszarr_method(tif, image)
619        del image
620        assert__str__(tif)
621
622
623@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
624def test_issue_incorrect_rowsperstrip_count():
625    """Test read incorrect count for rowsperstrip; bitspersample = 4."""
626    # https://github.com/python-pillow/Pillow/issues/1544
627    fname = private_file('bad/incorrect_count.tiff')
628    with TiffFile(fname) as tif:
629        assert len(tif.pages) == 1
630        page = tif.pages[0]
631        assert page.photometric == PALETTE
632        assert page.compression == ADOBE_DEFLATE
633        assert page.imagewidth == 32
634        assert page.imagelength == 32
635        assert page.bitspersample == 4
636        assert page.samplesperpixel == 1
637        assert page.rowsperstrip == 32
638        assert page.dataoffsets[0] == 8
639        assert page.databytecounts[0] == 89
640        # assert data
641        image = page.asrgb()
642        assert image.shape == (32, 32, 3)
643        assert_aszarr_method(page)
644        del image
645        assert__str__(tif)
646
647
648@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
649def test_issue_extra_strips(caplog):
650    """Test read extra strips."""
651    # https://github.com/opencv/opencv/issues/17054
652    with TiffFile(private_file('issues/extra_strips.tif')) as tif:
653        assert not tif.is_bigtiff
654        assert len(tif.pages) == 1
655        page = tif.pages[0]
656        assert page.tags['StripOffsets'].value == (8, 0, 0)
657        assert page.tags['StripByteCounts'].value == (55064448, 0, 0)
658        assert page.dataoffsets[0] == 8
659        assert page.databytecounts[0] == 55064448
660        assert page.is_contiguous
661        # assert data
662        image = tif.asarray()
663        assert image.shape == (2712, 3384, 3)
664        assert_aszarr_method(page, image)
665    assert 'incorrect StripOffsets count' in caplog.text
666    assert 'incorrect StripByteCounts count' in caplog.text
667
668
669@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
670def test_issue_no_bytecounts(caplog):
671    """Test read no bytecounts."""
672    with TiffFile(private_file('bad/img2_corrupt.tif')) as tif:
673        assert not tif.is_bigtiff
674        assert len(tif.pages) == 1
675        page = tif.pages[0]
676        assert page.is_contiguous
677        assert page.planarconfig == CONTIG
678        assert page.dataoffsets[0] == 512
679        assert page.databytecounts[0] == 0
680        # assert data
681        image = tif.asarray()
682        assert image.shape == (800, 1200)
683        # fails: assert_aszarr_method(tif, image)
684    assert 'invalid tag value offset' in caplog.text
685    assert 'unknown tag data type 31073' in caplog.text
686    assert 'invalid page offset 808333686' in caplog.text
687
688
689@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
690def test_issue_missing_eoi_in_strips():
691    """Test read LZW strips without EOI."""
692    # 256x256 uint16, lzw, imagej
693    # Strips do not contain an EOI code as required by the TIFF spec.
694    # File generated by `tiffcp -c lzw Z*.tif stack.tif` from
695    # Bars-G10-P15.zip
696    # Failed with "series 0 failed: string size must be a multiple of
697    # element size"
698    # Reported by Kai Wohlfahrt on 3/7/2014
699    fname = private_file('issues/stack.tif')
700    with TiffFile(fname) as tif:
701        assert tif.is_imagej
702        assert tif.byteorder == '<'
703        assert len(tif.pages) == 128
704        assert len(tif.series) == 1
705        # assert page properties
706        page = tif.pages[0]
707        assert page.imagewidth == 256
708        assert page.imagelength == 256
709        assert page.bitspersample == 16
710        # assert series properties
711        series = tif.series[0]
712        assert series.shape == (128, 256, 256)
713        assert series.dtype == numpy.uint16
714        assert series.axes == 'IYX'
715        # assert ImageJ tags
716        ijtags = tif.imagej_metadata
717        assert ijtags['ImageJ'] == '1.41e'
718        # assert data
719        data = tif.asarray()
720        assert data.shape == (128, 256, 256)
721        assert data.dtype == numpy.uint16
722        assert data[64, 128, 128] == 19226
723        assert_aszarr_method(tif, data)
724        del data
725        assert__str__(tif)
726
727
728@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
729def test_issue_imagej_grascalemode():
730    """Test read ImageJ grayscale mode RGB image."""
731    # https://github.com/cgohlke/tifffile/issues/6
732    fname = private_file('issues/hela-cells.tif')
733    with TiffFile(fname) as tif:
734        assert tif.is_imagej
735        assert tif.byteorder == '>'
736        assert len(tif.pages) == 1
737        assert len(tif.series) == 1
738        # assert page properties
739        page = tif.pages[0]
740        assert page.photometric == RGB
741        assert page.imagewidth == 672
742        assert page.imagelength == 512
743        assert page.bitspersample == 16
744        assert page.is_contiguous
745        # assert series properties
746        series = tif.series[0]
747        assert series.shape == (512, 672, 3)
748        assert series.dtype == numpy.uint16
749        assert series.axes == 'YXS'
750        # assert ImageJ tags
751        ijtags = tif.imagej_metadata
752        assert ijtags['ImageJ'] == '1.52p'
753        assert ijtags['channels'] == 3
754        # assert data
755        data = tif.asarray()
756        assert isinstance(data, numpy.ndarray)
757        assert data.shape == (512, 672, 3)
758        assert data.dtype == numpy.uint16
759        assert tuple(data[255, 336]) == (440, 378, 298)
760        assert_aszarr_method(tif, data)
761        assert__str__(tif)
762
763
764@pytest.mark.parametrize('byteorder', ['>', '<'])
765def test_issue_valueoffset(byteorder):
766    """Test read TiffTag.valueoffsets."""
767    unpack = struct.unpack
768    data = random_data(byteorder + 'u2', (2, 19, 31))
769    software = 'test_tifffile'
770    bo = {'>': 'be', '<': 'le'}[byteorder]
771    with TempFileName(f'valueoffset_{bo}') as fname:
772        imwrite(
773            fname,
774            data,
775            software=software,
776            photometric=MINISBLACK,
777            extratags=[(65535, 3, 2, (21, 22), True)],
778        )
779        with TiffFile(fname, _useframes=True) as tif:
780            with open(fname, 'rb') as fh:
781                page = tif.pages[0]
782                # inline value
783                fh.seek(page.tags['ImageLength'].valueoffset)
784                assert (
785                    page.imagelength
786                    == unpack(tif.byteorder + 'I', fh.read(4))[0]
787                )
788                # two inline values
789                fh.seek(page.tags[65535].valueoffset)
790                assert unpack(tif.byteorder + 'H', fh.read(2))[0] == 21
791                # separate value
792                fh.seek(page.tags['Software'].valueoffset)
793                assert page.software == bytes2str(fh.read(13))
794                # TiffFrame
795                page = tif.pages[1].aspage()
796                fh.seek(page.tags['StripOffsets'].valueoffset)
797                assert (
798                    page.dataoffsets[0]
799                    == unpack(tif.byteorder + 'I', fh.read(4))[0]
800                )
801
802
803@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
804def test_issue_pages_number():
805    """Test number of pages."""
806    fname = public_file('tifffile/100000_pages.tif')
807    with TiffFile(fname) as tif:
808        assert len(tif.pages) == 100000
809        assert__str__(tif, 0)
810
811
812def test_issue_pages_iterator():
813    """Test iterating over pages in series."""
814    data = random_data(numpy.int8, (8, 219, 301))
815    with TempFileName('page_iterator') as fname:
816        imwrite(fname, data[0])
817        imwrite(
818            fname,
819            data,
820            photometric=MINISBLACK,
821            append=True,
822            metadata={'axes': 'ZYX'},
823        )
824        imwrite(fname, data[-1], append=True)
825        with TiffFile(fname) as tif:
826            assert len(tif.pages) == 10
827            assert len(tif.series) == 3
828            page = tif.pages[1]
829            assert page.is_contiguous
830            assert page.photometric == MINISBLACK
831            assert page.imagewidth == 301
832            assert page.imagelength == 219
833            assert page.samplesperpixel == 1
834            # test reading series 1
835            series = tif.series[1]
836            assert len(series._pages) == 1
837            assert len(series.pages) == 8
838            image = series.asarray()
839            assert_array_equal(data, image)
840            for i, page in enumerate(series.pages):
841                im = page.asarray()
842                assert_array_equal(image[i], im)
843            assert__str__(tif)
844
845
846def test_issue_tile_partial():
847    """Test writing single tiles larger than image data."""
848    # https://github.com/cgohlke/tifffile/issues/3
849    data = random_data(numpy.uint8, (3, 15, 15, 15))
850    with TempFileName('tile_partial_2d') as fname:
851        imwrite(fname, data[0, 0], tile=(16, 16))
852        with TiffFile(fname) as tif:
853            assert len(tif.pages) == 1
854            page = tif.pages[0]
855            assert not page.is_contiguous
856            assert page.is_tiled
857            assert (
858                page.tags['TileOffsets'].value[0]
859                + page.tags['TileByteCounts'].value[0]
860                == tif.filehandle.size
861            )
862            assert_array_equal(page.asarray(), data[0, 0])
863            assert_aszarr_method(page, data[0, 0])
864            assert__str__(tif)
865
866    with TempFileName('tile_partial_3d') as fname:
867        imwrite(fname, data[0], tile=(16, 16, 16))
868        with TiffFile(fname) as tif:
869            assert len(tif.pages) == 1
870            page = tif.pages[0]
871            assert not page.is_contiguous
872            assert page.is_tiled
873            assert page.is_volumetric
874            assert (
875                page.tags['TileOffsets'].value[0]
876                + page.tags['TileByteCounts'].value[0]
877                == tif.filehandle.size
878            )
879            assert_array_equal(page.asarray(), data[0])
880            assert_aszarr_method(page, data[0])
881            assert__str__(tif)
882
883    with TempFileName('tile_partial_3d_separate') as fname:
884        imwrite(
885            fname,
886            data,
887            tile=(16, 16, 16),
888            planarconfig=SEPARATE,
889            photometric=RGB,
890        )
891        with TiffFile(fname) as tif:
892            assert len(tif.pages) == 1
893            page = tif.pages[0]
894            assert not page.is_contiguous
895            assert page.is_tiled
896            assert (
897                page.tags['TileOffsets'].value[0]
898                + page.tags['TileByteCounts'].value[0] * 3
899                == tif.filehandle.size
900            )
901            assert_array_equal(page.asarray(), data)
902            assert_aszarr_method(page, data)
903            assert__str__(tif)
904
905    # test complete tile is contiguous
906    data = random_data(numpy.uint8, (16, 16))
907    with TempFileName('tile_partial_not') as fname:
908        imwrite(fname, data, tile=(16, 16))
909        with TiffFile(fname) as tif:
910            assert len(tif.pages) == 1
911            page = tif.pages[0]
912            assert page.is_contiguous
913            assert page.is_memmappable
914            assert page.is_tiled
915            assert (
916                page.tags['TileOffsets'].value[0]
917                + page.tags['TileByteCounts'].value[0]
918                == tif.filehandle.size
919            )
920            assert_array_equal(page.asarray(), data)
921            assert_aszarr_method(page, data)
922            assert__str__(tif)
923
924
925@pytest.mark.parametrize('samples', [1, 3])
926def test_issue_tiles_pad(samples):
927    """Test tiles from iterator get padded."""
928    # https://github.com/cgohlke/tifffile/issues/38
929    if samples == 3:
930        data = numpy.random.randint(0, 2 ** 12, (31, 33, 3), numpy.uint16)
931        photometric = 'rgb'
932    else:
933        data = numpy.random.randint(0, 2 ** 12, (31, 33), numpy.uint16)
934        photometric = None
935
936    def tiles(data, tileshape, pad=False):
937        for y in range(0, data.shape[0], tileshape[0]):
938            for x in range(0, data.shape[1], tileshape[1]):
939                tile = data[y : y + tileshape[0], x : x + tileshape[1]]
940                if pad and tile.shape != tileshape:
941                    tile = numpy.pad(
942                        tile,
943                        (
944                            (0, tileshape[0] - tile.shape[0]),
945                            (0, tileshape[1] - tile.shape[1]),
946                        ),
947                    )
948                yield tile
949
950    with TempFileName(f'issue_tiles_pad_{samples}') as fname:
951        imwrite(
952            fname,
953            tiles(data, (16, 16)),
954            dtype=data.dtype,
955            shape=data.shape,
956            tile=(16, 16),
957            photometric=photometric,
958        )
959        assert_array_equal(imread(fname), data)
960        assert_valid_tiff(fname)
961
962
963def test_issue_fcontiguous():
964    """Test writing F-contiguous arrays."""
965    # https://github.com/cgohlke/tifffile/issues/24
966    data = numpy.asarray(random_data(numpy.uint8, (31, 33)), order='F')
967    with TempFileName('fcontiguous') as fname:
968        imwrite(fname, data, compression=ADOBE_DEFLATE)
969        with TiffFile(fname) as tif:
970            assert len(tif.pages) == 1
971            page = tif.pages[0]
972            assert_array_equal(page.asarray(), data)
973            assert__str__(tif)
974
975
976def test_issue_pathlib():
977    """Test support for pathlib.Path."""
978    data = random_data(numpy.uint16, (219, 301))
979    with TempFileName('pathlib') as fname:
980        fname = pathlib.Path(fname)
981        assert isinstance(fname, os.PathLike)
982        # imwrite
983        imwrite(fname, data)
984        # imread
985        im = imread(fname)
986        assert_array_equal(im, data)
987        # memmap
988        im = memmap(fname)
989        try:
990            assert_array_equal(im, data)
991        finally:
992            del im
993        # TiffFile
994        with TiffFile(fname) as tif:
995            with TempFileName('pathlib_out') as outfname:
996                outfname = pathlib.Path(outfname)
997                # out=file
998                im = tif.asarray(out=outfname)
999                try:
1000                    assert isinstance(im, numpy.core.memmap)
1001                    assert_array_equal(im, data)
1002                    assert os.path.samefile(im.filename, str(outfname))
1003                finally:
1004                    del im
1005        # TiffSequence
1006        with TiffSequence(fname) as tifs:
1007            im = tifs.asarray()
1008            assert_array_equal(im[0], data)
1009        with TiffSequence([fname]) as tifs:
1010            im = tifs.asarray()
1011            assert_array_equal(im[0], data)
1012
1013    # TiffSequence container
1014    if SKIP_PRIVATE or SKIP_CODECS:
1015        pytest.skip(REASON)
1016    fname = pathlib.Path(private_file('TiffSequence.zip'))
1017    with TiffSequence('*.tif', container=fname, pattern=None) as tifs:
1018        im = tifs.asarray()
1019        assert im[9, 256, 256] == 135
1020
1021
1022@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
1023def test_issue_lzw_corrupt():
1024    """Test decoding corrupted LZW segment raises RuntimeError."""
1025    # reported by S Richter on 2020.2.17
1026    fname = private_file('issues/lzw_corrupt.tiff')
1027    with pytest.raises(RuntimeError):
1028        with TiffFile(fname) as tif:
1029            tif.asarray()
1030
1031
1032def test_issue_iterable_compression():
1033    """Test writing iterable of pages with compression."""
1034    # https://github.com/cgohlke/tifffile/issues/20
1035    data = numpy.random.rand(10, 10, 10) * 127
1036    data = data.astype(numpy.int8)
1037    with TempFileName('issue_iterable_compression') as fname:
1038        with TiffWriter(fname) as tif:
1039            tif.write(data, shape=(10, 10, 10), dtype=numpy.int8)
1040            tif.write(
1041                data,
1042                shape=(10, 10, 10),
1043                dtype=numpy.int8,
1044                compression=ADOBE_DEFLATE,
1045            )
1046        with TiffFile(fname) as tif:
1047            assert_array_equal(tif.series[0].asarray(), data)
1048            assert_array_equal(tif.series[1].asarray(), data)
1049    with TempFileName('issue_iterable_compression_fail') as fname:
1050        with TiffWriter(fname) as tif:
1051            with pytest.raises(ValueError):
1052                tif.write(data, shape=(10, 10, 10), dtype=numpy.uint8)
1053        with TiffWriter(fname) as tif:
1054            with pytest.raises(ValueError):
1055                tif.write(
1056                    data,
1057                    shape=(10, 10, 10),
1058                    dtype=numpy.uint8,
1059                    compression=ADOBE_DEFLATE,
1060                )
1061
1062
1063def test_issue_write_separated():
1064    """Test write SEPARATED colorspace."""
1065    # https://github.com/cgohlke/tifffile/issues/37
1066    contig = random_data(numpy.uint8, (63, 95, 4))
1067    separate = random_data(numpy.uint8, (4, 63, 95))
1068    extrasample = random_data(numpy.uint8, (63, 95, 5))
1069    with TempFileName('issue_write_separated') as fname:
1070        with TiffWriter(fname) as tif:
1071            tif.write(contig, photometric=SEPARATED)
1072            tif.write(separate, photometric=SEPARATED)
1073            tif.write(extrasample, photometric=SEPARATED, extrasamples=[1])
1074        assert_valid_tiff(fname)
1075        with TiffFile(fname) as tif:
1076            assert len(tif.pages) == 3
1077            assert len(tif.series) == 3
1078            page = tif.pages[0]
1079            assert page.photometric == SEPARATED
1080            assert_array_equal(page.asarray(), contig)
1081            page = tif.pages[1]
1082            assert page.photometric == SEPARATED
1083            assert_array_equal(page.asarray(), separate)
1084            page = tif.pages[2]
1085            assert page.photometric == SEPARATED
1086            assert page.extrasamples == (1,)
1087            assert_array_equal(page.asarray(), extrasample)
1088
1089
1090@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
1091def test_issue_mmap():
1092    """Test reading from mmap object with no readinto function.."""
1093    fname = public_file('OME/bioformats-artificial/4D-series.ome.tiff')
1094    with open(fname, 'rb') as fh:
1095        mm = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
1096        assert_array_equal(imread(mm), imread(fname))
1097        mm.close()
1098
1099
1100@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
1101def test_issue_micromanager(caplog):
1102    """Test fallback to ImageJ metadata if OME series fails."""
1103    # https://github.com/cgohlke/tifffile/issues/54
1104    # https://forum.image.sc/t/47567/9
1105    # OME-XML does not contain reference to master file
1106    # file has corrupt MicroManager DisplaySettings metadata
1107    fname = private_file(
1108        'OME/'
1109        'image_stack_tpzc_50tp_2p_5z_3c_512k_1_MMStack_2-Pos001_000.ome.tif'
1110    )
1111    with TiffFile(fname) as tif:
1112        assert len(tif.pages) == 750
1113        assert len(tif.series) == 1
1114        assert 'OME series: not an ome-tiff master file' in caplog.text
1115        assert tif.is_micromanager
1116        assert tif.is_ome
1117        assert tif.is_imagej
1118        assert tif.micromanager_metadata['DisplaySettings'] is None
1119        assert 'read_json: invalid JSON' in caplog.text
1120        series = tif.series[0]
1121        assert series.shape == (50, 5, 3, 256, 256)
1122
1123
1124def test_issue_pickle():
1125    """Test that TIFF constants are picklable."""
1126    # https://github.com/cgohlke/tifffile/issues/64
1127    from pickle import dumps, loads
1128
1129    assert loads(dumps(TIFF)).CHUNKMODE.PLANE == TIFF.CHUNKMODE.PLANE
1130    assert loads(dumps(TIFF.CHUNKMODE)).PLANE == TIFF.CHUNKMODE.PLANE
1131    assert loads(dumps(TIFF.CHUNKMODE.PLANE)) == TIFF.CHUNKMODE.PLANE
1132
1133
1134def test_issue_imagej_singlet_dimensions():
1135    """Test that ImageJ files can be read preserving singlet dimensions."""
1136    # https://github.com/cgohlke/tifffile/issues/19
1137    # https://github.com/cgohlke/tifffile/issues/66
1138
1139    data = numpy.random.randint(
1140        0, 2 ** 8, (1, 10, 1, 248, 260, 1), numpy.uint8
1141    )
1142
1143    with TempFileName('issue_imagej_singlet_dimensions') as fname:
1144        imwrite(fname, data, imagej=True)
1145        image = imread(fname, squeeze=False)
1146        assert_array_equal(image, data)
1147
1148        with TiffFile(fname) as tif:
1149            assert tif.is_imagej
1150            series = tif.series[0]
1151            assert series.axes == 'ZYX'
1152            assert series.shape == (10, 248, 260)
1153            assert series.get_axes(squeeze=False) == 'TZCYXS'
1154            assert series.get_shape(squeeze=False) == (1, 10, 1, 248, 260, 1)
1155            data = tif.asarray(squeeze=False)
1156            assert_array_equal(image, data)
1157            assert_aszarr_method(series, data, squeeze=False)
1158            assert_aszarr_method(series, data, squeeze=False, chunkmode='page')
1159
1160
1161@pytest.mark.skipif(
1162    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
1163)
1164def test_issue_cr2_ojpeg():
1165    """Test read OJPEG image from CR2."""
1166    # https://github.com/cgohlke/tifffile/issues/75
1167
1168    fname = private_file('CanonCR2/Canon - EOS M6 - RAW (3 2).cr2')
1169
1170    with TiffFile(fname) as tif:
1171        assert len(tif.pages) == 4
1172        page = tif.pages[0]
1173        assert page.compression == 6
1174        assert page.shape == (4000, 6000, 3)
1175        assert page.dtype == numpy.uint8
1176        assert page.photometric == YCBCR
1177        assert page.compression == OJPEG
1178        data = page.asarray()
1179        assert data.shape == (4000, 6000, 3)
1180        assert data.dtype == numpy.uint8
1181        assert tuple(data[1640, 2372]) == (71, 75, 58)
1182        assert_aszarr_method(page, data)
1183
1184        page = tif.pages[1]
1185        assert page.shape == (120, 160, 3)
1186        assert page.dtype == numpy.uint8
1187        assert page.photometric == YCBCR
1188        assert page.compression == OJPEG
1189        data = page.asarray()
1190        assert tuple(data[60, 80]) == (124, 144, 107)
1191        assert_aszarr_method(page, data)
1192
1193        page = tif.pages[2]
1194        assert page.shape == (400, 600, 3)
1195        assert page.dtype == numpy.uint16
1196        assert page.photometric == RGB
1197        assert page.compression == NONE
1198        data = page.asarray()
1199        assert tuple(data[200, 300]) == (1648, 2340, 1348)
1200        assert_aszarr_method(page, data)
1201
1202        page = tif.pages[3]
1203        assert page.shape == (4056, 3144, 2)
1204        assert page.dtype == numpy.uint16
1205        assert page.photometric == MINISWHITE
1206        assert page.compression == OJPEG  # SOF3
1207        data = page.asarray()
1208        assert tuple(data[2000, 1500]) == (1759, 2467)
1209        assert_aszarr_method(page, data)
1210
1211
1212@pytest.mark.skipif(
1213    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
1214)
1215def test_issue_ojpeg_preview():
1216    """Test read JPEGInterchangeFormat from RAW image."""
1217    # https://github.com/cgohlke/tifffile/issues/93
1218
1219    fname = private_file('RAW/RAW_NIKON_D3X.NEF')
1220
1221    with TiffFile(fname) as tif:
1222        assert len(tif.pages) == 1
1223        page = tif.pages[0]
1224        assert page.compression == NONE
1225        assert page.shape == (120, 160, 3)
1226        assert page.dtype == numpy.uint8
1227        assert page.photometric == RGB
1228        data = page.asarray()
1229        assert data.shape == (120, 160, 3)
1230        assert data.dtype == numpy.uint8
1231        assert tuple(data[60, 80]) == (180, 167, 159)
1232        assert_aszarr_method(page, data)
1233
1234        page = tif.pages[0].pages[0]
1235        assert page.shape == (4032, 6048, 3)
1236        assert page.dtype == numpy.uint8
1237        assert page.photometric == OJPEG
1238        data = page.asarray()
1239        assert tuple(data[60, 80]) == (67, 13, 11)
1240        assert_aszarr_method(page, data)
1241
1242        page = tif.pages[0].pages[1]
1243        assert page.shape == (4044, 6080)
1244        assert page.bitspersample == 14
1245        assert page.photometric == CFA
1246        assert page.compression == TIFF.COMPRESSION.NIKON_NEF
1247        with pytest.raises(ValueError):
1248            data = page.asarray()
1249
1250
1251@pytest.mark.skipif(
1252    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
1253)
1254def test_issue_arw(caplog):
1255    """Test read Sony ARW RAW image."""
1256    # https://github.com/cgohlke/tifffile/issues/95
1257
1258    fname = private_file('RAW/A1_full_lossless_compressed.ARW')
1259
1260    with TiffFile(fname) as tif:
1261        assert len(tif.pages) == 3
1262        assert len(tif.series) == 4
1263
1264        page = tif.pages[0]
1265        assert page.compression == OJPEG
1266        assert page.photometric == YCBCR
1267        assert page.shape == (1080, 1616, 3)
1268        assert page.dtype == numpy.uint8
1269        data = page.asarray()
1270        assert data.shape == (1080, 1616, 3)
1271        assert data.dtype == numpy.uint8
1272        assert tuple(data[60, 80]) == (122, 119, 104)
1273        assert_aszarr_method(page, data)
1274
1275        page = tif.pages[0].pages[0]
1276        assert page.is_tiled
1277        assert page.compression == JPEG
1278        assert page.photometric == CFA
1279        assert page.bitspersample == 14
1280        assert page.tags['SonyRawFileType'].value == 4
1281        assert page.tags['CFARepeatPatternDim'].value == (2, 2)
1282        assert page.tags['CFAPattern'].value == b'\0\1\1\2'
1283        assert page.shape == (6144, 8704)
1284        assert page.dtype == numpy.uint16
1285        data = page.asarray()
1286        assert 'SonyRawFileType' in caplog.text
1287        assert data[60, 80] == 1000  # might not be correct according to #95
1288        assert_aszarr_method(page, data)
1289
1290        page = tif.pages[1]
1291        assert page.compression == OJPEG
1292        assert page.photometric == YCBCR
1293        assert page.shape == (120, 160, 3)
1294        assert page.dtype == numpy.uint8
1295        data = page.asarray()
1296        assert tuple(data[60, 80]) == (56, 54, 29)
1297        assert_aszarr_method(page, data)
1298
1299        page = tif.pages[2]
1300        assert page.compression == JPEG
1301        assert page.photometric == YCBCR
1302        assert page.shape == (5760, 8640, 3)
1303        assert page.dtype == numpy.uint8
1304        data = page.asarray()
1305        assert tuple(data[60, 80]) == (243, 238, 218)
1306        assert_aszarr_method(page, data)
1307
1308
1309def test_issue_rational_rounding():
1310    """Test rational are rounded to 64-bit."""
1311    # https://github.com/cgohlke/tifffile/issues/81
1312
1313    data = numpy.array([[255]])
1314
1315    with TempFileName('issue_rational_rounding') as fname:
1316        imwrite(fname, data, resolution=(7411.824413635355, 7411.824413635355))
1317
1318        with TiffFile(fname) as tif:
1319            assert tif.pages[0].tags['XResolution'].value == (
1320                4294967295,
1321                579475,
1322            )
1323
1324
1325def test_issue_omexml_micron():
1326    """Test OME-TIFF can be created with micron character in XML."""
1327    # https://forum.image.sc/t/micro-character-in-omexml-from-python/53578/4
1328
1329    with TempFileName('issue_omexml_micron', ext='.ome.tif') as fname:
1330        imwrite(
1331            fname,
1332            [[0]],
1333            metadata={'PhysicalSizeX': 1.0, 'PhysicalSizeXUnit': 'µm'},
1334        )
1335        with TiffFile(fname) as tif:
1336            assert tif.is_ome
1337            assert (
1338                'PhysicalSizeXUnit="µm"'
1339                in tif.pages[0].tags['ImageDescription'].value
1340            )
1341
1342
1343def test_issue_svs_doubleheader():
1344    """Test svs_description_metadata for SVS with double header."""
1345    # https://github.com/cgohlke/tifffile/pull/88
1346
1347    assert svs_description_metadata(
1348        'Aperio Image Library v11.2.1\r\n'
1349        '2220x2967 -> 574x768 - ;Aperio Image Library v10.0.51\r\n'
1350        '46920x33014 [0,100 46000x32914] (256x256) JPEG/RGB Q=30'
1351        '|AppMag = 20|StripeWidth = 2040|ScanScope ID = CPAPERIOCS'
1352        '|Filename = CMU-1|Date = 12/29/09|Time = 09:59:15'
1353        '|User = b414003d-95c6-48b0-9369-8010ed517ba7|Parmset = USM Filter'
1354        '|MPP = 0.4990|Left = 25.691574|Top = 23.449873'
1355        '|LineCameraSkew = -0.000424|LineAreaXOffset = 0.019265'
1356        '|LineAreaYOffset = -0.000313|Focus Offset = 0.000000'
1357        '|ImageID = 1004486|OriginalWidth = 46920|Originalheight = 33014'
1358        '|Filtered = 5|OriginalWidth = 46000|OriginalHeight = 32914'
1359    ) == {
1360        'Header': (
1361            'Aperio Image Library v11.2.1\r\n'
1362            '2220x2967 -> 574x768 - ;Aperio Image Library v10.0.51\r\n'
1363            '46920x33014 [0,100 46000x32914] (256x256) JPEG/RGB Q=30'
1364        ),
1365        'AppMag': 20,
1366        'StripeWidth': 2040,
1367        'ScanScope ID': 'CPAPERIOCS',
1368        'Filename': 'CMU-1',
1369        'Date': '12/29/09',
1370        'Time': '09:59:15',
1371        'User': 'b414003d-95c6-48b0-9369-8010ed517ba7',
1372        'Parmset': 'USM Filter',
1373        'MPP': 0.499,
1374        'Left': 25.691574,
1375        'Top': 23.449873,
1376        'LineCameraSkew': -0.000424,
1377        'LineAreaXOffset': 0.019265,
1378        'LineAreaYOffset': -0.000313,
1379        'Focus Offset': 0.0,
1380        'ImageID': 1004486,
1381        'OriginalWidth': 46000,
1382        'Originalheight': 33014,
1383        'Filtered': 5,
1384        'OriginalHeight': 32914,
1385    }
1386
1387
1388@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
1389def test_issue_packbits_dtype():
1390    """Test read and efficiently write PackBits compressed int16 image."""
1391    # https://github.com/blink1073/tifffile/issues/61
1392    # requires imagecodecs > 2021.6.8
1393
1394    fname = private_file('packbits/imstack_packbits-int16.tif')
1395
1396    with TiffFile(fname) as tif:
1397        assert len(tif.pages) == 519
1398        page = tif.pages[181]
1399        assert page.compression == PACKBITS
1400        assert page.photometric == MINISBLACK
1401        assert page.shape == (348, 185)
1402        assert page.dtype == numpy.int16
1403        data = page.asarray()
1404        assert data.shape == (348, 185)
1405        assert data.dtype == numpy.int16
1406        assert data[184, 72] == 24
1407        assert_aszarr_method(page, data)
1408        data = tif.asarray()
1409        assert_aszarr_method(tif, data)
1410
1411    buf = BytesIO()
1412    imwrite(buf, data, compression='packbits')
1413    assert buf.seek(0, 2) < 1700000  # efficiently compressed
1414    buf.seek(0)
1415
1416    with TiffFile(buf) as tif:
1417        assert len(tif.pages) == 519
1418        page = tif.pages[181]
1419        assert page.compression == PACKBITS
1420        assert page.photometric == MINISBLACK
1421        assert page.shape == (348, 185)
1422        assert page.dtype == numpy.int16
1423        data = page.asarray()
1424        assert data.shape == (348, 185)
1425        assert data.dtype == numpy.int16
1426        assert data[184, 72] == 24
1427        assert_aszarr_method(page, data)
1428        data = tif.asarray()
1429        assert_aszarr_method(tif, data)
1430
1431
1432@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
1433def test_issue_predictor_byteorder():
1434    """Test read big-endian uint32 RGB with horizontal predictor."""
1435
1436    fname = private_file('issues/flower-rgb-contig-32_msb_zip_predictor.tiff')
1437
1438    with TiffFile(fname) as tif:
1439        assert tif.tiff.byteorder == '>'
1440        assert len(tif.pages) == 1
1441        page = tif.pages[0]
1442        assert page.compression == ADOBE_DEFLATE
1443        assert page.photometric == RGB
1444        assert page.predictor == HORIZONTAL
1445        assert page.shape == (43, 73, 3)
1446        assert page.dtype == numpy.uint32
1447        data = page.asarray()
1448        assert data.shape == (43, 73, 3)
1449        assert data.dtype == numpy.uint32
1450        assert tuple(data[30, 2]) == (0, 246337650, 191165795)
1451        assert data.dtype.byteorder == '='
1452        assert_aszarr_method(page, data)
1453        data = tif.asarray()
1454        assert_aszarr_method(tif, data)
1455
1456
1457@pytest.mark.skipif(SKIP_ZARR or SKIP_DASK, reason=REASON)
1458@pytest.mark.parametrize('truncate', [False, True])
1459def test_issue_dask_multipage(truncate):
1460    """Test multi-threaded access of memory-mapable, multi-page Zarr stores."""
1461    # https://github.com/cgohlke/tifffile/issues/67#issuecomment-908529425
1462    import dask.array
1463
1464    data = numpy.arange(5 * 4 * 6, dtype=numpy.uint16).reshape((5, 4, 6))
1465    with TempFileName(f'test_issue_dask_multipage{int(truncate)}') as fname:
1466        imwrite(fname, data, truncate=truncate)
1467        with imread(fname, aszarr=True) as store:
1468            daskarray = dask.array.from_zarr(store).compute()
1469    assert_array_equal(data, daskarray)
1470
1471
1472###############################################################################
1473
1474# Test specific functions and classes
1475
1476
1477def test_class_filecache():
1478    """Test FileCache class."""
1479    with TempFileName('class_filecache') as fname:
1480        cache = FileCache(3)
1481
1482        with open(fname, 'wb') as fh:
1483            fh.close()
1484
1485        # create 6 handles, leaving only first one open
1486        handles = []
1487        for i in range(6):
1488            fh = FileHandle(fname)
1489            if i > 0:
1490                fh.close()
1491            handles.append(fh)
1492
1493        # open all files
1494        for fh in handles:
1495            cache.open(fh)
1496        assert len(cache) == 6
1497        for i, fh in enumerate(handles):
1498            assert not fh.closed
1499            assert cache.files[fh] == 1 if i else 2
1500
1501        # close all files: only first file and recently used files are open
1502        for fh in handles:
1503            cache.close(fh)
1504        assert len(cache) == 3
1505        for i, fh in enumerate(handles):
1506            assert fh.closed == (0 < i < 4)
1507            if not 0 < i < 4:
1508                assert cache.files[fh] == 0 if i else 1
1509
1510        # open all files, then clear cache: only first file is open
1511        for fh in handles:
1512            cache.open(fh)
1513        cache.clear()
1514        assert len(cache) == 1
1515        assert handles[0] in cache.files
1516        for i, fh in enumerate(handles):
1517            assert fh.closed == (i > 0)
1518
1519        # randomly open and close files
1520        for i in range(13):
1521            fh = handles[random.randint(0, 5)]
1522            cache.open(fh)
1523            cache.close(fh)
1524            assert len(cache) <= 3
1525            assert fh in cache.files
1526            assert handles[0] in cache.files
1527
1528        # randomly read from files
1529        for i in range(13):
1530            fh = handles[random.randint(0, 5)]
1531            cache.read(fh, 0, 0)
1532            assert len(cache) <= 3
1533            assert fh in cache.files
1534            assert handles[0] in cache.files
1535
1536        # clear cache: only first file is open
1537        cache.clear()
1538        assert len(cache) == 1
1539        assert handles[0] in cache.files
1540        for i, fh in enumerate(handles):
1541            assert fh.closed == (i > 0)
1542
1543        # open and close all files twice
1544        for fh in handles:
1545            cache.open(fh)
1546            cache.open(fh)
1547        assert len(cache) == 6
1548        for i, fh in enumerate(handles):
1549            assert not fh.closed
1550            assert cache.files[fh] == 2 if i else 3
1551        # close files once
1552        for fh in handles:
1553            cache.close(fh)
1554        assert len(cache) == 6
1555        for i, fh in enumerate(handles):
1556            assert not fh.closed
1557            assert cache.files[fh] == 1 if i else 2
1558        # close files twice
1559        for fh in handles:
1560            cache.close(fh)
1561        assert len(cache) == 3
1562        for i, fh in enumerate(handles):
1563            assert fh.closed == (0 < i < 4)
1564            if not 0 < i < 4:
1565                assert cache.files[fh] == 0 if i else 1
1566
1567        # close all files
1568        cache.clear()
1569        handles[0].close()
1570
1571
1572@pytest.mark.parametrize('bigtiff', [False, True])
1573@pytest.mark.parametrize('byteorder', ['<', '>'])
1574def test_class_tifftag_overwrite(bigtiff, byteorder):
1575    """Test TiffTag.overwrite method."""
1576    data = numpy.ones((16, 16, 3), dtype=byteorder + 'i2')
1577    bt = '_bigtiff' if bigtiff else ''
1578    bo = 'be' if byteorder == '>' else 'le'
1579
1580    with TempFileName(f'class_tifftag_overwrite_{bo}{bt}') as fname:
1581        imwrite(fname, data, bigtiff=bigtiff, photometric=RGB, software='in')
1582
1583        with TiffFile(fname, mode='r+b') as tif:
1584            tags = tif.pages[0].tags
1585            # inline -> inline
1586            tag = tags[305]
1587            t305 = tags[305].overwrite('inl')
1588            assert tag.valueoffset == t305.valueoffset
1589            valueoffset = tag.valueoffset
1590            # xresolution
1591            tag = tags[282]
1592            t282 = tags[282].overwrite((2000, 1000))
1593            assert tag.valueoffset == t282.valueoffset
1594            # sampleformat, int -> uint
1595            tag = tags[339]
1596            t339 = tags[339].overwrite((1, 1, 1))
1597            assert tag.valueoffset == t339.valueoffset
1598
1599        with TiffFile(fname) as tif:
1600            tags = tif.pages[0].tags
1601            tag = tags[305]
1602            assert tag.value == 'inl'
1603            assert tag.count == t305.count
1604            tag = tags[282]
1605            assert tag.value == (2000, 1000)
1606            assert tag.count == t282.count
1607            tag = tags[339]
1608            assert tag.value == (1, 1, 1)
1609            assert tag.count == t339.count
1610
1611        # inline -> separate
1612        with TiffFile(fname, mode='r+b') as tif:
1613            tag = tif.pages[0].tags[305]
1614            t305 = tag.overwrite('separate')
1615            assert tag.valueoffset != t305.valueoffset
1616
1617        # separate at end -> separate longer
1618        with TiffFile(fname, mode='r+b') as tif:
1619            tag = tif.pages[0].tags[305]
1620            assert tag.value == 'separate'
1621            assert tag.valueoffset == t305.valueoffset
1622            t305 = tag.overwrite('separate longer')
1623            assert tag.valueoffset == t305.valueoffset  # overwrite, not append
1624
1625        # separate -> separate shorter
1626        with TiffFile(fname, mode='r+b') as tif:
1627            tag = tif.pages[0].tags[305]
1628            assert tag.value == 'separate longer'
1629            assert tag.valueoffset == t305.valueoffset
1630            t305 = tag.overwrite('separate short')
1631            assert tag.valueoffset == t305.valueoffset
1632
1633        # separate -> separate longer
1634        with TiffFile(fname, mode='r+b') as tif:
1635            tag = tif.pages[0].tags[305]
1636            assert tag.value == 'separate short'
1637            assert tag.valueoffset == t305.valueoffset
1638            filesize = tif.filehandle.size
1639            t305 = tag.overwrite('separate longer')
1640            assert tag.valueoffset != t305.valueoffset
1641            assert t305.valueoffset == filesize  # append to end
1642
1643        # separate -> inline
1644        with TiffFile(fname, mode='r+b') as tif:
1645            tag = tif.pages[0].tags[305]
1646            assert tag.value == 'separate longer'
1647            assert tag.valueoffset == t305.valueoffset
1648            t305 = tag.overwrite('inl')
1649            assert tag.valueoffset != t305.valueoffset
1650            assert t305.valueoffset == valueoffset
1651
1652        # inline - > erase
1653        with TiffFile(fname, mode='r+b') as tif:
1654            tag = tif.pages[0].tags[305]
1655            assert tag.value == 'inl'
1656            assert tag.valueoffset == t305.valueoffset
1657            with pytest.warns(DeprecationWarning):
1658                t305 = tag.overwrite(tif, '')
1659            assert tag.valueoffset == t305.valueoffset
1660
1661        with TiffFile(fname) as tif:
1662            tag = tif.pages[0].tags[305]
1663            assert tag.value == ''
1664            assert tag.valueoffset == t305.valueoffset
1665
1666        if not bigtiff:
1667            assert_valid_tiff(fname)
1668
1669
1670def test_class_tifftags():
1671    """Test TiffTags interface."""
1672    data = random_data(numpy.uint8, (21, 31))
1673
1674    with TempFileName('class_tifftags') as fname:
1675        imwrite(fname, data, description='test', software=False)
1676
1677        with TiffFile(fname) as tif:
1678            tags = tif.pages[0].tags
1679            # assert len(tags) == 14
1680            assert 270 in tags
1681            assert 'ImageDescription' in tags
1682            assert tags[270].value == 'test'
1683            assert tags['ImageDescription'].value == 'test'
1684            assert tags.get(270).value == 'test'
1685            assert tags.get('ImageDescription').value == 'test'
1686            assert tags.get(270, index=0).value == 'test'
1687            assert tags.get('ImageDescription', index=0).value == 'test'
1688            assert tags.get(270, index=1).value.startswith('{')
1689            assert tags.get('ImageDescription', index=1).value.startswith('{')
1690            assert tags.get(270, index=2) is None
1691            assert tags.get('ImageDescription', index=2) is None
1692            assert tags.getall(270)[0].value == 'test'
1693            assert tags.getall(270)[1].value.startswith('{')
1694
1695            assert len(tags.getall(270)) == 2
1696            assert 305 not in tags
1697            assert 'Software' not in tags
1698            assert tags.get(305) is None
1699            assert tags.get('Software') is None
1700            with pytest.raises(KeyError):
1701                tags[305].value
1702            with pytest.raises(KeyError):
1703                tags['Software'].value
1704            assert len(tags.values()) == len(tags.items())
1705            assert len(tags.keys()) == len(tags.items()) - 1
1706            assert set(tags.keys()) == set(i[0] for i in tags.items())
1707            assert list(tags.values()) == [i[1] for i in tags.items()]
1708            assert list(tags.values()) == [t for t in tags]
1709
1710            tag270 = tags[270]
1711            del tags[270]
1712            assert 270 not in tags
1713            assert 'ImageDescription' not in tags
1714            with pytest.raises(KeyError):
1715                del tags[270]
1716            with pytest.raises(KeyError):
1717                del tags['ImageDescription']
1718
1719            tags.add(tag270)
1720            assert 270 in tags
1721            assert 'ImageDescription' in tags
1722            del tags['ImageDescription']
1723            assert 270 not in tags
1724            assert 'ImageDescription' not in tags
1725
1726            tags[270] = tag270
1727            assert 270 in tags
1728            assert 'ImageDescription' in tags
1729
1730            assert 0 not in tags
1731            assert 'None' not in tags
1732            assert None not in tags
1733
1734
1735def test_class_tifftagregistry():
1736    """Test TiffTagRegistry."""
1737    tags = TIFF.TAGS
1738    assert len(tags) == 632
1739    assert tags[11] == 'ProcessingSoftware'
1740    assert tags['ProcessingSoftware'] == 11
1741    assert tags.getall(11) == ['ProcessingSoftware']
1742    assert tags.getall('ProcessingSoftware') == [11]
1743    tags.add(11, 'ProcessingSoftware')
1744    assert len(tags) == 632
1745
1746    # one code with two names
1747    assert 34853 in tags
1748    assert 'GPSTag' in tags
1749    assert 'OlympusSIS2' in tags
1750    assert tags[34853] == 'GPSTag'
1751    assert tags['GPSTag'] == 34853
1752    assert tags['OlympusSIS2'] == 34853
1753    assert tags.getall(34853) == ['GPSTag', 'OlympusSIS2']
1754    assert tags.getall('GPSTag') == [34853]
1755
1756    del tags[34853]
1757    assert len(tags) == 630
1758    assert 34853 not in tags
1759    assert 'GPSTag' not in tags
1760    assert 'OlympusSIS2' not in tags
1761    tags.add(34853, 'GPSTag')
1762    tags.add(34853, 'OlympusSIS2')
1763    assert 34853 in tags
1764    assert 'GPSTag' in tags
1765    assert 'OlympusSIS2' in tags
1766
1767    info = str(tags)
1768    assert "34853, 'GPSTag'" in info
1769    assert "34853, 'OlympusSIS2'" in info
1770
1771    # two codes with same name
1772    assert 37387 in tags
1773    assert 41483 in tags
1774    assert 'FlashEnergy' in tags
1775    assert tags[37387] == 'FlashEnergy'
1776    assert tags[41483] == 'FlashEnergy'
1777    assert tags['FlashEnergy'] == 37387
1778    assert tags.getall('FlashEnergy') == [37387, 41483]
1779    assert tags.getall(37387) == ['FlashEnergy']
1780    assert tags.getall(41483) == ['FlashEnergy']
1781
1782    del tags['FlashEnergy']
1783    assert len(tags) == 630
1784    assert 37387 not in tags
1785    assert 41483 not in tags
1786    assert 'FlashEnergy' not in tags
1787    tags.add(37387, 'FlashEnergy')
1788    tags.add(41483, 'FlashEnergy')
1789    assert 37387 in tags
1790    assert 41483 in tags
1791    assert 'FlashEnergy' in tags
1792
1793    assert "37387, 'FlashEnergy'" in info
1794    assert "41483, 'FlashEnergy'" in info
1795
1796
1797@pytest.mark.parametrize(
1798    'shape, storedshape, dtype, axes, error',
1799    [
1800        # separate and contig
1801        ((32, 32), (1, 2, 1, 32, 32, 2), numpy.uint8, None, ValueError),
1802        # depth
1803        ((32, 32, 32), (1, 1, 32, 32, 32, 1), numpy.uint8, None, OmeXmlError),
1804        # dtype
1805        ((32, 32), (1, 1, 1, 32, 32, 1), numpy.float16, None, OmeXmlError),
1806        # empty
1807        ((0, 0), (1, 1, 1, 0, 0, 1), numpy.uint8, None, OmeXmlError),
1808        # not YX
1809        ((32, 32), (1, 1, 1, 32, 32, 1), numpy.uint8, 'XZ', OmeXmlError),
1810        # unknown axis
1811        ((1, 32, 32), (1, 1, 1, 32, 32, 1), numpy.uint8, 'KYX', OmeXmlError),
1812        # double axis
1813        ((1, 32, 32), (1, 1, 1, 32, 32, 1), numpy.uint8, 'YYX', OmeXmlError),
1814        # more than 5 dimensions
1815        (
1816            (1, 1, 1, 5, 32, 32),
1817            (5, 1, 1, 32, 32, 1),
1818            numpy.uint8,
1819            None,
1820            OmeXmlError,
1821        ),
1822        # more than 6 dimensions
1823        (
1824            (1, 1, 1, 1, 32, 32, 3),
1825            (1, 1, 1, 32, 32, 3),
1826            numpy.uint8,
1827            None,
1828            OmeXmlError,
1829        ),
1830        # more than 8 dimensions
1831        (
1832            (1, 1, 1, 1, 1, 1, 1, 32, 32),
1833            (1, 1, 1, 32, 32, 1),
1834            numpy.uint8,
1835            'ARHETZCYX',
1836            OmeXmlError,
1837        ),
1838        # more than 9 dimensions
1839        (
1840            (1, 1, 1, 1, 1, 1, 1, 32, 32, 3),
1841            (1, 1, 1, 32, 32, 3),
1842            numpy.uint8,
1843            'ARHETZCYXS',
1844            OmeXmlError,
1845        ),
1846        # double axis
1847        ((1, 32, 32), (1, 1, 1, 32, 32, 1), numpy.uint8, 'YYX', OmeXmlError),
1848        # planecount mismatch
1849        ((3, 32, 32), (1, 1, 1, 32, 32, 1), numpy.uint8, 'CYX', ValueError),
1850        # stored shape mismatch
1851        ((3, 32, 32), (1, 2, 1, 32, 32, 1), numpy.uint8, 'SYX', ValueError),
1852        ((32, 32, 3), (1, 1, 1, 32, 32, 2), numpy.uint8, 'YXS', ValueError),
1853        ((3, 32, 32), (1, 3, 1, 31, 31, 1), numpy.uint8, 'SYX', ValueError),
1854        ((32, 32, 3), (1, 1, 1, 31, 31, 3), numpy.uint8, 'YXS', ValueError),
1855        ((32, 32), (1, 1, 1, 32, 31, 1), numpy.uint8, None, ValueError),
1856        # too many modulo dimensions
1857        (
1858            (2, 3, 4, 5, 32, 32),
1859            (60, 1, 1, 32, 32, 1),
1860            numpy.uint8,
1861            'RHEQYX',
1862            OmeXmlError,
1863        ),
1864    ],
1865)
1866def test_class_omexml_fail(shape, storedshape, dtype, axes, error):
1867    """Test OmeXml class failures."""
1868    metadata = {'axes': axes} if axes else {}
1869    ox = OmeXml()
1870    with pytest.raises(error):
1871        ox.addimage(dtype, shape, storedshape, **metadata)
1872
1873
1874@pytest.mark.parametrize(
1875    'axes, autoaxes, shape, storedshape, dimorder',
1876    [
1877        ('YX', 'YX', (32, 32), (1, 1, 1, 32, 32, 1), 'XYCZT'),
1878        ('YXS', 'YXS', (32, 32, 1), (1, 1, 1, 32, 32, 1), 'XYCZT'),
1879        ('SYX', 'SYX', (1, 32, 32), (1, 1, 1, 32, 32, 1), 'XYCZT'),
1880        ('YXS', 'YXS', (32, 32, 3), (1, 1, 1, 32, 32, 3), 'XYCZT'),
1881        ('SYX', 'SYX', (3, 32, 32), (1, 3, 1, 32, 32, 1), 'XYCZT'),
1882        ('CYX', 'CYX', (5, 32, 32), (5, 1, 1, 32, 32, 1), 'XYCZT'),
1883        ('CYXS', 'CYXS', (5, 32, 32, 1), (5, 1, 1, 32, 32, 1), 'XYCZT'),
1884        ('CSYX', 'ZCYX', (5, 1, 32, 32), (5, 1, 1, 32, 32, 1), 'XYCZT'),  # !
1885        ('CYXS', 'CYXS', (5, 32, 32, 3), (5, 1, 1, 32, 32, 3), 'XYCZT'),
1886        ('CSYX', 'CSYX', (5, 3, 32, 32), (5, 3, 1, 32, 32, 1), 'XYCZT'),
1887        ('TZCYX', 'TZCYX', (3, 4, 5, 32, 32), (60, 1, 1, 32, 32, 1), 'XYCZT'),
1888        (
1889            'TZCYXS',
1890            'TZCYXS',
1891            (3, 4, 5, 32, 32, 1),
1892            (60, 1, 1, 32, 32, 1),
1893            'XYCZT',
1894        ),
1895        (
1896            'TZCSYX',
1897            'TZCSYX',
1898            (3, 4, 5, 1, 32, 32),
1899            (60, 1, 1, 32, 32, 1),
1900            'XYCZT',
1901        ),
1902        (
1903            'TZCYXS',
1904            'TZCYXS',
1905            (3, 4, 5, 32, 32, 3),
1906            (60, 1, 1, 32, 32, 3),
1907            'XYCZT',
1908        ),
1909        ('ZTCSYX', '', (3, 4, 5, 3, 32, 32), (60, 3, 1, 32, 32, 1), 'XYCTZ'),
1910    ],
1911)
1912@pytest.mark.parametrize('metadata', ('axes', None))
1913def test_class_omexml(axes, autoaxes, shape, storedshape, dimorder, metadata):
1914    """Test OmeXml class."""
1915    dtype = numpy.uint8
1916    if not metadata and dimorder != 'XYCZT':
1917        pytest.xfail('')
1918    metadata = dict(axes=axes) if metadata else dict()
1919    omexml = OmeXml()
1920    omexml.addimage(dtype, shape, storedshape, **metadata)
1921    if not SKIP_WIN:
1922        assert '\n  ' in str(omexml)
1923    omexml = omexml.tostring()
1924    assert dimorder in omexml
1925    if metadata:
1926        autoaxes = axes
1927    for ax in 'XYCZT':
1928        if ax in autoaxes:
1929            size = shape[autoaxes.index(ax)]
1930        else:
1931            size = 1
1932        if ax == 'C':
1933            size *= storedshape[1] * storedshape[-1]
1934        assert f'Size{ax}="{size}"' in omexml
1935    assert_valid_omexml(omexml)
1936
1937
1938@pytest.mark.parametrize(
1939    'axes, shape, storedshape, sizetzc, dimorder',
1940    [
1941        ('ZAYX', (3, 4, 32, 32), (12, 1, 1, 32, 32, 1), (1, 12, 1), 'XYCZT'),
1942        ('AYX', (3, 32, 32), (3, 1, 1, 32, 32, 1), (3, 1, 1), 'XYCZT'),
1943        ('APYX', (3, 4, 32, 32), (12, 1, 1, 32, 32, 1), (3, 4, 1), 'XYCZT'),
1944        ('TAYX', (3, 4, 32, 32), (12, 1, 1, 32, 32, 1), (12, 1, 1), 'XYCZT'),
1945        (
1946            'CHYXS',
1947            (3, 4, 32, 32, 3),
1948            (12, 1, 1, 32, 32, 3),
1949            (1, 1, 36),
1950            'XYCZT',
1951        ),
1952        (
1953            'CHSYX',
1954            (3, 4, 3, 32, 32),
1955            (12, 3, 1, 32, 32, 1),
1956            (1, 1, 36),
1957            'XYCZT',
1958        ),
1959        (
1960            'APRYX',
1961            (3, 4, 5, 32, 32),
1962            (60, 1, 1, 32, 32, 1),
1963            (3, 4, 5),
1964            'XYCZT',
1965        ),
1966        (
1967            'TAPYX',
1968            (3, 4, 5, 32, 32),
1969            (60, 1, 1, 32, 32, 1),
1970            (12, 5, 1),
1971            'XYCZT',
1972        ),
1973        (
1974            'TZAYX',
1975            (3, 4, 5, 32, 32),
1976            (60, 1, 1, 32, 32, 1),
1977            (3, 20, 1),
1978            'XYCZT',
1979        ),
1980        (
1981            'ZCHYX',
1982            (3, 4, 5, 32, 32),
1983            (60, 1, 1, 32, 32, 1),
1984            (1, 3, 20),
1985            'XYCZT',
1986        ),
1987        (
1988            'EPYX',
1989            (10, 5, 200, 200),
1990            (50, 1, 1, 200, 200, 1),
1991            (10, 5, 1),
1992            'XYCZT',
1993        ),
1994        (
1995            'TQCPZRYX',
1996            (2, 3, 4, 5, 6, 7, 32, 32),
1997            (5040, 1, 1, 32, 32, 1),
1998            (6, 42, 20),
1999            'XYZCT',
2000        ),
2001    ],
2002)
2003def test_class_omexml_modulo(axes, shape, storedshape, sizetzc, dimorder):
2004    """Test OmeXml class with modulo dimensions."""
2005    dtype = numpy.uint8
2006    omexml = OmeXml()
2007    omexml.addimage(dtype, shape, storedshape, axes=axes)
2008    assert '\n  ' in str(omexml)
2009    omexml = omexml.tostring()
2010    assert dimorder in omexml
2011    for ax, size in zip('TZC', sizetzc):
2012        assert f'Size{ax}="{size}"' in omexml
2013    assert_valid_omexml(omexml)
2014
2015
2016def test_class_omexml_attributes():
2017    """Test OmeXml class with attributes and elements."""
2018    from uuid import uuid1  # noqa: delayed import
2019
2020    uuid = str(uuid1())
2021    metadata = dict(
2022        # document
2023        UUID=uuid,
2024        Creator=f'test_tifffile.py {tifffile.__version__}',
2025        # image
2026        axes='ZYXS',
2027        Name='ImageName',
2028        Acquisitiondate='2011-09-16T10:45:48',
2029        Description='Image "Description" < & >\n{test}',
2030        SignificantBits=12,
2031        PhysicalSizeX=1.1,
2032        PhysicalSizeXUnit='nm',
2033        PhysicalSizeY=1.2,
2034        PhysicalSizeYUnit='\xb5m',
2035        PhysicalSizeZ=1.3,
2036        PhysicalSizeZUnit='\xc5',
2037        TimeIncrement=1.4,
2038        TimeIncrementUnit='\xb5s',
2039        Channel=dict(Name='ChannelName'),  # one channel with 3 samples
2040        Plane=dict(PositionZ=[0.0, 2.0, 4.0]),  # 3 Z-planes
2041    )
2042
2043    omexml = OmeXml(**metadata)
2044    omexml.addimage(
2045        numpy.uint16, (3, 32, 32, 3), (3, 1, 1, 32, 32, 3), **metadata
2046    )
2047    xml = omexml.tostring()
2048    assert uuid in xml
2049    assert 'SignificantBits="12"' in xml
2050    assert 'SamplesPerPixel="3" Name="ChannelName"' in xml
2051    assert 'TheC="0" TheZ="2" TheT="0" PositionZ="4.0"' in xml
2052    if SKIP_PYPY:
2053        pytest.xfail('lxml bug?')
2054    assert_valid_omexml(xml)
2055    assert '\n  ' in str(omexml)
2056
2057
2058def test_class_omexml_multiimage():
2059    """Test OmeXml class with multiple images."""
2060    omexml = OmeXml(description='multiimage')
2061    omexml.addimage(
2062        numpy.uint8, (32, 32, 3), (1, 1, 1, 32, 32, 3), name='preview'
2063    )
2064    omexml.addimage(
2065        numpy.float32, (4, 256, 256), (4, 1, 1, 256, 256, 1), name='1'
2066    )
2067    omexml.addimage('bool', (256, 256), (1, 1, 1, 256, 256, 1), name='mask')
2068    assert '\n  ' in str(omexml)
2069    omexml = omexml.tostring()
2070    assert 'TiffData IFD="0" PlaneCount="1"' in omexml
2071    assert 'TiffData IFD="1" PlaneCount="4"' in omexml
2072    assert 'TiffData IFD="5" PlaneCount="1"' in omexml
2073    assert_valid_omexml(omexml)
2074
2075
2076def test_func_xml2dict():
2077    """Test xml2dict function."""
2078    d = xml2dict(
2079        """<?xml version="1.0" ?>
2080    <root attr="attribute">
2081        <int>1</int>
2082        <float>3.14</float>
2083        <bool>True</bool>
2084        <string>Lorem Ipsum</string>
2085    </root>
2086    """
2087    )
2088    assert d['root']['attr'] == 'attribute'
2089    assert d['root']['int'] == 1
2090    assert d['root']['float'] == 3.14
2091    assert d['root']['bool'] is True
2092    assert d['root']['string'] == 'Lorem Ipsum'
2093
2094
2095def test_func_memmap():
2096    """Test memmap function."""
2097    with TempFileName('memmap_new') as fname:
2098        # create new file
2099        im = memmap(
2100            fname,
2101            shape=(32, 16),
2102            dtype=numpy.float32,
2103            bigtiff=True,
2104            compression=False,
2105        )
2106        im[31, 15] = 1.0
2107        im.flush()
2108        assert im.shape == (32, 16)
2109        assert im.dtype == numpy.float32
2110        del im
2111        im = memmap(fname, page=0, mode='r')
2112        assert im[31, 15] == 1.0
2113        del im
2114        im = memmap(fname, series=0, mode='c')
2115        assert im[31, 15] == 1.0
2116        del im
2117        # append to file
2118        im = memmap(
2119            fname,
2120            shape=(3, 64, 64),
2121            dtype=numpy.uint16,
2122            append=True,
2123            photometric=MINISBLACK,
2124        )
2125        im[2, 63, 63] = 1.0
2126        im.flush()
2127        assert im.shape == (3, 64, 64)
2128        assert im.dtype == numpy.uint16
2129        del im
2130        im = memmap(fname, page=3, mode='r')
2131        assert im[63, 63] == 1
2132        del im
2133        im = memmap(fname, series=1, mode='c')
2134        assert im[2, 63, 63] == 1
2135        del im
2136        # can not memory-map compressed array
2137        with pytest.raises(ValueError):
2138            memmap(
2139                fname,
2140                shape=(16, 16),
2141                dtype=numpy.float32,
2142                append=True,
2143                compression=ADOBE_DEFLATE,
2144            )
2145
2146
2147def test_func_memmap_fail():
2148    """Test non-native byteorder can not be memory mapped."""
2149    with TempFileName('memmap_fail') as fname:
2150        with pytest.raises(ValueError):
2151            memmap(
2152                fname,
2153                shape=(16, 16),
2154                dtype=numpy.float32,
2155                byteorder='>' if sys.byteorder == 'little' else '<',
2156            )
2157
2158
2159def test_func_repeat_nd():
2160    """Test repeat_nd function."""
2161    a = repeat_nd([[0, 1, 2], [3, 4, 5], [6, 7, 8]], (2, 3))
2162    assert_array_equal(
2163        a,
2164        [
2165            [0, 0, 0, 1, 1, 1, 2, 2, 2],
2166            [0, 0, 0, 1, 1, 1, 2, 2, 2],
2167            [3, 3, 3, 4, 4, 4, 5, 5, 5],
2168            [3, 3, 3, 4, 4, 4, 5, 5, 5],
2169            [6, 6, 6, 7, 7, 7, 8, 8, 8],
2170            [6, 6, 6, 7, 7, 7, 8, 8, 8],
2171        ],
2172    )
2173
2174
2175def test_func_byteorder_isnative():
2176    """Test byteorder_isnative function."""
2177    assert byteorder_isnative(sys.byteorder)
2178    assert byteorder_isnative('=')
2179    if sys.byteorder == 'little':
2180        assert byteorder_isnative('<')
2181        assert not byteorder_isnative('>')
2182    else:
2183        assert byteorder_isnative('>')
2184        assert not byteorder_isnative('<')
2185
2186
2187def test_func_byteorder_compare():
2188    """Test byteorder_isnative function."""
2189    assert byteorder_compare('<', '<')
2190    assert byteorder_compare('>', '>')
2191    assert byteorder_compare('=', '=')
2192    assert byteorder_compare('|', '|')
2193    assert byteorder_compare('>', '|')
2194    assert byteorder_compare('<', '|')
2195    assert byteorder_compare('|', '>')
2196    assert byteorder_compare('|', '<')
2197    assert byteorder_compare('=', '|')
2198    assert byteorder_compare('|', '=')
2199    if sys.byteorder == 'little':
2200        assert byteorder_compare('<', '=')
2201    else:
2202        assert byteorder_compare('>', '=')
2203
2204
2205def test_func_reshape_nd():
2206    """Test reshape_nd function."""
2207    assert reshape_nd(numpy.empty(0), 2).shape == (1, 0)
2208    assert reshape_nd(numpy.empty(1), 3).shape == (1, 1, 1)
2209    assert reshape_nd(numpy.empty((2, 3)), 3).shape == (1, 2, 3)
2210    assert reshape_nd(numpy.empty((2, 3, 4)), 3).shape == (2, 3, 4)
2211
2212    assert reshape_nd((0,), 2) == (1, 0)
2213    assert reshape_nd((1,), 3) == (1, 1, 1)
2214    assert reshape_nd((2, 3), 3) == (1, 2, 3)
2215    assert reshape_nd((2, 3, 4), 3) == (2, 3, 4)
2216
2217
2218def test_func_apply_colormap():
2219    """Test apply_colormap function."""
2220    image = numpy.arange(256, dtype=numpy.uint8)
2221    colormap = numpy.vstack([image, image, image]).astype(numpy.uint16) * 256
2222    assert_array_equal(apply_colormap(image, colormap)[-1], colormap[:, -1])
2223
2224
2225def test_func_parse_filenames():
2226    """Test parse_filenames function."""
2227    func = parse_filenames
2228
2229    files = ['c1t001.ext', 'c1t002.ext', 'c2t002.ext']  # 'c2t001.ext' missing
2230    # group names
2231    p = r'(?P<a>\d).[!\d](?P<b>\d+)\.ext'
2232    assert func(files[:1], p) == ('ab', (1, 1), [(0, 0)], (1, 1))
2233    assert func(files[:2], p) == ('ab', (1, 2), [(0, 0), (0, 1)], (1, 1))
2234    assert func(files, p) == ('ab', (2, 2), [(0, 0), (0, 1), (1, 1)], (1, 1))
2235    # unknown axes
2236    p = r'(\d)[^\d](\d+)\.ext'
2237    assert func(files[:1], p) == ('QQ', (1, 1), [(0, 0)], (1, 1))
2238    assert func(files[:2], p) == ('QQ', (1, 2), [(0, 0), (0, 1)], (1, 1))
2239    assert func(files, p) == ('QQ', (2, 2), [(0, 0), (0, 1), (1, 1)], (1, 1))
2240    # match axes
2241    p = r'([^\d])(\d)([^\d])(\d+)\.ext'
2242    assert func(files[:1], p) == ('ct', (1, 1), [(0, 0)], (1, 1))
2243    assert func(files[:2], p) == ('ct', (1, 2), [(0, 0), (0, 1)], (1, 1))
2244    assert func(files, p) == ('ct', (2, 2), [(0, 0), (0, 1), (1, 1)], (1, 1))
2245    # misc
2246    files = ['c0t001.ext', 'c0t002.ext', 'c2t002.ext']  # 'c2t001.ext' missing
2247    p = r'([^\d])(\d)[^\d](?P<b>\d+)\.ext'
2248    assert func(files[:1], p) == ('cb', (1, 1), [(0, 0)], (0, 1))
2249    assert func(files[:2], p) == ('cb', (1, 2), [(0, 0), (0, 1)], (0, 1))
2250    assert func(files, p) == ('cb', (3, 2), [(0, 0), (0, 1), (2, 1)], (0, 1))
2251
2252    # BBBC006_v1
2253    files = [
2254        'BBBC006_v1_images_z_00/mcf-z-stacks-03212011_a01_s1_w1a57.tif',
2255        'BBBC006_v1_images_z_00/mcf-z-stacks-03212011_a03_s2_w1419.tif',
2256        'BBBC006_v1_images_z_00/mcf-z-stacks-03212011_p24_s2_w2283.tif',
2257        'BBBC006_v1_images_z_01/mcf-z-stacks-03212011_p24_s2_w11cf.tif',
2258    ]
2259    # don't match directory
2260    p = r'_(?P<p>[a-z])(?P<a>\d+)(?:_(s)(\d))(?:_(w)(\d))'
2261    assert func(files[:1], p) == (
2262        'pasw',
2263        (1, 1, 1, 1),
2264        [(0, 0, 0, 0)],
2265        (97, 1, 1, 1),
2266    )
2267    assert func(files[:2], p) == (
2268        'pasw',
2269        (1, 3, 2, 1),
2270        [(0, 0, 0, 0), (0, 2, 1, 0)],
2271        (97, 1, 1, 1),
2272    )
2273    # match directory
2274    p = r'(?:_(z)_(\d+)).*_(?P<p>[a-z])(?P<a>\d+)(?:_(s)(\d))(?:_(w)(\d))'
2275    assert func(files, p) == (
2276        'zpasw',
2277        (2, 16, 24, 2, 2),
2278        [
2279            (0, 0, 0, 0, 0),
2280            (0, 0, 2, 1, 0),
2281            (0, 15, 23, 1, 1),
2282            (1, 15, 23, 1, 0),
2283        ],
2284        (0, 97, 1, 1, 1),
2285    )
2286    # reorder axes
2287    p = r'(?:_(z)_(\d+)).*_(?P<p>[a-z])(?P<a>\d+)(?:_(s)(\d))(?:_(w)(\d))'
2288    assert func(files, p, axesorder=(2, 0, 1, 3, 4)) == (
2289        'azpsw',
2290        (24, 2, 16, 2, 2),
2291        [
2292            (0, 0, 0, 0, 0),
2293            (2, 0, 0, 1, 0),
2294            (23, 0, 15, 1, 1),
2295            (23, 1, 15, 1, 0),
2296        ],
2297        (1, 0, 97, 1, 1),
2298    )
2299
2300
2301def test_func_reshape_axes():
2302    """Test reshape_axes function."""
2303    assert reshape_axes('YXS', (219, 301, 1), (219, 301, 1)) == 'YXS'
2304    assert reshape_axes('YXS', (219, 301, 3), (219, 301, 3)) == 'YXS'
2305    assert reshape_axes('YXS', (219, 301, 1), (219, 301)) == 'YX'
2306    assert reshape_axes('YXS', (219, 301, 1), (219, 1, 1, 301, 1)) == 'YQQXS'
2307    assert reshape_axes('IYX', (12, 219, 301), (3, 4, 219, 301, 1)) == 'QQYXQ'
2308    assert (
2309        reshape_axes('IYX', (12, 219, 301), (3, 4, 219, 1, 301, 1)) == 'QQYQXQ'
2310    )
2311    assert (
2312        reshape_axes('IYX', (12, 219, 301), (3, 2, 219, 2, 301, 1)) == 'QQQQXQ'
2313    )
2314    with pytest.raises(ValueError):
2315        reshape_axes('IYX', (12, 219, 301), (3, 4, 219, 2, 301, 1))
2316    with pytest.raises(ValueError):
2317        reshape_axes('IYX', (12, 219, 301), (3, 4, 219, 301, 2))
2318
2319
2320def test_func_julian_datetime():
2321    """Test julian_datetime function."""
2322    assert julian_datetime(2451576, 54362783) == (
2323        datetime.datetime(2000, 2, 2, 15, 6, 2, 783)
2324    )
2325
2326
2327def test_func_excel_datetime():
2328    """Test excel_datetime function."""
2329    assert excel_datetime(40237.029999999795) == (
2330        datetime.datetime(2010, 2, 28, 0, 43, 11, 999982)
2331    )
2332
2333
2334def test_func_natural_sorted():
2335    """Test natural_sorted function."""
2336    assert natural_sorted(['f1', 'f2', 'f10']) == ['f1', 'f2', 'f10']
2337
2338
2339def test_func_stripnull():
2340    """Test stripnull function."""
2341    assert stripnull(b'string\x00') == b'string'
2342    assert stripnull('string\x00', null='\0') == 'string'
2343    assert (
2344        stripnull(b'string\x00string\x00\x00', first=False)
2345        == b'string\x00string'
2346    )
2347    assert (
2348        stripnull('string\x00string\x00\x00', null='\0', first=False)
2349        == 'string\x00string'
2350    )
2351
2352
2353def test_func_stripascii():
2354    """Test stripascii function."""
2355    assert stripascii(b'string\x00string\n\x01\x00') == b'string\x00string\n'
2356    assert stripascii(b'\x00') == b''
2357
2358
2359def test_func_sequence():
2360    """Test sequence function."""
2361    assert sequence(1) == (1,)
2362    assert sequence([1]) == [1]
2363
2364
2365def test_func_product():
2366    """Test product function."""
2367    assert product([2 ** 8, 2 ** 30]) == 274877906944
2368    assert product([]) == 1
2369
2370
2371def test_func_squeeze_axes():
2372    """Test squeeze_axes function."""
2373    assert squeeze_axes((5, 1, 2, 1, 1), 'TZYXC') == ((5, 2, 1), 'TYX')
2374    assert squeeze_axes((1,), 'Y') == ((1,), 'Y')
2375    assert squeeze_axes((1,), 'Q') == ((1,), 'Q')
2376    assert squeeze_axes((1, 1), 'PQ') == ((1,), 'Q')
2377
2378
2379def test_func_transpose_axes():
2380    """Test transpose_axes function."""
2381    assert transpose_axes(
2382        numpy.zeros((2, 3, 4, 5)), 'TYXC', asaxes='CTZYX'
2383    ).shape == (5, 2, 1, 3, 4)
2384
2385
2386def test_func_subresolution():
2387    """Test subresolution function."""
2388
2389    class a:
2390        dtype = numpy.uint8
2391        axes = 'QzyxS'
2392        shape = (3, 256, 512, 1024, 4)
2393
2394    class b:
2395        dtype = numpy.uint8
2396        axes = 'QzyxS'
2397        shape = (3, 128, 256, 512, 4)
2398
2399    assert subresolution(a, a) == 0
2400    assert subresolution(a, b) == 1
2401    assert subresolution(a, b, p=2, n=2) == 1
2402    assert subresolution(a, b, p=3) is None
2403    b.shape = (3, 86, 171, 342, 4)
2404    assert subresolution(a, b, p=3) == 1
2405    b.shape = (3, 128, 256, 512, 2)
2406    assert subresolution(a, b) is None
2407    b.shape = (3, 64, 256, 512, 4)
2408    assert subresolution(a, b) is None
2409    b.shape = (3, 128, 64, 512, 4)
2410    assert subresolution(a, b) is None
2411    b.shape = (3, 128, 256, 1024, 4)
2412    assert subresolution(a, b) is None
2413    b.shape = (3, 32, 64, 128, 4)
2414    assert subresolution(a, b) == 3
2415
2416
2417@pytest.mark.skipif(SKIP_BE, reason=REASON)
2418def test_func_unpack_rgb():
2419    """Test unpack_rgb function."""
2420    data = struct.pack('BBBB', 0x21, 0x08, 0xFF, 0xFF)
2421    assert_array_equal(
2422        unpack_rgb(data, '<B', (5, 6, 5), False), [1, 1, 1, 31, 63, 31]
2423    )
2424    assert_array_equal(
2425        unpack_rgb(data, '<B', (5, 6, 5)), [8, 4, 8, 255, 255, 255]
2426    )
2427    assert_array_equal(
2428        unpack_rgb(data, '<B', (5, 5, 5)), [16, 8, 8, 255, 255, 255]
2429    )
2430
2431
2432def test_func_json_description():
2433    """Test json_description function."""
2434    descr = json_description((256, 256, 3), axes='YXS')
2435    assert json.loads(descr) == {'shape': [256, 256, 3], 'axes': 'YXS'}
2436
2437
2438def test_func_json_description_metadata():
2439    """Test json_description_metadata function."""
2440    assert json_description_metadata('shape=(256, 256, 3)') == {
2441        'shape': (256, 256, 3)
2442    }
2443    assert json_description_metadata(
2444        '{"shape": [256, 256, 3], "axes": "YXS"}'
2445    ) == {'shape': [256, 256, 3], 'axes': 'YXS'}
2446
2447
2448def test_func_imagej_shape():
2449    """Test imagej_shape function."""
2450    for k, v in (
2451        ((1, None), (1, 1, 1, 1, 1, 1)),
2452        ((3, None), (1, 1, 1, 1, 3, 1)),
2453        ((4, 3, None), (1, 1, 1, 4, 3, 1)),
2454        ((4, 3, True), (1, 1, 1, 1, 4, 3)),
2455        ((4, 4, None), (1, 1, 1, 4, 4, 1)),
2456        ((4, 4, True), (1, 1, 1, 1, 4, 4)),
2457        ((4, 3, 1, None), (1, 1, 1, 4, 3, 1)),
2458        ((4, 3, 2, None), (1, 1, 4, 3, 2, 1)),
2459        ((4, 3, 3, None), (1, 1, 1, 4, 3, 3)),
2460        ((4, 3, 4, None), (1, 1, 1, 4, 3, 4)),
2461        ((4, 3, 4, True), (1, 1, 1, 4, 3, 4)),
2462        ((4, 3, 4, False), (1, 1, 4, 3, 4, 1)),
2463        ((4, 3, 5, None), (1, 1, 4, 3, 5, 1)),
2464        ((3, 2, 1, 5, 4, None), (1, 3, 2, 1, 5, 4)),
2465        ((3, 2, 1, 4, 5, None), (3, 2, 1, 4, 5, 1)),
2466        ((1, 2, 3, 4, 5, None), (1, 2, 3, 4, 5, 1)),
2467        ((2, 3, 4, 5, 3, None), (1, 2, 3, 4, 5, 3)),
2468        ((2, 3, 4, 5, 3, True), (1, 2, 3, 4, 5, 3)),
2469        ((2, 3, 4, 5, 3, False), (2, 3, 4, 5, 3, 1)),
2470        ((1, 2, 3, 4, 5, 4, None), (1, 2, 3, 4, 5, 4)),
2471        ((6, 5, 4, 3, 2, 1, None), (6, 5, 4, 3, 2, 1)),
2472    ):
2473        assert imagej_shape(k[:-1], k[-1]) == v
2474
2475
2476def test_func_imagej_description():
2477    """Test imagej_description function."""
2478    expected = (
2479        'ImageJ=1.11a\nimages=510\nchannels=2\nslices=5\n'
2480        'frames=51\nhyperstack=true\nmode=grayscale\nloop=false\n'
2481    )
2482    assert imagej_description((51, 5, 2, 196, 171)) == expected
2483    assert imagej_description((51, 5, 2, 196, 171), axes='TZCYX') == expected
2484    expected = (
2485        'ImageJ=1.11a\nimages=2\nslices=2\nhyperstack=true\nmode=grayscale\n'
2486    )
2487    assert imagej_description((1, 2, 1, 196, 171)) == expected
2488    assert imagej_description((2, 196, 171), axes='ZYX') == expected
2489    expected = 'ImageJ=1.11a\nimages=1\nhyperstack=true\nmode=grayscale\n'
2490    assert imagej_description((196, 171)) == expected
2491    assert imagej_description((196, 171), axes='YX') == expected
2492    expected = 'ImageJ=1.11a\nimages=1\nhyperstack=true\n'
2493    assert imagej_description((196, 171, 3)) == expected
2494    assert imagej_description((196, 171, 3), axes='YXS') == expected
2495
2496    with pytest.raises(ValueError):
2497        imagej_description((196, 171, 3), axes='TYXS')
2498    with pytest.raises(ValueError):
2499        imagej_description((196, 171, 2), axes='TYXS')
2500    with pytest.raises(ValueError):
2501        imagej_description((3, 196, 171, 3), axes='ZTYX')
2502
2503
2504def test_func_imagej_description_metadata():
2505    """Test imagej_description_metadata function."""
2506    imagej_str = (
2507        'ImageJ=1.11a\nimages=510\nchannels=2\nslices=5\n'
2508        'frames=51\nhyperstack=true\nmode=grayscale\nloop=false\n'
2509    )
2510    imagej_dict = {
2511        'ImageJ': '1.11a',
2512        'images': 510,
2513        'channels': 2,
2514        'slices': 5,
2515        'frames': 51,
2516        'hyperstack': True,
2517        'mode': 'grayscale',
2518        'loop': False,
2519    }
2520    assert imagej_description_metadata(imagej_str) == imagej_dict
2521
2522
2523def test_func_pilatus_header_metadata():
2524    """Test pilatus_description_metadata function."""
2525    header = """
2526        # Detector: PILATUS 300K, 3-0101
2527        # 2011-07-22T17:33:22.529
2528        # Pixel_size 172e-6 m x 172e-6 m
2529        # Silicon sensor, thickness 0.000320 m
2530        # Exposure_time 0.0970000 s
2531        # Exposure_period 0.1000000 s
2532        # Tau = 383.8e-09 s
2533        # Count_cutoff 126367 counts
2534        # Threshold_setting: not set
2535        # Gain_setting: high gain (vrf = -0.150)
2536        # N_excluded_pixels = 19
2537        # Excluded_pixels: badpix_mask.tif
2538        # Flat_field: (nil)
2539        # Trim_file: p300k0101_E8048_T4024_vrf_m0p15.bin
2540        #  Beam_xy (243.12, 309.12) pixels
2541        # Image_path: /ramdisk/
2542            Invalid
2543        # Unknown 1 2 3 4 5""".strip().replace(
2544        '            ', ''
2545    )
2546    attr = pilatus_description_metadata(header)
2547    assert attr['Detector'] == 'PILATUS 300K 3-0101'
2548    assert attr['Pixel_size'] == (0.000172, 0.000172)
2549    assert attr['Silicon'] == 0.000320
2550    # self.assertEqual(attr['Threshold_setting'], float('nan'))
2551    assert attr['Beam_xy'] == (243.12, 309.12)
2552    assert attr['Unknown'] == '1 2 3 4 5'
2553
2554
2555def test_func_matlabstr2py():
2556    """Test matlabstr2py function."""
2557    assert matlabstr2py('1') == 1
2558    assert matlabstr2py(
2559        "['x y z' true false; 1 2.0 -3e4; Inf Inf @class;[1;2;3][1 2] 3]"
2560    ) == [
2561        ['x y z', True, False],
2562        [1, 2.0, -30000.0],
2563        [float('inf'), float('inf'), '@class'],
2564        [[[1], [2], [3]], [1, 2], 3],
2565    ]
2566
2567    assert matlabstr2py(
2568        "SI.hChannels.channelType = {'stripe' 'stripe'}\n"
2569        "SI.hChannels.channelsActive = 2"
2570    )['SI.hChannels.channelType'] == ['stripe', 'stripe']
2571
2572    p = matlabstr2py(
2573        """
2574        true = true
2575        false = false
2576        True = True
2577        False = False
2578        Int = 10
2579        Float = 3.14
2580        Float.E = 314.0e-02
2581        Float.NaN = nan
2582        Float.Inf = inf
2583        String = 'string'
2584        String.Empty = ''
2585        String.Array = ['ab']
2586        Array = [1 2]
2587        Array.2D = [1;2]
2588        Array.Empty = [[]]
2589        Transform = [1 0 0;0 1 0;0 0 1]
2590        Zeros = zeros(1,1)
2591        Zeros.Empty = zeros(1,0)
2592        Ones = ones(1,0)
2593        Filename = C:\\Users\\scanimage.cfg
2594        Cell = {'' ''}
2595        Class = @class
2596        StructObject = <nonscalar struct/object>
2597        Unknown = unknown
2598
2599        % Comment
2600        """
2601    )
2602    assert p['Array'] == [1, 2]
2603    assert p['Array.2D'] == [[1], [2]]
2604    assert p['Array.Empty'] == []
2605    assert p['Cell'] == ['', '']
2606    assert p['Class'] == '@class'
2607    assert p['False'] is False
2608    assert p['Filename'] == 'C:\\Users\\scanimage.cfg'
2609    assert p['Float'] == 3.14
2610    assert p['Float.E'] == 3.14
2611    assert p['Float.Inf'] == float('inf')
2612    # self.assertEqual(p['Float.NaN'], float('nan'))  # can't compare NaN
2613    assert p['Int'] == 10
2614    assert p['StructObject'] == '<nonscalar struct/object>'
2615    assert p['Ones'] == [[]]
2616    assert p['String'] == 'string'
2617    assert p['String.Array'] == 'ab'
2618    assert p['String.Empty'] == ''
2619    assert p['Transform'] == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
2620    assert p['True'] is True
2621    assert p['Unknown'] == 'unknown'
2622    assert p['Zeros'] == [[0.0]]
2623    assert p['Zeros.Empty'] == [[]]
2624    assert p['false'] is False
2625    assert p['true'] is True
2626
2627
2628def test_func_hexdump():
2629    """Test hexdump function."""
2630    # test hexdump function
2631    data = binascii.unhexlify(
2632        '49492a00080000000e00fe0004000100'
2633        '00000000000000010400010000000001'
2634        '00000101040001000000000100000201'
2635        '03000100000020000000030103000100'
2636    )
2637    # one line
2638    assert hexdump(data[:16]) == (
2639        '49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 II*.............'
2640    )
2641    # height=1
2642    assert hexdump(data, width=64, height=1) == (
2643        '49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 II*.............'
2644    )
2645    # all lines
2646    assert hexdump(data) == (
2647        '00: 49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 '
2648        'II*.............\n'
2649        '10: 00 00 00 00 00 00 00 01 04 00 01 00 00 00 00 01 '
2650        '................\n'
2651        '20: 00 00 01 01 04 00 01 00 00 00 00 01 00 00 02 01 '
2652        '................\n'
2653        '30: 03 00 01 00 00 00 20 00 00 00 03 01 03 00 01 00 '
2654        '...... .........'
2655    )
2656    # skip center
2657    assert hexdump(data, height=3, snipat=0.5) == (
2658        '00: 49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 '
2659        'II*.............\n'
2660        '...\n'
2661        '30: 03 00 01 00 00 00 20 00 00 00 03 01 03 00 01 00 '
2662        '...... .........'
2663    )
2664    # skip start
2665    assert hexdump(data, height=3, snipat=0) == (
2666        '10: 00 00 00 00 00 00 00 01 04 00 01 00 00 00 00 01 '
2667        '................\n'
2668        '20: 00 00 01 01 04 00 01 00 00 00 00 01 00 00 02 01 '
2669        '................\n'
2670        '30: 03 00 01 00 00 00 20 00 00 00 03 01 03 00 01 00 '
2671        '...... .........'
2672    )
2673    # skip end
2674    assert hexdump(data, height=3, snipat=1) == (
2675        '00: 49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 '
2676        'II*.............\n'
2677        '10: 00 00 00 00 00 00 00 01 04 00 01 00 00 00 00 01 '
2678        '................\n'
2679        '20: 00 00 01 01 04 00 01 00 00 00 00 01 00 00 02 01 '
2680        '................'
2681    )
2682
2683
2684def test_func_asbool():
2685    """Test asbool function."""
2686    for true in ('TRUE', ' True ', 'true '):
2687        assert asbool(true)
2688        assert asbool(true.encode())
2689    for false in ('FALSE', ' False ', 'false '):
2690        assert not asbool(false)
2691        assert not asbool(false.encode())
2692    assert asbool('ON', ['on'], ['off'])
2693    assert asbool('ON', 'on', 'off')
2694    with pytest.raises(TypeError):
2695        assert asbool('Yes')
2696    with pytest.raises(TypeError):
2697        assert asbool('True', ['on'], ['off'])
2698
2699
2700def test_func_snipstr():
2701    """Test snipstr function."""
2702    # cut middle
2703    assert snipstr('abc', 3, ellipsis='...') == 'abc'
2704    assert snipstr('abc', 3, ellipsis='....') == 'abc'
2705    assert snipstr('abcdefg', 4, ellipsis='') == 'abcd'
2706    assert snipstr('abcdefg', 4, ellipsis=None) == 'abc…'
2707    assert snipstr(b'abcdefg', 4, ellipsis=None) == b'a...'
2708    assert snipstr('abcdefghijklmnop', 8, ellipsis=None) == 'abcd…nop'
2709    assert snipstr(b'abcdefghijklmnop', 8, ellipsis=None) == b'abc...op'
2710    assert snipstr('abcdefghijklmnop', 9, ellipsis=None) == 'abcd…mnop'
2711    assert snipstr(b'abcdefghijklmnop', 9, ellipsis=None) == b'abc...nop'
2712    assert snipstr('abcdefghijklmnop', 8, ellipsis='..') == 'abc..nop'
2713    assert snipstr('abcdefghijklmnop', 8, ellipsis='....') == 'ab....op'
2714    assert snipstr('abcdefghijklmnop', 8, ellipsis='......') == 'ab......'
2715    # cut right
2716    assert snipstr('abc', 3, snipat=1, ellipsis='...') == 'abc'
2717    assert snipstr('abc', 3, snipat=1, ellipsis='....') == 'abc'
2718    assert snipstr('abcdefg', 4, snipat=1, ellipsis='') == 'abcd'
2719    assert snipstr('abcdefg', 4, snipat=1, ellipsis=None) == 'abc…'
2720    assert snipstr(b'abcdefg', 4, snipat=1, ellipsis=None) == b'a...'
2721    assert (
2722        snipstr('abcdefghijklmnop', 8, snipat=1, ellipsis=None) == 'abcdefg…'
2723    )
2724    assert (
2725        snipstr(b'abcdefghijklmnop', 8, snipat=1, ellipsis=None) == b'abcde...'
2726    )
2727    assert (
2728        snipstr('abcdefghijklmnop', 9, snipat=1, ellipsis=None) == 'abcdefgh…'
2729    )
2730    assert (
2731        snipstr(b'abcdefghijklmnop', 9, snipat=1, ellipsis=None)
2732        == b'abcdef...'
2733    )
2734    assert (
2735        snipstr('abcdefghijklmnop', 8, snipat=1, ellipsis='..') == 'abcdef..'
2736    )
2737    assert (
2738        snipstr('abcdefghijklmnop', 8, snipat=1, ellipsis='....') == 'abcd....'
2739    )
2740    assert (
2741        snipstr('abcdefghijklmnop', 8, snipat=1, ellipsis='......')
2742        == 'ab......'
2743    )
2744    # cut left
2745    assert snipstr('abc', 3, snipat=0, ellipsis='...') == 'abc'
2746    assert snipstr('abc', 3, snipat=0, ellipsis='....') == 'abc'
2747    assert snipstr('abcdefg', 4, snipat=0, ellipsis='') == 'defg'
2748    assert snipstr('abcdefg', 4, snipat=0, ellipsis=None) == '…efg'
2749    assert snipstr(b'abcdefg', 4, snipat=0, ellipsis=None) == b'...g'
2750    assert (
2751        snipstr('abcdefghijklmnop', 8, snipat=0, ellipsis=None) == '…jklmnop'
2752    )
2753    assert (
2754        snipstr(b'abcdefghijklmnop', 8, snipat=0, ellipsis=None) == b'...lmnop'
2755    )
2756    assert (
2757        snipstr('abcdefghijklmnop', 9, snipat=0, ellipsis=None) == '…ijklmnop'
2758    )
2759    assert (
2760        snipstr(b'abcdefghijklmnop', 9, snipat=0, ellipsis=None)
2761        == b'...klmnop'
2762    )
2763    assert (
2764        snipstr('abcdefghijklmnop', 8, snipat=0, ellipsis='..') == '..klmnop'
2765    )
2766    assert (
2767        snipstr('abcdefghijklmnop', 8, snipat=0, ellipsis='....') == '....mnop'
2768    )
2769    assert (
2770        snipstr('abcdefghijklmnop', 8, snipat=0, ellipsis='......')
2771        == '......op'
2772    )
2773
2774
2775def test_func_pformat_printable_bytes():
2776    """Test pformat function with printable bytes."""
2777    value = (
2778        b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST'
2779        b'UVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
2780    )
2781
2782    assert pformat(value, height=1, width=60) == (
2783        '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX'
2784    )
2785
2786    assert pformat(value, height=8, width=60) == (
2787        r'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'
2788        r""""#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
2789    )
2790
2791
2792def test_func_pformat_printable_unicode():
2793    """Test pformat function with printable unicode."""
2794    value = (
2795        '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST'
2796        'UVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
2797    )
2798
2799    assert pformat(value, height=1, width=60) == (
2800        '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX'
2801    )
2802
2803    assert pformat(value, height=8, width=60) == (
2804        r'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!'
2805        r""""#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
2806    )
2807
2808
2809def test_func_pformat_hexdump():
2810    """Test pformat function with unprintable bytes."""
2811    value = binascii.unhexlify(
2812        '49492a00080000000e00fe0004000100'
2813        '00000000000000010400010000000001'
2814        '00000101040001000000000100000201'
2815        '03000100000020000000030103000100'
2816    )
2817
2818    assert pformat(value, height=1, width=60) == (
2819        '49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 II*............'
2820    )
2821
2822    assert (
2823        pformat(value, height=8, width=70)
2824        == """
282500: 49 49 2a 00 08 00 00 00 0e 00 fe 00 04 00 01 00 II*.............
282610: 00 00 00 00 00 00 00 01 04 00 01 00 00 00 00 01 ................
282720: 00 00 01 01 04 00 01 00 00 00 00 01 00 00 02 01 ................
282830: 03 00 01 00 00 00 20 00 00 00 03 01 03 00 01 00 ...... .........
2829""".strip()
2830    )
2831
2832
2833def test_func_pformat_dict():
2834    """Test pformat function with dict."""
2835    value = {
2836        'GTCitationGeoKey': 'WGS 84 / UTM zone 29N',
2837        'GTModelTypeGeoKey': 1,
2838        'GTRasterTypeGeoKey': 1,
2839        'KeyDirectoryVersion': 1,
2840        'KeyRevision': 1,
2841        'KeyRevisionMinor': 2,
2842        'ModelTransformation': numpy.array(
2843            [
2844                [6.00000e01, 0.00000e00, 0.00000e00, 6.00000e05],
2845                [0.00000e00, -6.00000e01, 0.00000e00, 5.90004e06],
2846                [0.00000e00, 0.00000e00, 0.00000e00, 0.00000e00],
2847                [0.00000e00, 0.00000e00, 0.00000e00, 1.00000e00],
2848            ]
2849        ),
2850        'PCSCitationGeoKey': 'WGS 84 / UTM zone 29N',
2851        'ProjectedCSTypeGeoKey': 32629,
2852    }
2853
2854    assert pformat(value, height=1, width=60) == (
2855        "{'GTCitationGeoKey': 'WGS 84 / UTM zone 29N', 'GTModelTypeGe"
2856    )
2857
2858    assert pformat(value, height=8, width=60) == (
2859        """{'GTCitationGeoKey': 'WGS 84 / UTM zone 29N',
2860 'GTModelTypeGeoKey': 1,
2861 'GTRasterTypeGeoKey': 1,
2862 'KeyDirectoryVersion': 1,
2863...
2864       [      0.,       0.,       0.,       0.],
2865       [      0.,       0.,       0.,       1.]]),
2866 'PCSCitationGeoKey': 'WGS 84 / UTM zone 29N',
2867 'ProjectedCSTypeGeoKey': 32629}"""
2868    )
2869
2870
2871def test_func_pformat_list():
2872    """Test pformat function with list."""
2873    value = (
2874        60.0,
2875        0.0,
2876        0.0,
2877        600000.0,
2878        0.0,
2879        -60.0,
2880        0.0,
2881        5900040.0,
2882        60.0,
2883        0.0,
2884        0.0,
2885        600000.0,
2886        0.0,
2887        -60.0,
2888        0.0,
2889        5900040.0,
2890    )
2891
2892    assert pformat(value, height=1, width=60) == (
2893        '(60.0, 0.0, 0.0, 600000.0, 0.0, -60.0, 0.0, 5900040.0, 60.0,'
2894    )
2895
2896    assert pformat(value, height=8, width=60) == (
2897        '(60.0, 0.0, 0.0, 600000.0, 0.0, -60.0, 0.0, 5900040.0, 60.0,\n'
2898        ' 0.0, 0.0, 600000.0, 0.0, -60.0, 0.0, 5900040.0)'
2899    )
2900
2901
2902def test_func_pformat_numpy():
2903    """Test pformat function with numpy array."""
2904    value = numpy.array(
2905        (
2906            60.0,
2907            0.0,
2908            0.0,
2909            600000.0,
2910            0.0,
2911            -60.0,
2912            0.0,
2913            5900040.0,
2914            60.0,
2915            0.0,
2916            0.0,
2917            600000.0,
2918            0.0,
2919            -60.0,
2920            0.0,
2921            5900040.0,
2922        )
2923    )
2924
2925    assert pformat(value, height=1, width=60) == (
2926        'array([ 60., 0., 0., 600000., 0., -60., 0., 5900040., 60., 0'
2927    )
2928
2929    assert pformat(value, height=8, width=60) == (
2930        """array([     60.,       0.,       0.,  600000.,       0.,
2931           -60.,       0., 5900040.,      60.,       0.,
2932             0.,  600000.,       0.,     -60.,       0.,
2933       5900040.])"""
2934    )
2935
2936
2937@pytest.mark.skipif(SKIP_WIN, reason='not reliable on Linux')
2938def test_func_pformat_xml():
2939    """Test pformat function with XML."""
2940    value = """<?xml version="1.0" encoding="ISO-8859-1" ?>
2941<Dimap_Document name="band2.dim">
2942  <Metadata_Id>
2943    <METADATA_FORMAT version="2.12.1">DIMAP</METADATA_FORMAT>
2944    <METADATA_PROFILE>BEAM-DATAMODEL-V1</METADATA_PROFILE>
2945  </Metadata_Id>
2946  <Image_Interpretation>
2947    <Spectral_Band_Info>
2948      <BAND_INDEX>0</BAND_INDEX>
2949    </Spectral_Band_Info>
2950  </Image_Interpretation>
2951</Dimap_Document>"""
2952
2953    assert pformat(value, height=1, width=60) == (
2954        '<?xml version="1.0" encoding="ISO-8859-1" ?> <Dimap_Document'
2955    )
2956
2957    assert pformat(value, height=8, width=60) == (
2958        """<?xml version='1.0' encoding='ISO-8859-1'?>
2959<Dimap_Document name="band2.dim">
2960 <Metadata_Id>
2961  <METADATA_FORMAT version="2.12.1">DIMAP</METADATA_FORMAT>
2962...
2963   <BAND_INDEX>0</BAND_INDEX>
2964  </Spectral_Band_Info>
2965 </Image_Interpretation>
2966</Dimap_Document>"""
2967    )
2968
2969
2970@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
2971def test_func_lsm2bin():
2972    """Test lsm2bin function."""
2973    # Convert LSM to BIN
2974    fname = private_file(
2975        'lsm/Twoareas_Zstacks54slices_3umintervals_5cycles.lsm'
2976    )
2977    # fname = private_file(
2978    #     'LSM/fish01-wt-t01-10_ForTest-20zplanes10timepoints.lsm')
2979    lsm2bin(fname, '', verbose=True)
2980
2981
2982def test_func_tiffcomment():
2983    """Test tiffcomment function."""
2984    data = random_data(numpy.uint8, (33, 31, 3))
2985    with TempFileName('func_tiffcomment') as fname:
2986        comment = 'A comment'
2987        imwrite(
2988            fname, data, photometric=RGB, description=comment, metadata=None
2989        )
2990        assert comment == tiffcomment(fname)
2991        comment = 'changed comment'
2992        tiffcomment(fname, comment)
2993        assert comment == tiffcomment(fname)
2994        assert_valid_tiff(fname)
2995
2996
2997def test_func_create_output():
2998    """Test create_output function."""
2999    shape = (16, 17)
3000    dtype = numpy.uint16
3001    # None
3002    a = create_output(None, shape, dtype)
3003    assert_array_equal(a, numpy.zeros(shape, dtype))
3004    # existing array
3005    b = create_output(a, a.shape, a.dtype)
3006    assert a is b.base
3007    # 'memmap'
3008    a = create_output('memmap', shape, dtype)
3009    assert isinstance(a, numpy.core.memmap)
3010    del a
3011    # 'memmap:tempdir'
3012    a = create_output(f'memmap:{os.path.abspath(TEMP_DIR)}', shape, dtype)
3013    assert isinstance(a, numpy.core.memmap)
3014    del a
3015    # filename
3016    with TempFileName('nopages') as fname:
3017        a = create_output(fname, shape, dtype)
3018        del a
3019
3020
3021@pytest.mark.parametrize('key', [None, 0, 3, 'series'])
3022@pytest.mark.parametrize('out', [None, 'empty', 'memmap', 'dir', 'name'])
3023def test_func_create_output_asarray(out, key):
3024    """Test create_output function in context of asarray."""
3025    data = random_data(numpy.uint16, (5, 219, 301))
3026
3027    with TempFileName(f'out_{key}_{out}') as fname:
3028        imwrite(fname, data)
3029        # assert file
3030        with TiffFile(fname) as tif:
3031            tif.pages.useframes = True
3032            tif.pages._load()
3033
3034            if key is None:
3035                # default
3036                obj = tif
3037                dat = data
3038            elif key == 'series':
3039                # series
3040                obj = tif.series[0]
3041                dat = data
3042            else:
3043                # single page/frame
3044                obj = tif.pages[key]
3045                dat = data[key]
3046                if key == 0:
3047                    assert isinstance(obj, TiffPage)
3048                else:
3049                    assert isinstance(obj, TiffFrame)
3050
3051            if out is None:
3052                # new array
3053                image = obj.asarray(out=None)
3054                assert_array_equal(dat, image)
3055                del image
3056            elif out == 'empty':
3057                # existing array
3058                image = numpy.empty_like(dat)
3059                obj.asarray(out=image)
3060                assert_array_equal(dat, image)
3061                del image
3062            elif out == 'memmap':
3063                # memmap in temp dir
3064                image = obj.asarray(out='memmap')
3065                assert isinstance(image, numpy.core.memmap)
3066                assert_array_equal(dat, image)
3067                del image
3068            elif out == 'dir':
3069                # memmap in specified dir
3070                tempdir = os.path.dirname(fname)
3071                image = obj.asarray(out=f'memmap:{tempdir}')
3072                assert isinstance(image, numpy.core.memmap)
3073                assert_array_equal(dat, image)
3074                del image
3075            elif out == 'name':
3076                # memmap in specified file
3077                with TempFileName(
3078                    f'out_{key}_{out}', ext='.memmap'
3079                ) as fileout:
3080                    image = obj.asarray(out=fileout)
3081                    assert isinstance(image, numpy.core.memmap)
3082                    assert_array_equal(dat, image)
3083                    del image
3084
3085
3086###############################################################################
3087
3088# Test FileHandle class
3089
3090FILEHANDLE_NAME = public_file('tifffile/test_FileHandle.bin')
3091FILEHANDLE_SIZE = 7937381
3092FILEHANDLE_OFFSET = 333
3093FILEHANDLE_LENGTH = 7937381 - 666
3094
3095
3096@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3097def create_filehandle_file():
3098    """Write test_FileHandle.bin file."""
3099    # array start 999
3100    # array end 1254
3101    # recarray start 2253
3102    # recarray end 6078
3103    # tiff start 7077
3104    # tiff end 12821
3105    # mm offset = 13820
3106    # mm size = 7936382
3107    with open(FILEHANDLE_NAME, 'wb') as fh:
3108        # buffer
3109        numpy.ones(999, dtype=numpy.uint8).tofile(fh)
3110        # array
3111        print('array start', fh.tell())
3112        numpy.arange(255, dtype=numpy.uint8).tofile(fh)
3113        print('array end', fh.tell())
3114        # buffer
3115        numpy.ones(999, dtype=numpy.uint8).tofile(fh)
3116        # recarray
3117        print('recarray start', fh.tell())
3118        a = numpy.recarray(
3119            (255, 3), dtype=[('x', numpy.float32), ('y', numpy.uint8)]
3120        )
3121        for i in range(3):
3122            a[:, i].x = numpy.arange(255, dtype=numpy.float32)
3123            a[:, i].y = numpy.arange(255, dtype=numpy.uint8)
3124        a.tofile(fh)
3125        print('recarray end', fh.tell())
3126        # buffer
3127        numpy.ones(999, dtype=numpy.uint8).tofile(fh)
3128        # tiff
3129        print('tiff start', fh.tell())
3130        with open('data/public/tifffile/generic_series.tif', 'rb') as tif:
3131            fh.write(tif.read())
3132        print('tiff end', fh.tell())
3133        # buffer
3134        numpy.ones(999, dtype=numpy.uint8).tofile(fh)
3135        # micromanager
3136        print('micromanager start', fh.tell())
3137        with open('data/public/tifffile/micromanager.tif', 'rb') as tif:
3138            fh.write(tif.read())
3139        print('micromanager end', fh.tell())
3140        # buffer
3141        numpy.ones(999, dtype=numpy.uint8).tofile(fh)
3142
3143
3144def assert_filehandle(fh, offset=0):
3145    """Assert filehandle can read test_FileHandle.bin."""
3146    size = FILEHANDLE_SIZE - 2 * offset
3147    pad = 999 - offset
3148    assert fh.size == size
3149    assert fh.tell() == 0
3150    assert fh.read(4) == b'\x01\x01\x01\x01'
3151    fh.seek(pad - 4)
3152    assert fh.tell() == pad - 4
3153    assert fh.read(4) == b'\x01\x01\x01\x01'
3154    fh.seek(-4, whence=1)
3155    assert fh.tell() == pad - 4
3156    assert fh.read(4) == b'\x01\x01\x01\x01'
3157    fh.seek(-pad, whence=2)
3158    assert fh.tell() == size - pad
3159    assert fh.read(4) == b'\x01\x01\x01\x01'
3160    # assert array
3161    fh.seek(pad, whence=0)
3162    assert fh.tell() == pad
3163    assert_array_equal(
3164        fh.read_array(numpy.uint8, 255), numpy.arange(255, dtype=numpy.uint8)
3165    )
3166    # assert records
3167    fh.seek(999, whence=1)
3168    assert fh.tell() == 2253 - offset
3169    records = fh.read_record(
3170        [('x', numpy.float32), ('y', numpy.uint8)], (255, 3)
3171    )
3172    assert_array_equal(records.y[:, 0], range(255))
3173    assert_array_equal(records.x, records.y)
3174    # assert memmap
3175    if fh.is_file:
3176        assert_array_equal(
3177            fh.memmap_array(numpy.uint8, 255, pad),
3178            numpy.arange(255, dtype=numpy.uint8),
3179        )
3180
3181
3182@pytest.mark.skipif(SKIP_HTTP, reason=REASON)
3183def test_filehandle_seekable():
3184    """Test FileHandle must be seekable."""
3185    from urllib.request import HTTPHandler, build_opener
3186
3187    opener = build_opener(HTTPHandler())
3188    opener.addheaders = [('User-Agent', 'test_tifffile.py')]
3189    try:
3190        fh = opener.open(URL + 'data/test_http.tif')
3191    except OSError:
3192        pytest.skip(URL + 'data/test_http.tif')
3193
3194    with pytest.raises(ValueError):
3195        FileHandle(fh)
3196
3197
3198def test_filehandle_write_bytesio():
3199    """Test write to FileHandle from BytesIO."""
3200    value = b'123456789'
3201    buf = BytesIO()
3202    with FileHandle(buf) as fh:
3203        fh.write(value)
3204    buf.seek(0)
3205    assert buf.read() == value
3206
3207
3208def test_filehandle_write_bytesio_offset():
3209    """Test write to FileHandle from BytesIO with offset."""
3210    pad = b'abcd'
3211    value = b'123456789'
3212    buf = BytesIO()
3213    buf.write(pad)
3214    with FileHandle(buf) as fh:
3215        fh.write(value)
3216    buf.write(pad)
3217    # assert buffer
3218    buf.seek(len(pad))
3219    assert buf.read(len(value)) == value
3220    buf.seek(2)
3221    with FileHandle(buf, offset=len(pad), size=len(value)) as fh:
3222        assert fh.read(len(value)) == value
3223
3224
3225@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3226def test_filehandle_filename():
3227    """Test FileHandle from filename."""
3228    with FileHandle(FILEHANDLE_NAME) as fh:
3229        assert fh.name == 'test_FileHandle.bin'
3230        assert fh.is_file
3231        assert_filehandle(fh)
3232
3233
3234@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3235def test_filehandle_filename_offset():
3236    """Test FileHandle from filename with offset."""
3237    with FileHandle(
3238        FILEHANDLE_NAME, offset=FILEHANDLE_OFFSET, size=FILEHANDLE_LENGTH
3239    ) as fh:
3240        assert fh.name == 'test_FileHandle.bin'
3241        assert fh.is_file
3242        assert_filehandle(fh, FILEHANDLE_OFFSET)
3243
3244
3245@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3246def test_filehandle_bytesio():
3247    """Test FileHandle from BytesIO."""
3248    with open(FILEHANDLE_NAME, 'rb') as fh:
3249        stream = BytesIO(fh.read())
3250    with FileHandle(stream) as fh:
3251        assert fh.name == 'Unnamed binary stream'
3252        assert not fh.is_file
3253        assert_filehandle(fh)
3254
3255
3256@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3257def test_filehandle_bytesio_offset():
3258    """Test FileHandle from BytesIO with offset."""
3259    with open(FILEHANDLE_NAME, 'rb') as fh:
3260        stream = BytesIO(fh.read())
3261    with FileHandle(
3262        stream, offset=FILEHANDLE_OFFSET, size=FILEHANDLE_LENGTH
3263    ) as fh:
3264        assert fh.name == 'Unnamed binary stream'
3265        assert not fh.is_file
3266        assert_filehandle(fh, offset=FILEHANDLE_OFFSET)
3267
3268
3269@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3270def test_filehandle_openfile():
3271    """Test FileHandle from open file."""
3272    with open(FILEHANDLE_NAME, 'rb') as fhandle:
3273        with FileHandle(fhandle) as fh:
3274            assert fh.name == 'test_FileHandle.bin'
3275            assert fh.is_file
3276            assert_filehandle(fh)
3277        assert not fhandle.closed
3278
3279
3280@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3281def test_filehandle_openfile_offset():
3282    """Test FileHandle from open file with offset."""
3283    with open(FILEHANDLE_NAME, 'rb') as fhandle:
3284        with FileHandle(
3285            fhandle, offset=FILEHANDLE_OFFSET, size=FILEHANDLE_LENGTH
3286        ) as fh:
3287            assert fh.name == 'test_FileHandle.bin'
3288            assert fh.is_file
3289            assert_filehandle(fh, offset=FILEHANDLE_OFFSET)
3290        assert not fhandle.closed
3291
3292
3293@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3294def test_filehandle_filehandle():
3295    """Test FileHandle from other FileHandle."""
3296    with FileHandle(FILEHANDLE_NAME, 'rb') as fhandle:
3297        with FileHandle(fhandle) as fh:
3298            assert fh.name == 'test_FileHandle.bin'
3299            assert fh.is_file
3300            assert_filehandle(fh)
3301        assert not fhandle.closed
3302
3303
3304@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3305def test_filehandle_offset():
3306    """Test FileHandle from other FileHandle with offset."""
3307    with FileHandle(FILEHANDLE_NAME, 'rb') as fhandle:
3308        with FileHandle(
3309            fhandle, offset=FILEHANDLE_OFFSET, size=FILEHANDLE_LENGTH
3310        ) as fh:
3311            assert fh.name == 'test_FileHandle@333.bin'
3312            assert fh.is_file
3313            assert_filehandle(fh, offset=FILEHANDLE_OFFSET)
3314        assert not fhandle.closed
3315
3316
3317@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3318def test_filehandle_reopen():
3319    """Test FileHandle close and open."""
3320    try:
3321        fh = FileHandle(FILEHANDLE_NAME)
3322        assert not fh.closed
3323        assert fh.is_file
3324        fh.close()
3325        assert fh.closed
3326        fh.open()
3327        assert not fh.closed
3328        assert fh.is_file
3329        assert fh.name == 'test_FileHandle.bin'
3330        assert_filehandle(fh)
3331    finally:
3332        fh.close()
3333
3334
3335@pytest.mark.skipif(SKIP_PUBLIC or SKIP_WIN, reason=REASON)
3336def test_filehandle_unc_path():
3337    """Test FileHandle from UNC path."""
3338    with FileHandle(r'\\localhost\Data\Data\test_FileHandle.bin') as fh:
3339        assert fh.name == 'test_FileHandle.bin'
3340        assert fh.dirname == '\\\\localhost\\Data\\Data'
3341        assert_filehandle(fh)
3342
3343
3344###############################################################################
3345
3346# Test reading specific files
3347
3348if SKIP_EXTENDED or SKIP_PRIVATE:
3349    TIGER_FILES = []
3350    TIGER_IDS = []
3351else:
3352    TIGER_FILES = (
3353        public_file('graphicsmagick.org/be/*.tif')
3354        + public_file('graphicsmagick.org/le/*.tif')
3355        + public_file('graphicsmagick.org/bigtiff-be/*.tif')
3356        + public_file('graphicsmagick.org/bigtiff-le/*.tif')
3357    )
3358    TIGER_IDS = [
3359        '-'.join(f.split(os.path.sep)[-2:])
3360        .replace('-tiger', '')
3361        .replace('.tif', '')
3362        for f in TIGER_FILES
3363    ]
3364
3365
3366@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS or SKIP_EXTENDED, reason=REASON)
3367@pytest.mark.parametrize('fname', TIGER_FILES, ids=TIGER_IDS)
3368def test_read_tigers(fname):
3369    """Test tiger images from GraphicsMagick."""
3370    # ftp://ftp.graphicsmagick.org/pub/tiff-samples
3371    with TiffFile(fname) as tif:
3372        byteorder = {'le': '<', 'be': '>'}[os.path.split(fname)[0][-2:]]
3373        databits = int(fname.rsplit('.tif')[0][-2:])
3374
3375        # assert file properties
3376        assert_file_flags(tif)
3377        assert tif.byteorder == byteorder
3378        assert tif.is_bigtiff == ('bigtiff' in fname)
3379        assert len(tif.pages) == 1
3380
3381        # assert page properties
3382        page = tif.pages[0]
3383        assert_page_flags(page)
3384        assert page.tags['DocumentName'].value == os.path.basename(fname)
3385        assert page.imagewidth == 73
3386        assert page.imagelength == 76
3387        assert page.bitspersample == databits
3388        assert (page.photometric == RGB) == ('rgb' in fname)
3389        assert (page.photometric == PALETTE) == ('palette' in fname)
3390        assert page.is_tiled == ('tile' in fname)
3391        assert (page.planarconfig == CONTIG) == ('planar' not in fname)
3392        if 'minisblack' in fname:
3393            assert page.photometric == MINISBLACK
3394
3395        # float24 not supported
3396        # if 'float' in fname and databits == 24:
3397        #     with pytest.raises(ValueError):
3398        #         data = tif.asarray()
3399        #     return
3400
3401        # assert data shapes
3402        data = tif.asarray()
3403        assert isinstance(data, numpy.ndarray)
3404        assert data.flags['C_CONTIGUOUS']
3405        # if 'palette' in fname:
3406        #     shape = (76, 73, 3)
3407        if 'rgb' in fname:
3408            if 'planar' in fname:
3409                shape = (3, 76, 73)
3410            else:
3411                shape = (76, 73, 3)
3412        elif 'separated' in fname:
3413            if 'planar' in fname:
3414                shape = (4, 76, 73)
3415            else:
3416                shape = (76, 73, 4)
3417        else:
3418            shape = (76, 73)
3419        assert data.shape == shape
3420
3421        # assert data types
3422        if 'float' in fname:
3423            if databits == 24:
3424                dtype = numpy.float32
3425            else:
3426                dtype = f'float{databits}'
3427        # elif 'palette' in fname:
3428        #     dtype = numpy.uint16
3429        elif databits == 1:
3430            dtype = numpy.bool8
3431        elif databits <= 8:
3432            dtype = numpy.uint8
3433        elif databits <= 16:
3434            dtype = numpy.uint16
3435        elif databits <= 32:
3436            dtype = numpy.uint32
3437        elif databits <= 64:
3438            dtype = numpy.uint64
3439        assert data.dtype == dtype
3440
3441        assert_decode_method(page, data)
3442        assert_aszarr_method(page, data)
3443        assert__str__(tif)
3444
3445
3446@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
3447def test_read_exif_paint():
3448    """Test read EXIF tags."""
3449    fname = private_file('exif/paint.tif')
3450    with TiffFile(fname) as tif:
3451        exif = tif.pages[0].tags['ExifTag'].value
3452        assert exif['ColorSpace'] == 65535
3453        assert exif['ExifVersion'] == '0230'
3454        assert exif['UserComment'] == 'paint'
3455        assert_aszarr_method(tif)
3456        assert__str__(tif)
3457
3458
3459@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3460def test_read_hopper_2bit():
3461    """Test read 2-bit, fillorder=lsb2msb."""
3462    # https://github.com/python-pillow/Pillow/pull/1789
3463    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper2.tif')
3464    with TiffFile(fname) as tif:
3465        assert tif.byteorder == '<'
3466        assert len(tif.pages) == 1
3467        assert len(tif.series) == 1
3468        # assert page properties
3469        page = tif.pages[0]
3470        assert page.photometric == MINISBLACK
3471        assert not page.is_contiguous
3472        assert page.compression == NONE
3473        assert page.imagewidth == 128
3474        assert page.imagelength == 128
3475        assert page.bitspersample == 2
3476        assert page.samplesperpixel == 1
3477        # assert series properties
3478        series = tif.series[0]
3479        assert series.shape == (128, 128)
3480        assert series.dtype == numpy.uint8
3481        assert series.axes == 'YX'
3482        assert series.offset is None
3483        # assert data
3484        data = tif.asarray()
3485        assert isinstance(data, numpy.ndarray)
3486        assert data.shape == (128, 128)
3487        assert data[50, 63] == 3
3488        assert_aszarr_method(tif, data)
3489        assert__str__(tif)
3490    # reversed
3491    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper2R.tif')
3492    with TiffFile(fname) as tif:
3493        page = tif.pages[0]
3494        assert page.photometric == MINISBLACK
3495        assert page.fillorder == LSB2MSB
3496        assert_array_equal(tif.asarray(), data)
3497        assert_aszarr_method(tif)
3498        assert__str__(tif)
3499    # inverted
3500    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper2I.tif')
3501    with TiffFile(fname) as tif:
3502        page = tif.pages[0]
3503        assert page.photometric == MINISWHITE
3504        assert_array_equal(tif.asarray(), 3 - data)
3505        assert_aszarr_method(tif)
3506        assert__str__(tif)
3507    # inverted and reversed
3508    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper2IR.tif')
3509    with TiffFile(fname) as tif:
3510        page = tif.pages[0]
3511        assert page.photometric == MINISWHITE
3512        assert_array_equal(tif.asarray(), 3 - data)
3513        assert_aszarr_method(tif)
3514        assert__str__(tif)
3515
3516
3517@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3518def test_read_hopper_4bit():
3519    """Test read 4-bit, fillorder=lsb2msb."""
3520    # https://github.com/python-pillow/Pillow/pull/1789
3521    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper4.tif')
3522    with TiffFile(fname) as tif:
3523        assert tif.byteorder == '<'
3524        assert len(tif.pages) == 1
3525        assert len(tif.series) == 1
3526        # assert page properties
3527        page = tif.pages[0]
3528        assert page.photometric == MINISBLACK
3529        assert not page.is_contiguous
3530        assert page.compression == NONE
3531        assert page.imagewidth == 128
3532        assert page.imagelength == 128
3533        assert page.bitspersample == 4
3534        assert page.samplesperpixel == 1
3535        # assert series properties
3536        series = tif.series[0]
3537        assert series.shape == (128, 128)
3538        assert series.dtype == numpy.uint8
3539        assert series.axes == 'YX'
3540        assert series.offset is None
3541        # assert data
3542        data = tif.asarray()
3543        assert isinstance(data, numpy.ndarray)
3544        assert data.shape == (128, 128)
3545        assert data[50, 63] == 13
3546    # reversed
3547    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper4R.tif')
3548    with TiffFile(fname) as tif:
3549        page = tif.pages[0]
3550        assert page.photometric == MINISBLACK
3551        assert page.fillorder == LSB2MSB
3552        assert_array_equal(tif.asarray(), data)
3553        assert__str__(tif)
3554    # inverted
3555    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper4I.tif')
3556    with TiffFile(fname) as tif:
3557        page = tif.pages[0]
3558        assert page.photometric == MINISWHITE
3559        assert_array_equal(tif.asarray(), 15 - data)
3560        assert__str__(tif)
3561    # inverted and reversed
3562    fname = public_file('pillow/tiff_gray_2_4_bpp/hopper4IR.tif')
3563    with TiffFile(fname) as tif:
3564        page = tif.pages[0]
3565        assert page.photometric == MINISWHITE
3566        assert_array_equal(tif.asarray(), 15 - data)
3567        assert__str__(tif)
3568
3569
3570@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
3571def test_read_lsb2msb():
3572    """Test read fillorder=lsb2msb, 2 series."""
3573    # http://lists.openmicroscopy.org.uk/pipermail/ome-users
3574    #   /2015-September/005635.html
3575    fname = private_file('test_lsb2msb.tif')
3576    with TiffFile(fname) as tif:
3577        assert tif.byteorder == '<'
3578        assert len(tif.pages) == 2
3579        assert len(tif.series) == 2
3580        # assert page properties
3581        page = tif.pages[0]
3582        assert page.is_contiguous
3583        assert page.compression == NONE
3584        assert page.imagewidth == 7100
3585        assert page.imagelength == 4700
3586        assert page.bitspersample == 16
3587        assert page.samplesperpixel == 3
3588        page = tif.pages[1]
3589        assert page.is_contiguous
3590        assert page.compression == NONE
3591        assert page.imagewidth == 7100
3592        assert page.imagelength == 4700
3593        assert page.bitspersample == 16
3594        assert page.samplesperpixel == 1
3595        # assert series properties
3596        series = tif.series[0]
3597        assert series.shape == (4700, 7100, 3)
3598        assert series.dtype == numpy.uint16
3599        assert series.axes == 'YXS'
3600        assert series.offset is None
3601        series = tif.series[1]
3602        assert series.shape == (4700, 7100)
3603        assert series.dtype == numpy.uint16
3604        assert series.axes == 'YX'
3605        assert series.offset is None
3606        # assert data
3607        data = tif.asarray(series=0)
3608        assert isinstance(data, numpy.ndarray)
3609        assert data.shape == (4700, 7100, 3)
3610        assert data[2350, 3550, 1] == 60457
3611        assert_aszarr_method(tif, data, series=0)
3612        data = tif.asarray(series=1)
3613        assert isinstance(data, numpy.ndarray)
3614        assert data.flags['C_CONTIGUOUS']
3615        assert data.shape == (4700, 7100)
3616        assert data[2350, 3550] == 56341
3617        assert_aszarr_method(tif, data, series=1)
3618        assert__str__(tif)
3619
3620
3621@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3622def test_read_gimp_u2():
3623    """Test read uint16 with horizontal predictor by GIMP."""
3624    fname = public_file('tifffile/gimp_u2.tiff')
3625    with TiffFile(fname) as tif:
3626        assert len(tif.pages) == 1
3627        page = tif.pages[0]
3628        assert page.compression == ADOBE_DEFLATE
3629        assert page.photometric == RGB
3630        assert page.predictor == HORIZONTAL
3631        assert page.imagewidth == 333
3632        assert page.imagelength == 231
3633        assert page.samplesperpixel == 3
3634        image = tif.asarray()
3635        assert image.flags['C_CONTIGUOUS']
3636        assert tuple(image[110, 110]) == (23308, 17303, 41160)
3637        assert_aszarr_method(tif, image)
3638        assert__str__(tif)
3639
3640
3641@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3642def test_read_gimp_f4():
3643    """Test read float32 with horizontal predictor by GIMP."""
3644    fname = public_file('tifffile/gimp_f4.tiff')
3645    with TiffFile(fname) as tif:
3646        assert len(tif.pages) == 1
3647        page = tif.pages[0]
3648        assert page.compression == ADOBE_DEFLATE
3649        assert page.photometric == RGB
3650        assert page.predictor == HORIZONTAL
3651        assert page.imagewidth == 333
3652        assert page.imagelength == 231
3653        assert page.samplesperpixel == 3
3654        image = tif.asarray()
3655        assert image.flags['C_CONTIGUOUS']
3656        assert_array_almost_equal(
3657            image[110, 110], (0.35565534, 0.26402164, 0.6280674)
3658        )
3659        assert_aszarr_method(tif, image)
3660        assert__str__(tif)
3661
3662
3663@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3664def test_read_gimp_f2():
3665    """Test read float16 with horizontal predictor by GIMP."""
3666    fname = public_file('tifffile/gimp_f2.tiff')
3667    with TiffFile(fname) as tif:
3668        assert len(tif.pages) == 1
3669        page = tif.pages[0]
3670        assert page.compression == ADOBE_DEFLATE
3671        assert page.photometric == RGB
3672        assert page.predictor == HORIZONTAL
3673        assert page.imagewidth == 333
3674        assert page.imagelength == 231
3675        assert page.samplesperpixel == 3
3676        image = tif.asarray()
3677        assert image.flags['C_CONTIGUOUS']
3678        assert_array_almost_equal(
3679            image[110, 110].astype(numpy.float64),
3680            (0.35571289, 0.26391602, 0.62792969),
3681        )
3682        assert_aszarr_method(tif, image)
3683        assert__str__(tif)
3684
3685
3686@pytest.mark.skipif(
3687    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.LJPEG, reason=REASON
3688)
3689def test_read_dng_jpeglossy():
3690    """Test read JPEG_LOSSY in DNG."""
3691    fname = private_file('DNG/Adobe DNG Converter.dng')
3692    with TiffFile(fname) as tif:
3693        assert len(tif.pages) == 1
3694        assert len(tif.series) == 6
3695        for series in tif.series:
3696            image = series.asarray()
3697            assert_aszarr_method(series, image)
3698        assert__str__(tif)
3699
3700
3701@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
3702@pytest.mark.parametrize('fp', ['fp16', 'fp24', 'fp32'])
3703def test_read_dng_floatpredx2(fp):
3704    """Test read FLOATINGPOINTX2 predictor in DNG."""
3705    # <https://raw.pixls.us/data/Canon/EOS%205D%20Mark%20III/>
3706    fname = private_file(f'DNG/fpx2/hdrmerge-bayer-{fp}-w-pred-deflate.dng')
3707    with TiffFile(fname) as tif:
3708        assert len(tif.pages) == 1
3709        assert len(tif.series) == 3
3710        page = tif.pages[0].pages[0]
3711        assert page.compression == ADOBE_DEFLATE
3712        assert page.photometric == CFA
3713        assert page.predictor == 34894
3714        assert page.imagewidth == 5920
3715        assert page.imagelength == 3950
3716        assert page.sampleformat == 3
3717        assert page.bitspersample == int(fp[2:])
3718        assert page.samplesperpixel == 1
3719        if fp == 'fp24':
3720            with pytest.raises(NotImplementedError):
3721                image = page.asarray()
3722        else:
3723            image = page.asarray()
3724            assert_aszarr_method(page, image)
3725        assert__str__(tif)
3726
3727
3728@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
3729@pytest.mark.parametrize('fname', ['sample1.orf', 'sample1.rw2'])
3730def test_read_rawformats(fname, caplog):
3731    """Test parse unsupported RAW formats."""
3732    fname = private_file(f'RAWformats/{fname}')
3733    with TiffFile(fname) as tif:
3734        assert 'RAW format' in caplog.text
3735        assert__str__(tif)
3736
3737
3738@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
3739def test_read_iss_vista():
3740    """Test read bogus imagedepth tag by ISS Vista."""
3741    fname = private_file('iss/10um_beads_14stacks_ch1.tif')
3742    with TiffFile(fname) as tif:
3743        assert tif.byteorder == '<'
3744        assert len(tif.pages) == 14
3745        assert len(tif.series) == 1
3746        # assert page properties
3747        page = tif.pages[0]
3748        assert not page.is_reduced
3749        assert not page.is_tiled
3750        assert page.compression == NONE
3751        assert page.imagewidth == 256
3752        assert page.imagelength == 256
3753        assert page.tags['ImageDepth'].value == 14  # bogus
3754        assert page.bitspersample == 16
3755        assert page.samplesperpixel == 1
3756        # assert series properties
3757        series = tif.series[0]
3758        assert series.shape == (14, 256, 256)
3759        assert series.dtype == numpy.int16
3760        assert series.axes == 'IYX'  # ZYX
3761        assert_aszarr_method(series)
3762        assert__str__(tif)
3763
3764
3765@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
3766def test_read_vips():
3767    """Test read 347x641 RGB, bigtiff, pyramid, tiled, produced by VIPS."""
3768    fname = private_file('vips.tif')
3769    with TiffFile(fname) as tif:
3770        assert tif.byteorder == '<'
3771        assert len(tif.pages) == 4
3772        assert len(tif.series) == 1
3773        # assert page properties
3774        page = tif.pages[0]
3775        assert not page.is_reduced
3776        assert page.is_tiled
3777        assert page.compression == ADOBE_DEFLATE
3778        assert page.imagewidth == 641
3779        assert page.imagelength == 347
3780        assert page.bitspersample == 8
3781        assert page.samplesperpixel == 3
3782        # assert series properties
3783        series = tif.series[0]
3784        assert series.is_pyramidal
3785        assert len(series.levels) == 4
3786        assert series.shape == (347, 641, 3)
3787        assert series.dtype == numpy.uint8
3788        assert series.axes == 'YXS'
3789        # level 3
3790        series = series.levels[3]
3791        page = series.pages[0]
3792        assert page.is_reduced
3793        assert page.is_tiled
3794        assert series.shape == (43, 80, 3)
3795        assert series.dtype == numpy.uint8
3796        assert series.axes == 'YXS'
3797        # assert data
3798        data = tif.asarray(series=0)
3799        assert isinstance(data, numpy.ndarray)
3800        assert data.flags['C_CONTIGUOUS']
3801        assert data.shape == (347, 641, 3)
3802        assert data.dtype == numpy.uint8
3803        assert tuple(data[132, 361]) == (114, 233, 58)
3804        assert_aszarr_method(tif, data, series=0, level=0)
3805        assert__str__(tif)
3806
3807
3808@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3809def test_read_volumetric():
3810    """Test read 128x128x128, float32, tiled SGI."""
3811    fname = public_file('tifffile/sgi_depth.tif')
3812    with TiffFile(fname) as tif:
3813        assert tif.byteorder == '<'
3814        assert len(tif.pages) == 1
3815        assert len(tif.series) == 1
3816        # assert page properties
3817        page = tif.pages[0]
3818        assert page.is_volumetric
3819        assert page.planarconfig == CONTIG
3820        assert page.is_tiled
3821        assert page.is_contiguous
3822        assert page.compression == NONE
3823        assert page.imagewidth == 128
3824        assert page.imagelength == 128
3825        assert page.imagedepth == 128
3826        assert page.tilewidth == 128
3827        assert page.tilelength == 128
3828        assert page.tiledepth == 1
3829        assert page.bitspersample == 32
3830        assert page.samplesperpixel == 1
3831        assert page.tags['Software'].value == (
3832            'MFL MeVis File Format Library, TIFF Module'
3833        )
3834        # assert series properties
3835        series = tif.series[0]
3836        assert series.shape == (128, 128, 128)
3837        assert series.dtype == numpy.float32
3838        assert series.axes == 'ZYX'
3839        # assert data
3840        data = tif.asarray()
3841        assert isinstance(data, numpy.ndarray)
3842        assert data.flags['C_CONTIGUOUS']
3843        assert data.shape == (128, 128, 128)
3844        assert data.dtype == numpy.float32
3845        assert data[64, 64, 64] == 0.0
3846        assert_decode_method(page)
3847        assert_aszarr_method(tif, data)
3848        assert__str__(tif)
3849
3850
3851@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3852def test_read_oxford():
3853    """Test read 601x81, uint8, PackBits."""
3854    fname = public_file('juicypixels/oxford.tif')
3855    with TiffFile(fname) as tif:
3856        assert tif.byteorder == '>'
3857        assert len(tif.pages) == 1
3858        assert len(tif.series) == 1
3859        # assert page properties
3860        page = tif.pages[0]
3861        assert page.planarconfig == SEPARATE
3862        assert page.photometric == RGB
3863        assert page.compression == LZW
3864        assert page.imagewidth == 601
3865        assert page.imagelength == 81
3866        assert page.bitspersample == 8
3867        assert page.samplesperpixel == 3
3868        # assert series properties
3869        series = tif.series[0]
3870        assert series.shape == (3, 81, 601)
3871        assert series.dtype == numpy.uint8
3872        assert series.axes == 'SYX'
3873        # assert data
3874        data = tif.asarray()
3875        assert isinstance(data, numpy.ndarray)
3876        assert data.flags['C_CONTIGUOUS']
3877        assert data.shape == (3, 81, 601)
3878        assert data.dtype == numpy.uint8
3879        assert data[1, 24, 49] == 191
3880        assert_aszarr_method(tif, data)
3881        assert__str__(tif)
3882
3883
3884@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3885def test_read_cramps():
3886    """Test 800x607 uint8, PackBits."""
3887    fname = public_file('juicypixels/cramps.tif')
3888    with TiffFile(fname) as tif:
3889        assert tif.byteorder == '>'
3890        assert len(tif.pages) == 1
3891        assert len(tif.series) == 1
3892        # assert page properties
3893        page = tif.pages[0]
3894        assert page.compression == PACKBITS
3895        assert page.photometric == MINISWHITE
3896        assert page.imagewidth == 800
3897        assert page.imagelength == 607
3898        assert page.bitspersample == 8
3899        assert page.samplesperpixel == 1
3900        # assert series properties
3901        series = tif.series[0]
3902        assert series.shape == (607, 800)
3903        assert series.dtype == numpy.uint8
3904        assert series.axes == 'YX'
3905        # assert data
3906        data = tif.asarray()
3907        assert isinstance(data, numpy.ndarray)
3908        assert data.flags['C_CONTIGUOUS']
3909        assert data.shape == (607, 800)
3910        assert data.dtype == numpy.uint8
3911        assert data[273, 426] == 34
3912        assert_aszarr_method(tif, data)
3913        assert__str__(tif)
3914
3915
3916@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
3917def test_read_cramps_tile():
3918    """Test read 800x607 uint8, raw, volumetric, tiled."""
3919    fname = public_file('juicypixels/cramps-tile.tif')
3920    with TiffFile(fname) as tif:
3921        assert tif.byteorder == '>'
3922        assert len(tif.pages) == 1
3923        assert len(tif.series) == 1
3924        # assert page properties
3925        page = tif.pages[0]
3926        assert page.is_tiled
3927        assert not page.is_volumetric
3928        assert page.compression == NONE
3929        assert page.photometric == MINISWHITE
3930        assert page.imagewidth == 800
3931        assert page.imagelength == 607
3932        assert page.imagedepth == 1
3933        assert page.tilewidth == 256
3934        assert page.tilelength == 256
3935        assert page.tiledepth == 1
3936        assert page.bitspersample == 8
3937        assert page.samplesperpixel == 1
3938        # assert series properties
3939        series = tif.series[0]
3940        assert series.shape == (607, 800)
3941        assert series.dtype == numpy.uint8
3942        assert series.axes == 'YX'
3943        # assert data
3944        data = tif.asarray()
3945        assert isinstance(data, numpy.ndarray)
3946        assert data.flags['C_CONTIGUOUS']
3947        assert data.shape == (607, 800)
3948        assert data.dtype == numpy.uint8
3949        assert data[273, 426] == 34
3950        assert_aszarr_method(tif, data)
3951        assert__str__(tif)
3952
3953
3954@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3955def test_read_jello():
3956    """Test read 256x192x3, uint16, palette, PackBits."""
3957    fname = public_file('juicypixels/jello.tif')
3958    with TiffFile(fname) as tif:
3959        assert tif.byteorder == '>'
3960        assert len(tif.pages) == 1
3961        assert len(tif.series) == 1
3962        # assert page properties
3963        page = tif.pages[0]
3964        assert page.photometric == PALETTE
3965        assert page.planarconfig == CONTIG
3966        assert page.compression == PACKBITS
3967        assert page.imagewidth == 256
3968        assert page.imagelength == 192
3969        assert page.bitspersample == 8
3970        assert page.samplesperpixel == 1
3971        # assert series properties
3972        series = tif.series[0]
3973        assert series.shape == (192, 256)
3974        assert series.dtype == numpy.uint8
3975        assert series.axes == 'YX'
3976        # assert data
3977        data = page.asrgb(uint8=False)
3978        assert isinstance(data, numpy.ndarray)
3979        assert data.flags['C_CONTIGUOUS']
3980        assert data.shape == (192, 256, 3)
3981        assert data.dtype == numpy.uint16
3982        assert tuple(data[100, 140, :]) == (48895, 65279, 48895)
3983        assert__str__(tif)
3984
3985
3986@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
3987def test_read_quad_lzw():
3988    """Test read 384x512 RGB uint8 old style LZW."""
3989    fname = public_file('libtiff/quad-lzw-compat.tiff')
3990    with TiffFile(fname) as tif:
3991        assert tif.byteorder == '>'
3992        assert len(tif.pages) == 1
3993        assert len(tif.series) == 1
3994        # assert page properties
3995        page = tif.pages[0]
3996        assert not page.is_tiled
3997        assert page.photometric == RGB
3998        assert page.compression == LZW
3999        assert page.imagewidth == 512
4000        assert page.imagelength == 384
4001        assert page.bitspersample == 8
4002        assert page.samplesperpixel == 3
4003        # assert series properties
4004        series = tif.series[0]
4005        assert series.shape == (384, 512, 3)
4006        assert series.dtype == numpy.uint8
4007        assert series.axes == 'YXS'
4008        # assert data
4009        data = tif.asarray()
4010        assert isinstance(data, numpy.ndarray)
4011        assert data.flags['C_CONTIGUOUS']
4012        assert data.shape == (384, 512, 3)
4013        assert data.dtype == numpy.uint8
4014        assert tuple(data[309, 460, :]) == (0, 163, 187)
4015        assert_aszarr_method(tif, data)
4016
4017
4018@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4019def test_read_quad_lzw_le():
4020    """Test read 384x512 RGB uint8 LZW."""
4021    fname = private_file('quad-lzw_le.tif')
4022    with TiffFile(fname) as tif:
4023        assert tif.byteorder == '<'
4024        assert len(tif.pages) == 1
4025        assert len(tif.series) == 1
4026        # assert page properties
4027        page = tif.pages[0]
4028        assert page.photometric == RGB
4029        assert not page.is_tiled
4030        assert page.compression == LZW
4031        assert page.imagewidth == 512
4032        assert page.imagelength == 384
4033        assert page.bitspersample == 8
4034        assert page.samplesperpixel == 3
4035        # assert series properties
4036        series = tif.series[0]
4037        assert series.shape == (384, 512, 3)
4038        assert series.dtype == numpy.uint8
4039        assert series.axes == 'YXS'
4040        # assert data
4041        data = tif.asarray()
4042        assert isinstance(data, numpy.ndarray)
4043        assert data.flags['C_CONTIGUOUS']
4044        assert data.shape == (384, 512, 3)
4045        assert data.dtype == numpy.uint8
4046        assert tuple(data[309, 460, :]) == (0, 163, 187)
4047        assert_aszarr_method(tif, data)
4048        assert_decode_method(page)
4049
4050
4051@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4052def test_read_quad_tile():
4053    """Test read 384x512 RGB uint8 LZW tiled."""
4054    # Strips and tiles defined in same page
4055    fname = public_file('juicypixels/quad-tile.tif')
4056    with TiffFile(fname) as tif:
4057        assert__str__(tif)
4058        assert tif.byteorder == '>'
4059        assert len(tif.pages) == 1
4060        assert len(tif.series) == 1
4061        # assert page properties
4062        page = tif.pages[0]
4063        assert page.photometric == RGB
4064        assert page.is_tiled
4065        assert page.compression == LZW
4066        assert page.imagewidth == 512
4067        assert page.imagelength == 384
4068        assert page.imagedepth == 1
4069        assert page.tilewidth == 128
4070        assert page.tilelength == 128
4071        assert page.tiledepth == 1
4072        assert page.bitspersample == 8
4073        assert page.samplesperpixel == 3
4074        # assert series properties
4075        series = tif.series[0]
4076        assert series.shape == (384, 512, 3)
4077        assert series.dtype == numpy.uint8
4078        assert series.axes == 'YXS'
4079        # assert data
4080        data = tif.asarray()
4081        # assert 'invalid tile data (49153,) (1, 128, 128, 3)' in caplog.text
4082        assert isinstance(data, numpy.ndarray)
4083        assert data.flags['C_CONTIGUOUS']
4084        assert data.shape == (384, 512, 3)
4085        assert data.dtype == numpy.uint8
4086        assert tuple(data[309, 460, :]) == (0, 163, 187)
4087        assert_aszarr_method(tif, data)
4088
4089
4090@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4091def test_read_strike():
4092    """Test read 256x200 RGBA uint8 LZW."""
4093    fname = public_file('juicypixels/strike.tif')
4094    with TiffFile(fname) as tif:
4095        assert__str__(tif)
4096        assert tif.byteorder == '>'
4097        assert len(tif.pages) == 1
4098        assert len(tif.series) == 1
4099        # assert page properties
4100        page = tif.pages[0]
4101        assert page.photometric == RGB
4102        assert page.compression == LZW
4103        assert page.imagewidth == 256
4104        assert page.imagelength == 200
4105        assert page.bitspersample == 8
4106        assert page.samplesperpixel == 4
4107        assert page.extrasamples[0] == ASSOCALPHA
4108        # assert series properties
4109        series = tif.series[0]
4110        assert series.shape == (200, 256, 4)
4111        assert series.dtype == numpy.uint8
4112        assert series.axes == 'YXS'
4113        # assert data
4114        data = tif.asarray()
4115        assert isinstance(data, numpy.ndarray)
4116        assert data.flags['C_CONTIGUOUS']
4117        assert data.shape == (200, 256, 4)
4118        assert data.dtype == numpy.uint8
4119        assert tuple(data[65, 139, :]) == (43, 34, 17, 91)
4120        assert_aszarr_method(tif, data)
4121        assert_decode_method(page)
4122        assert__str__(tif)
4123
4124
4125@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4126def test_read_incomplete_tile_contig():
4127    """Test read PackBits compressed incomplete tile, contig RGB."""
4128    fname = public_file('GDAL/contig_tiled.tif')
4129    with TiffFile(fname) as tif:
4130        assert tif.byteorder == '>'
4131        assert len(tif.pages) == 1
4132        assert len(tif.series) == 1
4133        # assert page properties
4134        page = tif.pages[0]
4135        assert page.photometric == RGB
4136        assert page.planarconfig == CONTIG
4137        assert page.compression == PACKBITS
4138        assert page.imagewidth == 35
4139        assert page.imagelength == 37
4140        assert page.bitspersample == 8
4141        assert page.samplesperpixel == 3
4142        # assert series properties
4143        series = tif.series[0]
4144        assert series.shape == (37, 35, 3)
4145        assert series.dtype == numpy.uint8
4146        assert series.axes == 'YXS'
4147        # assert data
4148        data = page.asarray()
4149        assert data.flags['C_CONTIGUOUS']
4150        assert data.shape == (37, 35, 3)
4151        assert data.dtype == numpy.uint8
4152        assert tuple(data[19, 31]) == (50, 50, 50)
4153        assert tuple(data[36, 34]) == (70, 70, 70)
4154        assert_aszarr_method(page, data)
4155        assert_decode_method(page)
4156        assert__str__(tif)
4157
4158
4159@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4160def test_read_incomplete_tile_separate():
4161    """Test read PackBits compressed incomplete tile, separate RGB."""
4162    fname = public_file('GDAL/separate_tiled.tif')
4163    with TiffFile(fname) as tif:
4164        assert tif.byteorder == '>'
4165        assert len(tif.pages) == 1
4166        assert len(tif.series) == 1
4167        # assert page properties
4168        page = tif.pages[0]
4169        assert page.photometric == RGB
4170        assert page.planarconfig == SEPARATE
4171        assert page.compression == PACKBITS
4172        assert page.imagewidth == 35
4173        assert page.imagelength == 37
4174        assert page.bitspersample == 8
4175        assert page.samplesperpixel == 3
4176        # assert series properties
4177        series = tif.series[0]
4178        assert series.shape == (3, 37, 35)
4179        assert series.dtype == numpy.uint8
4180        assert series.axes == 'SYX'
4181        # assert data
4182        data = page.asarray()
4183        assert data.flags['C_CONTIGUOUS']
4184        assert data.shape == (3, 37, 35)
4185        assert data.dtype == numpy.uint8
4186        assert tuple(data[:, 19, 31]) == (50, 50, 50)
4187        assert tuple(data[:, 36, 34]) == (70, 70, 70)
4188        assert_aszarr_method(page, data)
4189        assert_decode_method(page)
4190        assert__str__(tif)
4191
4192
4193@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
4194def test_read_django():
4195    """Test read 3x480x320, uint16, palette, raw."""
4196    fname = private_file('django.tiff')
4197    with TiffFile(fname) as tif:
4198        assert tif.byteorder == '<'
4199        assert len(tif.pages) == 1
4200        assert len(tif.series) == 1
4201        # assert page properties
4202        page = tif.pages[0]
4203        assert page.photometric == PALETTE
4204        assert page.planarconfig == CONTIG
4205        assert page.compression == NONE
4206        assert page.imagewidth == 320
4207        assert page.imagelength == 480
4208        assert page.bitspersample == 8
4209        assert page.samplesperpixel == 1
4210        # assert series properties
4211        series = tif.series[0]
4212        assert series.shape == (480, 320)
4213        assert series.dtype == numpy.uint8
4214        assert series.axes == 'YX'
4215        # assert data
4216        data = page.asrgb(uint8=False)
4217        assert isinstance(data, numpy.ndarray)
4218        assert data.flags['C_CONTIGUOUS']
4219        assert data.shape == (480, 320, 3)
4220        assert data.dtype == numpy.uint16
4221        assert tuple(data[64, 64, :]) == (65535, 52171, 63222)
4222        assert__str__(tif)
4223
4224
4225@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4226def test_read_pygame_icon():
4227    """Test read 128x128 RGBA uint8 PackBits."""
4228    fname = private_file('pygame_icon.tiff')
4229    with TiffFile(fname) as tif:
4230        assert tif.byteorder == '>'
4231        assert len(tif.pages) == 1
4232        assert len(tif.series) == 1
4233        # assert page properties
4234        page = tif.pages[0]
4235        assert page.photometric == RGB
4236        assert page.compression == PACKBITS
4237        assert page.imagewidth == 128
4238        assert page.imagelength == 128
4239        assert page.bitspersample == 8
4240        assert page.samplesperpixel == 4
4241        assert page.extrasamples[0] == UNASSALPHA  # ?
4242        assert page.tags['Software'].value == 'QuickTime 5.0.5'
4243        assert page.tags['HostComputer'].value == 'MacOS 10.1.2'
4244        assert page.tags['DateTime'].value == '2001:12:21 04:34:56'
4245        # assert series properties
4246        series = tif.series[0]
4247        assert series.shape == (128, 128, 4)
4248        assert series.dtype == numpy.uint8
4249        assert series.axes == 'YXS'
4250        # assert data
4251        data = tif.asarray()
4252        assert isinstance(data, numpy.ndarray)
4253        assert data.flags['C_CONTIGUOUS']
4254        assert data.shape == (128, 128, 4)
4255        assert data.dtype == numpy.uint8
4256        assert tuple(data[22, 112, :]) == (100, 99, 98, 132)
4257        assert_aszarr_method(tif, data)
4258        assert__str__(tif)
4259
4260
4261@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4262def test_read_rgba_wo_extra_samples():
4263    """Test read 1065x785 RGBA uint8."""
4264    fname = private_file('rgba_wo_extra_samples.tif')
4265    with TiffFile(fname) as tif:
4266        assert tif.byteorder == '<'
4267        assert len(tif.pages) == 1
4268        assert len(tif.series) == 1
4269        # assert page properties
4270        page = tif.pages[0]
4271        assert page.photometric == RGB
4272        assert page.compression == LZW
4273        assert page.imagewidth == 1065
4274        assert page.imagelength == 785
4275        assert page.bitspersample == 8
4276        assert page.samplesperpixel == 4
4277        # with self.assertRaises(AttributeError):
4278        #     page.extrasamples
4279        # assert series properties
4280        series = tif.series[0]
4281        assert series.shape == (785, 1065, 4)
4282        assert series.dtype == numpy.uint8
4283        assert series.axes == 'YXS'
4284        # assert data
4285        data = tif.asarray()
4286        assert isinstance(data, numpy.ndarray)
4287        assert data.flags['C_CONTIGUOUS']
4288        assert data.shape == (785, 1065, 4)
4289        assert data.dtype == numpy.uint8
4290        assert tuple(data[560, 412, :]) == (60, 92, 74, 255)
4291        assert_aszarr_method(tif, data)
4292        assert_decode_method(page)
4293        assert__str__(tif)
4294
4295
4296@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
4297def test_read_rgb565():
4298    """Test read 64x64 RGB uint8 5,6,5 bitspersample."""
4299    fname = private_file('rgb565.tif')
4300    with TiffFile(fname) as tif:
4301        assert tif.byteorder == '<'
4302        assert len(tif.pages) == 1
4303        assert len(tif.series) == 1
4304        # assert page properties
4305        page = tif.pages[0]
4306        assert page.photometric == RGB
4307        assert page.compression == NONE
4308        assert page.imagewidth == 64
4309        assert page.imagelength == 64
4310        assert page.bitspersample == (5, 6, 5)
4311        assert page.samplesperpixel == 3
4312        # assert series properties
4313        series = tif.series[0]
4314        assert series.shape == (64, 64, 3)
4315        assert series.dtype == numpy.uint8
4316        assert series.axes == 'YXS'
4317        # assert data
4318        data = tif.asarray()
4319        assert isinstance(data, numpy.ndarray)
4320        assert data.flags['C_CONTIGUOUS']
4321        assert data.shape == (64, 64, 3)
4322        assert data.dtype == numpy.uint8
4323        assert tuple(data[56, 32, :]) == (239, 243, 247)
4324        assert_aszarr_method(tif, data)
4325        assert_decode_method(page)
4326        assert__str__(tif)
4327
4328
4329@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4330def test_read_generic_series():
4331    """Test read 4 series in 6 pages."""
4332    fname = public_file('tifffile/generic_series.tif')
4333    with TiffFile(fname) as tif:
4334        assert tif.byteorder == '<'
4335        assert len(tif.pages) == 6
4336        assert len(tif.series) == 4
4337        # assert series 0 properties
4338        series = tif.series[0]
4339        assert series.shape == (3, 20, 20)
4340        assert series.dtype == numpy.uint8
4341        assert series.axes == 'IYX'
4342        page = series.pages[0]
4343        assert page.compression == LZW
4344        assert page.imagewidth == 20
4345        assert page.imagelength == 20
4346        assert page.bitspersample == 8
4347        assert page.samplesperpixel == 1
4348        data = tif.asarray(series=0)
4349        assert data.flags['C_CONTIGUOUS']
4350        assert data.shape == (3, 20, 20)
4351        assert data.dtype == numpy.uint8
4352        assert tuple(data[:, 9, 9]) == (19, 90, 206)
4353        assert_aszarr_method(tif, data, series=0)
4354        # assert series 1 properties
4355        series = tif.series[1]
4356        assert series.shape == (10, 10, 3)
4357        assert series.dtype == numpy.float32
4358        assert series.axes == 'YXS'
4359        page = series.pages[0]
4360        assert page.photometric == RGB
4361        assert page.compression == LZW
4362        assert page.imagewidth == 10
4363        assert page.imagelength == 10
4364        assert page.bitspersample == 32
4365        assert page.samplesperpixel == 3
4366        data = tif.asarray(series=1)
4367        assert isinstance(data, numpy.ndarray)
4368        assert data.flags['C_CONTIGUOUS']
4369        assert data.shape == (10, 10, 3)
4370        assert data.dtype == numpy.float32
4371        assert round(abs(data[9, 9, 1] - 214.5733642578125), 7) == 0
4372        assert_aszarr_method(tif, data, series=1)
4373        # assert series 2 properties
4374        series = tif.series[2]
4375        assert series.shape == (20, 20, 3)
4376        assert series.dtype == numpy.uint8
4377        assert series.axes == 'YXS'
4378        page = series.pages[0]
4379        assert page.photometric == RGB
4380        assert page.compression == LZW
4381        assert page.imagewidth == 20
4382        assert page.imagelength == 20
4383        assert page.bitspersample == 8
4384        assert page.samplesperpixel == 3
4385        data = tif.asarray(series=2)
4386        assert isinstance(data, numpy.ndarray)
4387        assert data.flags['C_CONTIGUOUS']
4388        assert data.shape == (20, 20, 3)
4389        assert data.dtype == numpy.uint8
4390        assert tuple(data[9, 9, :]) == (19, 90, 206)
4391        assert_aszarr_method(tif, data, series=2)
4392        # assert series 3 properties
4393        series = tif.series[3]
4394        assert series.shape == (10, 10)
4395        assert series.dtype == numpy.float32
4396        assert series.axes == 'YX'
4397        page = series.pages[0]
4398        assert page.compression == LZW
4399        assert page.imagewidth == 10
4400        assert page.imagelength == 10
4401        assert page.bitspersample == 32
4402        assert page.samplesperpixel == 1
4403        data = tif.asarray(series=3)
4404        assert isinstance(data, numpy.ndarray)
4405        assert data.flags['C_CONTIGUOUS']
4406        assert data.shape == (10, 10)
4407        assert data.dtype == numpy.float32
4408        assert round(abs(data[9, 9] - 223.1648712158203), 7) == 0
4409        assert_aszarr_method(tif, data, series=3)
4410        assert__str__(tif)
4411
4412
4413@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4414def test_read_freeimage():
4415    """Test read 3 series in 3 pages RGB LZW."""
4416    fname = private_file('freeimage.tif')
4417    with TiffFile(fname) as tif:
4418        assert tif.byteorder == '<'
4419        assert len(tif.pages) == 3
4420        assert len(tif.series) == 3
4421        for i, shape in enumerate(((100, 600), (379, 574), (689, 636))):
4422            series = tif.series[i]
4423            shape = shape + (3,)
4424            assert series.shape == shape
4425            assert series.dtype == numpy.uint8
4426            assert series.axes == 'YXS'
4427            page = series.pages[0]
4428            assert page.photometric == RGB
4429            assert page.compression == LZW
4430            assert page.imagewidth == shape[1]
4431            assert page.imagelength == shape[0]
4432            assert page.bitspersample == 8
4433            assert page.samplesperpixel == 3
4434            data = tif.asarray(series=i)
4435            assert isinstance(data, numpy.ndarray)
4436            assert data.flags['C_CONTIGUOUS']
4437            assert data.shape == shape
4438            assert data.dtype == numpy.uint8
4439            assert_aszarr_method(tif, data, series=i)
4440            assert__str__(tif)
4441
4442
4443@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4444def test_read_12bit():
4445    """Test read 12 bit images."""
4446    fname = private_file('12bit.tif')
4447    with TiffFile(fname) as tif:
4448        assert tif.byteorder == '<'
4449        assert len(tif.pages) == 1000
4450        assert len(tif.series) == 1
4451        # assert page properties
4452        page = tif.pages[0]
4453        assert not page.is_contiguous
4454        assert page.compression == NONE
4455        assert page.imagewidth == 1024
4456        assert page.imagelength == 304
4457        assert page.bitspersample == 12
4458        assert page.samplesperpixel == 1
4459        # assert series properties
4460        series = tif.series[0]
4461        assert series.shape == (1000, 304, 1024)
4462        assert series.dtype == numpy.uint16
4463        assert series.axes == 'IYX'
4464        # assert data
4465        data = tif.asarray(478)
4466        assert isinstance(data, numpy.ndarray)
4467        assert data.flags['C_CONTIGUOUS']
4468        assert data.shape == (304, 1024)
4469        assert data.dtype == numpy.uint16
4470        assert round(abs(data[138, 475] - 40), 7) == 0
4471        assert_aszarr_method(tif, data, key=478)
4472        assert__str__(tif, 0)
4473
4474
4475@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
4476def test_read_lzw_12bit_table():
4477    """Test read lzw-full-12-bit-table.tif.
4478
4479    Also test RowsPerStrip > ImageLength.
4480
4481    """
4482    fname = public_file('twelvemonkeys/tiff/lzw-full-12-bit-table.tif')
4483    with TiffFile(fname) as tif:
4484        assert len(tif.series) == 1
4485        assert len(tif.pages) == 1
4486        page = tif.pages[0]
4487        assert page.photometric == MINISBLACK
4488        assert page.imagewidth == 874
4489        assert page.imagelength == 1240
4490        assert page.bitspersample == 8
4491        assert page.samplesperpixel == 1
4492        assert page.rowsperstrip == 1240
4493        assert page.tags['RowsPerStrip'].value == 4294967295
4494        # assert data
4495        image = page.asarray()
4496        assert image.flags['C_CONTIGUOUS']
4497        assert image[434, 588] == 88
4498        assert image[400, 600] == 255
4499        assert_aszarr_method(page, image)
4500        assert__str__(tif)
4501
4502
4503@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS or SKIP_LARGE, reason=REASON)
4504def test_read_lzw_large_buffer():
4505    """Test read LZW compression which requires large buffer."""
4506    # https://github.com/groupdocs-viewer/GroupDocs.Viewer-for-.NET-MVC-App
4507    # /issues/35
4508    fname = private_file('lzw/lzw_large_buffer.tiff')
4509    with TiffFile(fname) as tif:
4510        assert len(tif.pages) == 1
4511        page = tif.pages[0]
4512        assert page.compression == LZW
4513        assert page.imagewidth == 5104
4514        assert page.imagelength == 8400
4515        assert page.bitspersample == 8
4516        assert page.samplesperpixel == 4
4517        # assert data
4518        image = page.asarray()
4519        assert image.shape == (8400, 5104, 4)
4520        assert image.dtype == numpy.uint8
4521        image = tif.asarray()
4522        assert image.shape == (8400, 5104, 4)
4523        assert image.dtype == numpy.uint8
4524        assert image[4200, 2550, 0] == 0
4525        assert image[4200, 2550, 3] == 255
4526        assert_aszarr_method(tif, image)
4527        assert__str__(tif)
4528
4529
4530@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4531def test_read_lzw_ycbcr_subsampling():
4532    """Test fail LZW compression with subsampling."""
4533    fname = private_file('lzw/lzw_ycbcr_subsampling.tif')
4534    with TiffFile(fname) as tif:
4535        assert len(tif.pages) == 1
4536        page = tif.pages[0]
4537        assert page.compression == LZW
4538        assert page.photometric == YCBCR
4539        assert page.planarconfig == CONTIG
4540        assert page.imagewidth == 39
4541        assert page.imagelength == 39
4542        assert page.bitspersample == 8
4543        assert page.samplesperpixel == 3
4544        # assert data
4545        with pytest.raises(NotImplementedError):
4546            page.asarray()
4547        assert__str__(tif)
4548
4549
4550@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
4551def test_read_ycbcr_subsampling():
4552    """Test fail YCBCR with subsampling."""
4553    fname = private_file('ycbcr_subsampling.tif')
4554    with TiffFile(fname) as tif:
4555        assert len(tif.pages) == 2
4556        page = tif.pages[0]
4557        assert page.compression == NONE
4558        assert page.photometric == YCBCR
4559        assert page.planarconfig == CONTIG
4560        assert page.imagewidth == 640
4561        assert page.imagelength == 480
4562        assert page.bitspersample == 8
4563        assert page.samplesperpixel == 3
4564        # assert data
4565        with pytest.raises(NotImplementedError):
4566            page.asarray()
4567        assert__str__(tif)
4568
4569
4570@pytest.mark.skipif(
4571    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
4572)
4573def test_read_jpeg_baboon():
4574    """Test JPEG compression."""
4575    fname = private_file('baboon.tiff')
4576    with TiffFile(fname) as tif:
4577        assert tif.byteorder == '<'
4578        assert len(tif.pages) == 1
4579        assert len(tif.series) == 1
4580        # assert page properties
4581        page = tif.pages[0]
4582        assert 'JPEGTables' in page.tags
4583        assert not page.is_reduced
4584        assert not page.is_tiled
4585        assert page.compression == JPEG
4586        assert page.imagewidth == 512
4587        assert page.imagelength == 512
4588        assert page.bitspersample == 8
4589        # assert series properties
4590        series = tif.series[0]
4591        assert series.shape == (512, 512, 3)
4592        assert series.dtype == numpy.uint8
4593        assert series.axes == 'YXS'
4594        # assert data
4595        # with pytest.raises((ValueError, NotImplementedError)):
4596        image = tif.asarray()
4597        assert image.flags['C_CONTIGUOUS']
4598        assert_aszarr_method(tif, image)
4599        assert__str__(tif)
4600
4601
4602@pytest.mark.skipif(
4603    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
4604)
4605def test_read_jpeg_ycbcr():
4606    """Test read YCBCR JPEG is returned as RGB."""
4607    fname = private_file('jpeg/jpeg_ycbcr.tiff')
4608    with TiffFile(fname) as tif:
4609        assert len(tif.pages) == 1
4610        page = tif.pages[0]
4611        assert page.compression == JPEG
4612        assert page.photometric == YCBCR
4613        assert page.planarconfig == CONTIG
4614        assert page.imagewidth == 128
4615        assert page.imagelength == 80
4616        assert page.bitspersample == 8
4617        assert page.samplesperpixel == 3
4618        # assert data
4619        image = tif.asarray()
4620        assert image.flags['C_CONTIGUOUS']
4621        assert image.shape == (80, 128, 3)
4622        assert image.dtype == numpy.uint8
4623        assert tuple(image[50, 50, :]) == (177, 149, 210)
4624        # YCBCR (164, 154, 137)
4625        assert_aszarr_method(tif, image)
4626        assert_decode_method(page)
4627        assert__str__(tif)
4628
4629
4630@pytest.mark.skipif(
4631    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
4632)
4633@pytest.mark.parametrize(
4634    'fname', ['tiff_tiled_cmyk_jpeg.tif', 'tiff_strip_cmyk_jpeg.tif']
4635)
4636def test_read_jpeg_cmyk(fname):
4637    """Test read JPEG compressed CMYK image."""
4638    with TiffFile(private_file(f'pillow/{fname}')) as tif:
4639        assert len(tif.pages) == 1
4640        page = tif.pages[0]
4641        assert page.compression == JPEG
4642        assert page.photometric == SEPARATED
4643        assert page.shape == (100, 100, 4)
4644        assert page.dtype == numpy.uint8
4645        data = page.asarray()
4646        assert data.shape == (100, 100, 4)
4647        assert data.dtype == numpy.uint8
4648        assert tuple(data[46, 49]) == (79, 230, 222, 77)
4649        assert_aszarr_method(tif, data)
4650        # assert_decode_method(page)
4651        assert__str__(tif)
4652
4653
4654@pytest.mark.skipif(
4655    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG12, reason=REASON
4656)
4657def test_read_jpeg12_mandril():
4658    """Test read JPEG 12-bit compression."""
4659    # JPEG 12-bit
4660    fname = private_file('jpeg/jpeg12_mandril.tif')
4661    with TiffFile(fname) as tif:
4662        assert len(tif.pages) == 1
4663        page = tif.pages[0]
4664        assert page.compression == JPEG
4665        assert page.photometric == YCBCR
4666        assert page.imagewidth == 512
4667        assert page.imagelength == 480
4668        assert page.bitspersample == 12
4669        assert page.samplesperpixel == 3
4670        # assert data
4671        image = tif.asarray()
4672        assert image.flags['C_CONTIGUOUS']
4673        assert image.shape == (480, 512, 3)
4674        assert image.dtype == numpy.uint16
4675        assert tuple(image[128, 128, :]) == (1685, 1859, 1376)
4676        # YCBCR (1752, 1836, 2000)
4677        assert_aszarr_method(tif, image)
4678        assert__str__(tif)
4679
4680
4681@pytest.mark.skipif(
4682    SKIP_PRIVATE or SKIP_CODECS or SKIP_LARGE or not imagecodecs.JPEG,
4683    reason=REASON,
4684)
4685def test_read_jpeg_lsb2msb():
4686    """Test read huge tiled, JPEG compressed, with lsb2msb specified.
4687
4688    Also test JPEG with RGB photometric.
4689
4690    """
4691    fname = private_file('large/jpeg_lsb2msb.tif')
4692    with TiffFile(fname) as tif:
4693        assert len(tif.pages) == 1
4694        page = tif.pages[0]
4695        assert page.compression == JPEG
4696        assert page.photometric == RGB
4697        assert page.imagewidth == 49128
4698        assert page.imagelength == 59683
4699        assert page.bitspersample == 8
4700        assert page.samplesperpixel == 3
4701        # assert data
4702        image = tif.asarray()
4703        assert image.flags['C_CONTIGUOUS']
4704        assert image.shape == (59683, 49128, 3)
4705        assert image.dtype == numpy.uint8
4706        assert tuple(image[38520, 43767, :]) == (255, 255, 255)
4707        assert tuple(image[47866, 30076, :]) == (52, 39, 23)
4708        assert__str__(tif)
4709
4710
4711@pytest.mark.skipif(
4712    SKIP_PUBLIC
4713    or SKIP_CODECS
4714    or not imagecodecs.JPEG
4715    or not imagecodecs.JPEG2K,
4716    reason=REASON,
4717)
4718def test_read_aperio_j2k():
4719    """Test read SVS slide with J2K compression."""
4720    fname = private_file('slides/CMU-1-JP2K-33005.tif')
4721    with TiffFile(fname) as tif:
4722        assert tif.is_svs
4723        assert len(tif.pages) == 6
4724        page = tif.pages[0]
4725        assert page.compression == APERIO_JP2000_RGB
4726        assert page.photometric == RGB
4727        assert page.planarconfig == CONTIG
4728        assert page.shape == (32893, 46000, 3)
4729        assert page.dtype == numpy.uint8
4730        page = tif.pages[1]
4731        assert page.compression == JPEG
4732        assert page.photometric == RGB
4733        assert page.planarconfig == CONTIG
4734        assert page.shape == (732, 1024, 3)
4735        assert page.dtype == numpy.uint8
4736        page = tif.pages[2]
4737        assert page.compression == APERIO_JP2000_RGB
4738        assert page.photometric == RGB
4739        assert page.planarconfig == CONTIG
4740        assert page.shape == (8223, 11500, 3)
4741        assert page.dtype == numpy.uint8
4742        page = tif.pages[3]
4743        assert page.compression == APERIO_JP2000_RGB
4744        assert page.photometric == RGB
4745        assert page.planarconfig == CONTIG
4746        assert page.shape == (2055, 2875, 3)
4747        assert page.dtype == numpy.uint8
4748        page = tif.pages[4]
4749        assert page.is_reduced
4750        assert page.compression == LZW
4751        assert page.photometric == RGB
4752        assert page.planarconfig == CONTIG
4753        assert page.shape == (463, 387, 3)
4754        assert page.dtype == numpy.uint8
4755        page = tif.pages[5]
4756        assert page.is_reduced
4757        assert page.compression == JPEG
4758        assert page.photometric == RGB
4759        assert page.planarconfig == CONTIG
4760        assert page.shape == (431, 1280, 3)
4761        assert page.dtype == numpy.uint8
4762        # assert data
4763        image = tif.pages[3].asarray()
4764        assert image.flags['C_CONTIGUOUS']
4765        assert image.shape == (2055, 2875, 3)
4766        assert image.dtype == numpy.uint8
4767        assert image[512, 1024, 0] == 246
4768        assert image[512, 1024, 1] == 245
4769        assert image[512, 1024, 2] == 245
4770
4771        assert_decode_method(tif.pages[3], image)
4772        assert__str__(tif)
4773
4774
4775@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4776def test_read_lzma():
4777    """Test read LZMA compression."""
4778    # 512x512, uint8, lzma compression
4779    fname = private_file('lzma.tif')
4780    with TiffFile(fname) as tif:
4781        assert tif.byteorder == '<'
4782        assert len(tif.pages) == 1
4783        assert len(tif.series) == 1
4784        # assert page properties
4785        page = tif.pages[0]
4786        assert page.compression == LZMA
4787        assert page.photometric == MINISBLACK
4788        assert page.imagewidth == 512
4789        assert page.imagelength == 512
4790        assert page.bitspersample == 8
4791        assert page.samplesperpixel == 1
4792        # assert series properties
4793        series = tif.series[0]
4794        assert series.shape == (512, 512)
4795        assert series.dtype == numpy.uint8
4796        assert series.axes == 'YX'
4797        # assert data
4798        data = tif.asarray()
4799        assert data.flags['C_CONTIGUOUS']
4800        assert isinstance(data, numpy.ndarray)
4801        assert data.shape == (512, 512)
4802        assert data.dtype == numpy.uint8
4803        assert data[273, 426] == 151
4804        assert_aszarr_method(tif, data)
4805        assert__str__(tif)
4806
4807
4808@pytest.mark.skipif(
4809    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.WEBP, reason=REASON
4810)
4811def test_read_webp():
4812    """Test read WebP compression."""
4813    fname = public_file('GDAL/tif_webp.tif')
4814    with TiffFile(fname) as tif:
4815        assert len(tif.pages) == 1
4816        page = tif.pages[0]
4817        assert page.compression == WEBP
4818        assert page.photometric == RGB
4819        assert page.planarconfig == CONTIG
4820        assert page.imagewidth == 50
4821        assert page.imagelength == 50
4822        assert page.bitspersample == 8
4823        assert page.samplesperpixel == 3
4824        # assert data
4825        image = tif.asarray()
4826        assert image.flags['C_CONTIGUOUS']
4827        assert image.shape == (50, 50, 3)
4828        assert image.dtype == numpy.uint8
4829        assert image[25, 25, 0] == 92
4830        assert image[25, 25, 1] == 122
4831        assert image[25, 25, 2] == 37
4832        assert_aszarr_method(tif, image)
4833        assert__str__(tif)
4834
4835
4836@pytest.mark.skipif(
4837    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.LERC, reason=REASON
4838)
4839def test_read_lerc():
4840    """Test read LERC compression."""
4841    if not hasattr(imagecodecs, 'LERC'):
4842        pytest.skip('LERC codec missing')
4843
4844    fname = public_file('imagecodecs/rgb.u2.lerc.tif')
4845    with TiffFile(fname) as tif:
4846        assert len(tif.pages) == 1
4847        page = tif.pages[0]
4848        assert page.compression == LERC
4849        assert page.photometric == RGB
4850        assert page.planarconfig == CONTIG
4851        assert page.imagewidth == 31
4852        assert page.imagelength == 32
4853        assert page.bitspersample == 16
4854        assert page.samplesperpixel == 3
4855        # assert data
4856        image = tif.asarray()
4857        assert image.flags['C_CONTIGUOUS']
4858        assert image.shape == (32, 31, 3)
4859        assert image.dtype == numpy.uint16
4860        assert tuple(image[25, 25]) == (3265, 1558, 2811)
4861        assert_aszarr_method(tif, image)
4862        assert__str__(tif)
4863
4864
4865@pytest.mark.skipif(
4866    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.ZSTD, reason=REASON
4867)
4868def test_read_zstd():
4869    """Test read ZStd compression."""
4870    fname = public_file('GDAL/byte_zstd.tif')
4871    with TiffFile(fname) as tif:
4872        assert len(tif.pages) == 1
4873        page = tif.pages[0]
4874        assert page.compression == ZSTD
4875        assert page.photometric == MINISBLACK
4876        assert page.planarconfig == CONTIG
4877        assert page.imagewidth == 20
4878        assert page.imagelength == 20
4879        assert page.bitspersample == 8
4880        assert page.samplesperpixel == 1
4881        # assert data
4882        image = tif.asarray()  # fails with imagecodecs <= 2018.11.8
4883        assert image.flags['C_CONTIGUOUS']
4884        assert image.shape == (20, 20)
4885        assert image.dtype == numpy.uint8
4886        assert image[18, 1] == 247
4887        assert_aszarr_method(tif, image)
4888        assert__str__(tif)
4889
4890
4891@pytest.mark.skipif(
4892    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.LJPEG, reason=REASON
4893)
4894def test_read_dng():
4895    """Test read JPEG compressed CFA image in SubIFD."""
4896    fname = private_file('DNG/IMG_0793.DNG')
4897    with TiffFile(fname) as tif:
4898        assert len(tif.pages) == 1
4899        assert len(tif.series) == 2
4900        page = tif.pages[0]
4901        assert page.index == 0
4902        assert page.shape == (640, 852, 3)
4903        assert page.bitspersample == 8
4904        data = page.asarray()
4905        assert_aszarr_method(tif, data)
4906        page = tif.pages[0].pages[0]
4907        assert page.is_tiled
4908        assert page.index == (0, 0)
4909        assert page.compression == JPEG
4910        assert page.photometric == CFA
4911        assert page.shape == (3024, 4032)
4912        assert page.bitspersample == 16
4913        assert page.tags['CFARepeatPatternDim'].value == (2, 2)
4914        assert page.tags['CFAPattern'].value == b'\x00\x01\x01\x02'
4915        data = page.asarray()
4916        assert_aszarr_method(tif.series[1], data)
4917        assert__str__(tif)
4918
4919
4920@pytest.mark.skipif(
4921    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.LJPEG, reason=REASON
4922)
4923def test_read_cfa():
4924    """Test read 14-bit uncompressed and JPEG compressed CFA image."""
4925    fname = private_file('DNG/cinemadng/M14-1451_000085_cDNG_uncompressed.dng')
4926    with TiffFile(fname) as tif:
4927        assert len(tif.pages) == 1
4928        page = tif.pages[0]
4929        assert page.compression == 1
4930        assert page.photometric == CFA
4931        assert page.imagewidth == 960
4932        assert page.imagelength == 540
4933        assert page.bitspersample == 14
4934        assert page.tags['CFARepeatPatternDim'].value == (2, 2)
4935        assert page.tags['CFAPattern'].value == b'\x00\x01\x01\x02'
4936        data = page.asarray()
4937        assert_aszarr_method(tif, data)
4938
4939    fname = private_file('DNG/cinemadng/M14-1451_000085_cDNG_compressed.dng')
4940    with TiffFile(fname) as tif:
4941        assert len(tif.pages) == 1
4942        page = tif.pages[0]
4943        assert page.compression == JPEG
4944        assert page.photometric == CFA
4945        assert page.imagewidth == 960
4946        assert page.imagelength == 540
4947        assert page.bitspersample == 14
4948        assert page.tags['CFARepeatPatternDim'].value == (2, 2)
4949        assert page.tags['CFAPattern'].value == b'\x00\x01\x01\x02'
4950        image = page.asarray()
4951        assert_array_equal(image, data)
4952        assert_aszarr_method(tif, data)
4953
4954
4955@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4956def test_read_lena_be_f16_contig():
4957    """Test read big endian float16 horizontal differencing."""
4958    fname = private_file('PS/lena_be_f16_contig.tif')
4959    with TiffFile(fname) as tif:
4960        assert tif.byteorder == '>'
4961        assert len(tif.pages) == 1
4962        assert len(tif.series) == 1
4963        # assert page properties
4964        page = tif.pages[0]
4965        assert not page.is_reduced
4966        assert not page.is_tiled
4967        assert page.compression == NONE
4968        assert page.imagewidth == 512
4969        assert page.imagelength == 512
4970        assert page.bitspersample == 16
4971        assert page.samplesperpixel == 3
4972        # assert series properties
4973        series = tif.series[0]
4974        assert series.shape == (512, 512, 3)
4975        assert series.dtype == numpy.float16
4976        assert series.axes == 'YXS'
4977        # assert data
4978        data = tif.asarray(series=0)
4979        assert isinstance(data, numpy.ndarray)
4980        assert data.flags['C_CONTIGUOUS']
4981        assert data.shape == (512, 512, 3)
4982        assert data.dtype == numpy.float16
4983        assert_array_almost_equal(data[256, 256], (0.4563, 0.052856, 0.064819))
4984        assert_aszarr_method(tif, data, series=0)
4985        assert_decode_method(page)
4986        assert__str__(tif)
4987
4988
4989@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
4990def test_read_lena_be_f16_lzw_planar():
4991    """Test read big endian, float16, LZW, horizontal differencing."""
4992    fname = private_file('PS/lena_be_f16_lzw_planar.tif')
4993    with TiffFile(fname, is_imagej=False) as tif:
4994        assert tif.byteorder == '>'
4995        assert len(tif.pages) == 1
4996        assert len(tif.series) == 1
4997        assert not tif.is_imagej
4998        # assert page properties
4999        page = tif.pages[0]
5000        assert not page.is_reduced
5001        assert not page.is_tiled
5002        assert page.compression == LZW
5003        assert page.imagewidth == 512
5004        assert page.imagelength == 512
5005        assert page.bitspersample == 16
5006        assert page.samplesperpixel == 3
5007        # assert series properties
5008        series = tif.series[0]
5009        assert series.shape == (3, 512, 512)
5010        assert series.dtype == numpy.float16
5011        assert series.axes == 'SYX'
5012        # assert data
5013        data = tif.asarray(series=0)
5014        assert isinstance(data, numpy.ndarray)
5015        assert data.flags['C_CONTIGUOUS']
5016        assert data.shape == (3, 512, 512)
5017        assert data.dtype == numpy.float16
5018        assert_array_almost_equal(
5019            data[:, 256, 256], (0.4563, 0.052856, 0.064819)
5020        )
5021        assert_aszarr_method(tif, data, series=0)
5022        assert_decode_method(page)
5023        assert__str__(tif)
5024
5025
5026@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
5027def test_read_lena_be_f32_deflate_contig():
5028    """Test read big endian, float32 horizontal differencing, deflate."""
5029    fname = private_file('PS/lena_be_f32_deflate_contig.tif')
5030    with TiffFile(fname, is_imagej=False) as tif:
5031        assert tif.byteorder == '>'
5032        assert len(tif.pages) == 1
5033        assert len(tif.series) == 1
5034        assert not tif.is_imagej
5035        # assert page properties
5036        page = tif.pages[0]
5037        assert not page.is_reduced
5038        assert not page.is_tiled
5039        assert page.compression == ADOBE_DEFLATE
5040        assert page.imagewidth == 512
5041        assert page.imagelength == 512
5042        assert page.bitspersample == 32
5043        assert page.samplesperpixel == 3
5044        # assert series properties
5045        series = tif.series[0]
5046        assert series.shape == (512, 512, 3)
5047        assert series.dtype == numpy.float32
5048        assert series.axes == 'YXS'
5049        # assert data
5050        data = tif.asarray(series=0)
5051        assert isinstance(data, numpy.ndarray)
5052        assert data.flags['C_CONTIGUOUS']
5053        assert data.shape == (512, 512, 3)
5054        assert data.dtype == numpy.float32
5055        assert_array_almost_equal(
5056            data[256, 256], (0.456386, 0.052867, 0.064795)
5057        )
5058        assert_aszarr_method(tif, data, series=0)
5059        assert__str__(tif)
5060
5061
5062@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
5063def test_read_lena_le_f32_lzw_planar():
5064    """Test read little endian, LZW, float32 horizontal differencing."""
5065    fname = private_file('PS/lena_le_f32_lzw_planar.tif')
5066    with TiffFile(fname, is_imagej=False) as tif:
5067        assert tif.byteorder == '<'
5068        assert len(tif.pages) == 1
5069        assert len(tif.series) == 1
5070        assert not tif.is_imagej
5071        # assert page properties
5072        page = tif.pages[0]
5073        assert not page.is_reduced
5074        assert not page.is_tiled
5075        assert page.compression == LZW
5076        assert page.imagewidth == 512
5077        assert page.imagelength == 512
5078        assert page.bitspersample == 32
5079        assert page.samplesperpixel == 3
5080        # assert series properties
5081        series = tif.series[0]
5082        assert series.shape == (3, 512, 512)
5083        assert series.dtype == numpy.float32
5084        assert series.axes == 'SYX'
5085        # assert data
5086        data = tif.asarray(series=0)
5087        assert isinstance(data, numpy.ndarray)
5088        assert data.flags['C_CONTIGUOUS']
5089        assert data.shape == (3, 512, 512)
5090        assert data.dtype == numpy.float32
5091        assert_array_almost_equal(
5092            data[:, 256, 256], (0.456386, 0.052867, 0.064795)
5093        )
5094        assert_aszarr_method(tif, data, series=0)
5095        assert__str__(tif)
5096
5097
5098@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
5099def test_read_lena_be_rgb48():
5100    """Test read RGB48."""
5101    fname = private_file('PS/lena_be_rgb48.tif')
5102    with TiffFile(fname) as tif:
5103        assert tif.byteorder == '>'
5104        assert len(tif.pages) == 1
5105        assert len(tif.series) == 1
5106        # assert page properties
5107        page = tif.pages[0]
5108        assert not page.is_reduced
5109        assert not page.is_tiled
5110        assert page.compression == NONE
5111        assert page.imagewidth == 512
5112        assert page.imagelength == 512
5113        assert page.bitspersample == 16
5114        assert page.samplesperpixel == 3
5115        # assert series properties
5116        series = tif.series[0]
5117        assert series.shape == (512, 512, 3)
5118        assert series.dtype == numpy.uint16
5119        assert series.axes == 'YXS'
5120        # assert data
5121        data = tif.asarray(series=0)
5122        assert isinstance(data, numpy.ndarray)
5123        assert data.flags['C_CONTIGUOUS']
5124        assert data.shape == (512, 512, 3)
5125        assert data.dtype == numpy.uint16
5126        assert_array_equal(data[256, 256], (46259, 16706, 18504))
5127        assert_aszarr_method(tif, data, series=0)
5128        assert__str__(tif)
5129
5130
5131@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE or SKIP_PYPY, reason=REASON)
5132def test_read_huge_ps5_memmap():
5133    """Test read 30000x30000 float32 contiguous."""
5134    # TODO: segfault on pypy3.7-v7.3.5rc2-win64
5135    fname = private_file('large/huge_ps5.tif')
5136    with TiffFile(fname) as tif:
5137        assert tif.byteorder == '<'
5138        assert len(tif.pages) == 1
5139        assert len(tif.series) == 1
5140        # assert page properties
5141        page = tif.pages[0]
5142        assert page.is_contiguous == (21890, 3600000000)
5143        assert not page.is_memmappable  # data not aligned!
5144        assert page.compression == NONE
5145        assert page.imagewidth == 30000
5146        assert page.imagelength == 30000
5147        assert page.bitspersample == 32
5148        assert page.samplesperpixel == 1
5149        # assert series properties
5150        series = tif.series[0]
5151        assert series.shape == (30000, 30000)
5152        assert series.dtype == numpy.float32
5153        assert series.axes == 'YX'
5154        # assert data
5155        data = tif.asarray(out='memmap')  # memmap in a temp file
5156        assert isinstance(data, numpy.core.memmap)
5157        assert data.flags['C_CONTIGUOUS']
5158        assert data.shape == (30000, 30000)
5159        assert data.dtype == numpy.float32
5160        assert data[6597, 8135] == 0.008780896663665771
5161        assert_aszarr_method(tif, data)
5162        del data
5163        assert not tif.filehandle.closed
5164        assert__str__(tif)
5165
5166
5167@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
5168def test_read_movie():
5169    """Test read 30000 pages, uint16."""
5170    fname = public_file('tifffile/movie.tif')
5171    with TiffFile(fname) as tif:
5172        assert tif.byteorder == '<'
5173        assert len(tif.pages) == 30000
5174        assert len(tif.series) == 1
5175        assert tif.is_uniform
5176        # assert series properties
5177        series = tif.series[0]
5178        assert series.shape == (30000, 64, 64)
5179        assert series.dtype == numpy.uint16
5180        assert series.axes == 'IYX'
5181        # assert page properties
5182        page = tif.pages[-1]
5183        if tif.pages.cache:
5184            assert isinstance(page, TiffFrame)
5185        else:
5186            assert isinstance(page, TiffPage)
5187        assert page.shape == (64, 64)
5188        page = tif.pages[-3]
5189        if tif.pages.cache:
5190            assert isinstance(page, TiffFrame)
5191        else:
5192            assert isinstance(page, TiffPage)
5193        # assert data
5194        data = tif.pages[29999].asarray()  # last frame
5195        assert isinstance(data, numpy.ndarray)
5196        assert data.flags['C_CONTIGUOUS']
5197        assert data.shape == (64, 64)
5198        assert data.dtype == numpy.uint16
5199        assert data[32, 32] == 460
5200        del data
5201        # read selected pages
5202        # https://github.com/blink1073/tifffile/issues/51
5203        data = tif.asarray(key=[31, 999, 29999])
5204        assert data.flags['C_CONTIGUOUS']
5205        assert data.shape == (3, 64, 64)
5206        assert data[2, 32, 32] == 460
5207        del data
5208        assert__str__(tif, 0)
5209
5210
5211@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
5212def test_read_movie_memmap():
5213    """Test read 30000 pages memory-mapped."""
5214    fname = public_file('tifffile/movie.tif')
5215    with TiffFile(fname) as tif:
5216        # assert data
5217        data = tif.asarray(out='memmap')
5218        assert isinstance(data, numpy.core.memmap)
5219        assert data.flags['C_CONTIGUOUS']
5220        assert data.shape == (30000, 64, 64)
5221        assert data.dtype == numpy.dtype('<u2')
5222        assert data[29999, 32, 32] == 460
5223        del data
5224        assert not tif.filehandle.closed
5225        assert__str__(tif, 0)
5226
5227
5228@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
5229def test_read_100000_pages_movie():
5230    """Test read 100000x64x64 big endian in memory."""
5231    fname = public_file('tifffile/100000_pages.tif')
5232    with TiffFile(fname, _useframes=True) as tif:
5233        assert tif.is_imagej
5234        assert tif.byteorder == '>'
5235        assert len(tif.pages) == 100000
5236        assert len(tif.series) == 1
5237        # assert series properties
5238        series = tif.series[0]
5239        assert series.shape == (100000, 64, 64)
5240        assert series.dtype == numpy.uint16
5241        assert series.axes == 'TYX'
5242        # assert page properties
5243        page = tif.pages[100]
5244        assert isinstance(page, TiffFrame)  # uniform=True
5245        assert page.shape == (64, 64)
5246        page = tif.pages[0]
5247        assert page.imagewidth == 64
5248        assert page.imagelength == 64
5249        assert page.bitspersample == 16
5250        assert page.is_contiguous
5251        # assert ImageJ tags
5252        tags = tif.imagej_metadata
5253        assert tags['ImageJ'] == '1.48g'
5254        assert round(abs(tags['max'] - 119.0), 7) == 0
5255        assert round(abs(tags['min'] - 86.0), 7) == 0
5256        # assert data
5257        data = tif.asarray()
5258        assert data.flags['C_CONTIGUOUS']
5259        assert data.shape == (100000, 64, 64)
5260        assert data.dtype == numpy.uint16
5261        assert round(abs(data[7310, 25, 25] - 100), 7) == 0
5262        # too slow: assert_aszarr_method(tif, data)
5263        del data
5264        assert__str__(tif, 0)
5265
5266
5267@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
5268def test_read_chart_bl():
5269    """Test read 13228x18710, 1 bit, no bitspersample tag."""
5270    fname = public_file('tifffile/chart_bl.tif')
5271    with TiffFile(fname) as tif:
5272        assert tif.byteorder == '<'
5273        assert len(tif.pages) == 1
5274        assert len(tif.series) == 1
5275        # assert page properties
5276        page = tif.pages[0]
5277        assert page.compression == NONE
5278        assert page.imagewidth == 13228
5279        assert page.imagelength == 18710
5280        assert page.bitspersample == 1
5281        assert page.samplesperpixel == 1
5282        assert page.rowsperstrip == 18710
5283        # assert series properties
5284        series = tif.series[0]
5285        assert series.shape == (18710, 13228)
5286        assert series.dtype == numpy.bool8
5287        assert series.axes == 'YX'
5288        # assert data
5289        data = tif.asarray()
5290        assert isinstance(data, numpy.ndarray)
5291        assert data.flags['C_CONTIGUOUS']
5292        assert data.shape == (18710, 13228)
5293        assert data.dtype == numpy.bool8
5294        assert data[0, 0] is numpy.bool8(True)
5295        assert data[5000, 5000] is numpy.bool8(False)
5296        if not SKIP_LARGE:
5297            assert_aszarr_method(tif, data)
5298        assert__str__(tif)
5299
5300
5301@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
5302def test_read_srtm_20_13():
5303    """Test read 6000x6000 int16 GDAL."""
5304    fname = private_file('large/srtm_20_13.tif')
5305    with TiffFile(fname) as tif:
5306        assert tif.byteorder == '<'
5307        assert len(tif.pages) == 1
5308        assert len(tif.series) == 1
5309        # assert page properties
5310        page = tif.pages[0]
5311        assert page.is_contiguous
5312        assert page.compression == NONE
5313        assert page.imagewidth == 6000
5314        assert page.imagelength == 6000
5315        assert page.bitspersample == 16
5316        assert page.samplesperpixel == 1
5317        assert page.nodata == -32768
5318        assert page.tags['GDAL_NODATA'].value == '-32768'
5319        assert page.tags['GeoAsciiParamsTag'].value == 'WGS 84|'
5320        # assert series properties
5321        series = tif.series[0]
5322        assert series.shape == (6000, 6000)
5323        assert series.dtype == numpy.int16
5324        assert series.axes == 'YX'
5325        # assert data
5326        data = tif.asarray()
5327        assert isinstance(data, numpy.ndarray)
5328        assert data.flags['C_CONTIGUOUS']
5329        assert data.shape == (6000, 6000)
5330        assert data.dtype == numpy.int16
5331        assert data[5199, 5107] == 1019
5332        assert data[0, 0] == -32768
5333        assert_aszarr_method(tif, data)
5334        del data
5335        assert__str__(tif)
5336
5337
5338@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS or SKIP_LARGE, reason=REASON)
5339def test_read_gel_scan():
5340    """Test read 6976x4992x3 uint8 LZW."""
5341    fname = private_file('large/gel_1-scan2.tif')
5342    with TiffFile(fname) as tif:
5343        assert tif.byteorder == '<'
5344        assert len(tif.pages) == 1
5345        assert len(tif.series) == 1
5346        # assert page properties
5347        page = tif.pages[0]
5348        assert page.photometric == RGB
5349        assert page.compression == LZW
5350        assert page.imagewidth == 4992
5351        assert page.imagelength == 6976
5352        assert page.bitspersample == 8
5353        assert page.samplesperpixel == 3
5354        # assert series properties
5355        series = tif.series[0]
5356        assert series.shape == (6976, 4992, 3)
5357        assert series.dtype == numpy.uint8
5358        assert series.axes == 'YXS'
5359        # assert data
5360        data = tif.asarray()
5361        assert isinstance(data, numpy.ndarray)
5362        assert data.flags['C_CONTIGUOUS']
5363        assert data.shape == (6976, 4992, 3)
5364        assert data.dtype == numpy.uint8
5365        assert tuple(data[2229, 1080, :]) == (164, 164, 164)
5366        assert_aszarr_method(tif, data)
5367        del data
5368        assert__str__(tif)
5369
5370
5371@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
5372def test_read_caspian():
5373    """Test read 3x220x279 float64, RGB, deflate, GDAL."""
5374    fname = public_file('juicypixels/caspian.tif')
5375    with TiffFile(fname) as tif:
5376        assert tif.byteorder == '<'
5377        assert len(tif.pages) == 1
5378        assert len(tif.series) == 1
5379        # assert page properties
5380        page = tif.pages[0]
5381        assert page.photometric == RGB
5382        assert page.planarconfig == SEPARATE
5383        assert page.compression == DEFLATE
5384        assert page.imagewidth == 279
5385        assert page.imagelength == 220
5386        assert page.bitspersample == 64
5387        assert page.samplesperpixel == 3
5388        assert page.tags['GDAL_METADATA'].value.startswith('<GDALMetadata>')
5389        # assert series properties
5390        series = tif.series[0]
5391        assert series.shape == (3, 220, 279)
5392        assert series.dtype == numpy.float64
5393        assert series.axes == 'SYX'
5394        # assert data
5395        data = tif.asarray()
5396        assert isinstance(data, numpy.ndarray)
5397        assert data.flags['C_CONTIGUOUS']
5398        assert data.shape == (3, 220, 279)
5399        assert data.dtype == numpy.float64
5400        assert round(abs(data[2, 100, 140] - 353.0), 7) == 0
5401        assert_aszarr_method(tif, data)
5402        assert__str__(tif)
5403
5404
5405@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
5406def test_read_subifds_array():
5407    """Test read SubIFDs."""
5408    fname = public_file('Tiff-Library-4J/IFD struct/SubIFDs array E.tif')
5409    with TiffFile(fname) as tif:
5410        assert len(tif.pages) == 1
5411
5412        # make sure no pyramid was detected
5413        assert len(tif.series) == 5
5414        assert tif.series[0].shape == (1500, 2000, 3)
5415        assert tif.series[1].shape == (1200, 1600, 3)
5416        assert tif.series[2].shape == (900, 1200, 3)
5417        assert tif.series[3].shape == (600, 800, 3)
5418        assert tif.series[4].shape == (300, 400, 3)
5419
5420        page = tif.pages[0]
5421        assert page.photometric == RGB
5422        assert page.imagewidth == 2000
5423        assert page.imagelength == 1500
5424        assert page.bitspersample == 8
5425        assert page.samplesperpixel == 3
5426        assert page.tags['SubIFDs'].value == (
5427            14760220,
5428            18614796,
5429            19800716,
5430            18974964,
5431        )
5432        # assert subifds
5433        assert len(page.pages) == 4
5434        page = tif.pages[0].pages[0]
5435        assert page.photometric == RGB
5436        assert page.imagewidth == 1600
5437        assert page.imagelength == 1200
5438        assert_aszarr_method(page)
5439        page = tif.pages[0].pages[1]
5440        assert page.photometric == RGB
5441        assert page.imagewidth == 1200
5442        assert page.imagelength == 900
5443        assert_aszarr_method(page)
5444        page = tif.pages[0].pages[2]
5445        assert page.photometric == RGB
5446        assert page.imagewidth == 800
5447        assert page.imagelength == 600
5448        assert_aszarr_method(page)
5449        page = tif.pages[0].pages[3]
5450        assert page.photometric == RGB
5451        assert page.imagewidth == 400
5452        assert page.imagelength == 300
5453        assert_aszarr_method(page)
5454        # assert data
5455        image = page.asarray()
5456        assert image.flags['C_CONTIGUOUS']
5457        assert image.shape == (300, 400, 3)
5458        assert image.dtype == numpy.uint8
5459        assert tuple(image[124, 292]) == (236, 109, 95)
5460        assert__str__(tif)
5461
5462
5463@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
5464def test_read_subifd4():
5465    """Test read BigTIFFSubIFD4."""
5466    fname = public_file('twelvemonkeys/bigtiff/BigTIFFSubIFD4.tif')
5467    with TiffFile(fname) as tif:
5468        assert len(tif.series) == 1
5469        assert len(tif.pages) == 2
5470        page = tif.pages[0]
5471        assert page.photometric == RGB
5472        assert page.imagewidth == 64
5473        assert page.imagelength == 64
5474        assert page.bitspersample == 8
5475        assert page.samplesperpixel == 3
5476        assert page.tags['SubIFDs'].value == (3088,)
5477        # assert subifd
5478        page = page.pages[0]
5479        assert page.photometric == RGB
5480        assert page.imagewidth == 32
5481        assert page.imagelength == 32
5482        assert page.bitspersample == 8
5483        assert page.samplesperpixel == 3
5484        # assert data
5485        image = page.asarray()
5486        assert image.flags['C_CONTIGUOUS']
5487        assert image.shape == (32, 32, 3)
5488        assert image.dtype == numpy.uint8
5489        assert image[15, 15, 0] == 255
5490        assert image[16, 16, 2] == 0
5491        assert_aszarr_method(page)
5492        assert__str__(tif)
5493
5494
5495@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
5496def test_read_subifd8():
5497    """Test read BigTIFFSubIFD8."""
5498    fname = public_file('twelvemonkeys/bigtiff/BigTIFFSubIFD8.tif')
5499    with TiffFile(fname) as tif:
5500        assert len(tif.series) == 1
5501        assert len(tif.pages) == 2
5502        page = tif.pages[0]
5503        assert page.photometric == RGB
5504        assert page.imagewidth == 64
5505        assert page.imagelength == 64
5506        assert page.bitspersample == 8
5507        assert page.samplesperpixel == 3
5508        assert page.tags['SubIFDs'].value == (3088,)
5509        # assert subifd
5510        page = page.pages[0]
5511        assert page.photometric == RGB
5512        assert page.imagewidth == 32
5513        assert page.imagelength == 32
5514        assert page.bitspersample == 8
5515        assert page.samplesperpixel == 3
5516        # assert data
5517        image = page.asarray()
5518        assert image.flags['C_CONTIGUOUS']
5519        assert image.shape == (32, 32, 3)
5520        assert image.dtype == numpy.uint8
5521        assert image[15, 15, 0] == 255
5522        assert image[16, 16, 2] == 0
5523        assert_aszarr_method(page)
5524        assert__str__(tif)
5525
5526
5527@pytest.mark.skipif(SKIP_CODECS or not imagecodecs.JPEG, reason=REASON)
5528def test_read_tiles():
5529    """Test iteration over tiles, manually and via page.segments."""
5530    data = numpy.arange(600 * 500 * 3, dtype=numpy.uint8).reshape(
5531        (600, 500, 3)
5532    )
5533    with TempFileName('read_tiles') as fname:
5534        with TiffWriter(fname) as tif:
5535            options = dict(
5536                tile=(256, 256),
5537                photometric=RGB,
5538                compression=JPEG,
5539                metadata=None,
5540            )
5541            tif.write(data, **options)
5542            tif.write(data[::2, ::2], subfiletype=1, **options)
5543        with TiffFile(fname) as tif:
5544            fh = tif.filehandle
5545            for page in tif.pages:
5546                segments = page.segments()
5547                jpegtables = page.tags.get('JPEGTables', None)
5548                if jpegtables is not None:
5549                    jpegtables = jpegtables.value
5550                for index, (offset, bytecount) in enumerate(
5551                    zip(page.dataoffsets, page.databytecounts)
5552                ):
5553                    fh.seek(offset)
5554                    data = fh.read(bytecount)
5555                    tile, indices, shape = page.decode(data, index, jpegtables)
5556                    assert_array_equal(tile, next(segments)[0])
5557
5558
5559@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
5560def test_read_lsm_mosaic():
5561    """Test read LSM: PTZCYX (Mosaic mode), two areas, 32 samples, >4 GB."""
5562    # LSM files are little endian with two series, one of which is reduced RGB
5563    # Tags may be unordered or contain bogus values
5564    fname = private_file(
5565        'lsm/Twoareas_Zstacks54slices_3umintervals_5cycles.lsm'
5566    )
5567    with TiffFile(fname) as tif:
5568        assert tif.is_lsm
5569        assert tif.byteorder == '<'
5570        assert len(tif.pages) == 1080
5571        assert len(tif.series) == 2
5572        # assert page properties
5573        page = tif.pages[0]
5574        assert page.is_lsm
5575        assert page.is_contiguous
5576        assert page.compression == NONE
5577        assert page.imagewidth == 512
5578        assert page.imagelength == 512
5579        assert page.bitspersample == 16
5580        assert page.samplesperpixel == 32
5581        # assert strip offsets are corrected
5582        page = tif.pages[-2]
5583        assert page.dataoffsets[0] == 9070895981
5584        # assert series properties
5585        series = tif.series[0]
5586        assert series.shape == (2, 5, 54, 32, 512, 512)
5587        assert series.dtype == numpy.uint16
5588        assert series.axes == 'PTZCYX'
5589        if 1:
5590            series = tif.series[1]
5591            assert series.shape == (2, 5, 54, 3, 128, 128)
5592            assert series.dtype == numpy.uint8
5593            assert series.axes == 'PTZSYX'
5594        # assert lsm_info tags
5595        tags = tif.lsm_metadata
5596        assert tags['DimensionX'] == 512
5597        assert tags['DimensionY'] == 512
5598        assert tags['DimensionZ'] == 54
5599        assert tags['DimensionTime'] == 5
5600        assert tags['DimensionChannels'] == 32
5601        # assert lsm_scan_info tags
5602        tags = tif.lsm_metadata['ScanInformation']
5603        assert tags['ScanMode'] == 'Stack'
5604        assert tags['User'] == 'lfdguest1'
5605        # very slow: assert_aszarr_method(tif)
5606        assert__str__(tif, 0)
5607
5608
5609@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
5610def test_read_lsm_carpet():
5611    """Test read LSM: ZCTYX (time series x-y), 72000 pages."""
5612    # reads very slowly, ensure colormap is not applied
5613    fname = private_file('lsm/Cardarelli_carpet_3.lsm')
5614    with TiffFile(fname) as tif:
5615        assert tif.is_lsm
5616        assert tif.byteorder == '<'
5617        assert len(tif.pages) == 72000
5618        assert len(tif.series) == 2
5619        # assert page properties
5620        page = tif.pages[0]
5621        assert page.is_lsm
5622        assert 'ColorMap' in page.tags
5623        assert page.photometric == PALETTE
5624        assert page.compression == NONE
5625        assert page.imagewidth == 32
5626        assert page.imagelength == 10
5627        assert page.bitspersample == 8
5628        assert page.samplesperpixel == 1
5629        # assert series properties
5630        series = tif.series[0]
5631        assert series.dtype == numpy.uint8
5632        assert series.shape == (36000, 10, 32)
5633        assert series.axes == 'TYX'
5634        assert series.get_shape(False) == (1, 1, 36000, 10, 32)
5635        assert series.get_axes(False) == 'ZCTYX'
5636        if 1:
5637            series = tif.series[1]
5638            assert series.dtype == numpy.uint8
5639            assert series.shape == (36000, 3, 40, 128)
5640            assert series.axes == 'TSYX'
5641            assert series.get_shape(False) == (1, 1, 36000, 3, 40, 128)
5642            assert series.get_axes(False) == 'ZCTSYX'
5643        # assert lsm_info tags
5644        tags = tif.lsm_metadata
5645        assert tags['DimensionX'] == 32
5646        assert tags['DimensionY'] == 10
5647        assert tags['DimensionZ'] == 1
5648        assert tags['DimensionTime'] == 36000
5649        assert tags['DimensionChannels'] == 1
5650        # assert lsm_scan_info tags
5651        tags = tif.lsm_metadata['ScanInformation']
5652        assert tags['ScanMode'] == 'Plane'
5653        assert tags['User'] == 'LSM User'
5654        # assert_aszarr_method(tif)
5655        assert__str__(tif, 0)
5656
5657
5658@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
5659def test_read_lsm_take1():
5660    """Test read LSM: TCZYX (Plane mode), single image, uint8."""
5661    fname = private_file('lsm/take1.lsm')
5662    with TiffFile(fname) as tif:
5663        assert tif.is_lsm
5664        assert tif.byteorder == '<'
5665        assert len(tif.pages) == 2
5666        assert len(tif.series) == 2
5667        # assert page properties
5668        page = tif.pages[0]
5669        assert page.is_lsm
5670        assert page.is_contiguous
5671        assert page.compression == NONE
5672        assert page.imagewidth == 512
5673        assert page.imagelength == 512
5674        assert page.bitspersample == 8
5675        assert page.samplesperpixel == 1
5676        page = tif.pages[1]
5677        assert page.is_reduced
5678        assert page.photometric == RGB
5679        assert page.planarconfig == SEPARATE
5680        assert page.compression == NONE
5681        assert page.imagewidth == 128
5682        assert page.imagelength == 128
5683        assert page.samplesperpixel == 3
5684        assert page.bitspersample == 8
5685        # assert series properties
5686        series = tif.series[0]
5687        assert series.dtype == numpy.uint8
5688        assert series.shape == (512, 512)
5689        assert series.axes == 'YX'
5690        assert series.get_shape(False) == (1, 1, 1, 512, 512)
5691        assert series.get_axes(False) == 'TCZYX'
5692        if 1:
5693            series = tif.series[1]
5694            assert series.shape == (3, 128, 128)
5695            assert series.dtype == numpy.uint8
5696            assert series.axes == 'SYX'
5697        # assert data
5698        data = tif.asarray()
5699        assert isinstance(data, numpy.ndarray)
5700        assert data.flags['C_CONTIGUOUS']
5701        assert data.shape == (512, 512)
5702        assert data.dtype == numpy.uint8
5703        assert data[..., 256, 256] == 101
5704        if 1:
5705            data = tif.asarray(series=1)
5706            assert isinstance(data, numpy.ndarray)
5707            assert data.shape == (3, 128, 128)
5708            assert data.dtype == numpy.uint8
5709            assert tuple(data[..., 64, 64]) == (89, 89, 89)
5710        # assert lsm_info tags
5711        tags = tif.lsm_metadata
5712        assert tags['DimensionX'] == 512
5713        assert tags['DimensionY'] == 512
5714        assert tags['DimensionZ'] == 1
5715        assert tags['DimensionTime'] == 1
5716        assert tags['DimensionChannels'] == 1
5717        # assert lsm_scan_info tags
5718        tags = tif.lsm_metadata['ScanInformation']
5719        assert tags['ScanMode'] == 'Plane'
5720        assert tags['User'] == 'LSM User'
5721        assert len(tags['Tracks']) == 1
5722        assert len(tags['Tracks'][0]['DataChannels']) == 1
5723        track = tags['Tracks'][0]
5724        assert track['DataChannels'][0]['Name'] == 'Ch1'
5725        assert track['DataChannels'][0]['BitsPerSample'] == 8
5726        assert len(track['IlluminationChannels']) == 1
5727        assert track['IlluminationChannels'][0]['Name'] == '561'
5728        assert track['IlluminationChannels'][0]['Wavelength'] == 561.0
5729        assert_aszarr_method(tif)
5730        assert_aszarr_method(tif, series=1)
5731        assert__str__(tif)
5732
5733
5734@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
5735def test_read_lsm_2chzt():
5736    """Test read LSM: ZCYX (Stack mode) uint8."""
5737    fname = public_file('scif.io/2chZT.lsm')
5738    with TiffFile(fname) as tif:
5739        assert tif.is_lsm
5740        assert tif.byteorder == '<'
5741        assert len(tif.pages) == 798
5742        assert len(tif.series) == 2
5743        # assert page properties
5744        page = tif.pages[0]
5745        assert page.is_lsm
5746        assert page.is_contiguous
5747        assert page.photometric == RGB
5748        assert page.tags['StripOffsets'].value[2] == 242632  # bogus offset
5749        assert page.tags['StripByteCounts'].value[2] == 0  # no strip data
5750        assert page.compression == NONE
5751        assert page.imagewidth == 400
5752        assert page.imagelength == 300
5753        assert page.bitspersample == 8
5754        assert page.samplesperpixel == 2
5755
5756        page = tif.pages[1]
5757        assert page.is_reduced
5758        assert page.photometric == RGB
5759        assert page.planarconfig == SEPARATE
5760        assert page.is_contiguous
5761        assert page.compression == NONE
5762        assert page.imagewidth == 128
5763        assert page.imagelength == 96
5764        assert page.samplesperpixel == 3
5765        assert page.bitspersample == 8
5766        # assert series properties
5767        series = tif.series[0]
5768        assert series.shape == (19, 21, 2, 300, 400)
5769        assert series.dtype == numpy.uint8
5770        assert series.axes == 'TZCYX'
5771        if 1:
5772            series = tif.series[1]
5773            assert series.shape == (19, 21, 3, 96, 128)
5774            assert series.dtype == numpy.uint8
5775            assert series.axes == 'TZSYX'
5776        # assert data
5777        data = tif.asarray(out='memmap')
5778        assert isinstance(data, numpy.core.memmap)
5779        assert data.flags['C_CONTIGUOUS']
5780        assert data.shape == (19, 21, 2, 300, 400)
5781        assert data.dtype == numpy.uint8
5782        assert data[18, 20, 1, 199, 299] == 39
5783        if 1:
5784            data = tif.asarray(series=1)
5785            assert isinstance(data, numpy.ndarray)
5786            assert data.shape == (19, 21, 3, 96, 128)
5787            assert data.dtype == numpy.uint8
5788            assert tuple(data[18, 20, :, 64, 96]) == (22, 22, 0)
5789        del data
5790        # assert lsm_info tags
5791        tags = tif.lsm_metadata
5792        assert tags['DimensionX'] == 400
5793        assert tags['DimensionY'] == 300
5794        assert tags['DimensionZ'] == 21
5795        assert tags['DimensionTime'] == 19
5796        assert tags['DimensionChannels'] == 2
5797        # assert lsm_scan_info tags
5798        tags = tif.lsm_metadata['ScanInformation']
5799        assert tags['ScanMode'] == 'Stack'
5800        assert tags['User'] == 'zjfhe'
5801        assert len(tags['Tracks']) == 3
5802        assert len(tags['Tracks'][0]['DataChannels']) == 1
5803        track = tags['Tracks'][0]
5804        assert track['DataChannels'][0]['Name'] == 'Ch3'
5805        assert track['DataChannels'][0]['BitsPerSample'] == 8
5806        assert len(track['IlluminationChannels']) == 6
5807        assert track['IlluminationChannels'][5]['Name'] == '488'
5808        assert track['IlluminationChannels'][5]['Wavelength'] == 488.0
5809        assert_aszarr_method(tif)
5810        assert_aszarr_method(tif, series=1)
5811        assert__str__(tif, 0)
5812
5813
5814@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
5815def test_read_lsm_earpax2isl11():
5816    """Test read LSM: TZCYX (1, 19, 3, 512, 512) uint8, RGB, LZW."""
5817    fname = private_file('lsm/earpax2isl11.lzw.lsm')
5818    with TiffFile(fname) as tif:
5819        assert tif.is_lsm
5820        assert tif.byteorder == '<'
5821        assert len(tif.pages) == 38
5822        assert len(tif.series) == 2
5823        # assert page properties
5824        page = tif.pages[0]
5825        assert page.is_lsm
5826        assert not page.is_contiguous
5827        assert page.photometric == RGB
5828        assert page.compression == LZW
5829        assert page.imagewidth == 512
5830        assert page.imagelength == 512
5831        assert page.bitspersample == 8
5832        assert page.samplesperpixel == 3
5833        # assert corrected strip_byte_counts
5834        assert page.tags['StripByteCounts'].value == (262144, 262144, 262144)
5835        assert page.databytecounts == (131514, 192933, 167874)
5836        page = tif.pages[1]
5837        assert page.is_reduced
5838        assert page.photometric == RGB
5839        assert page.planarconfig == SEPARATE
5840        assert page.compression == NONE
5841        assert page.imagewidth == 128
5842        assert page.imagelength == 128
5843        assert page.samplesperpixel == 3
5844        assert page.bitspersample == 8
5845        # assert series properties
5846        series = tif.series[0]
5847        assert series.shape == (19, 3, 512, 512)
5848        assert series.get_shape(False) == (1, 19, 3, 512, 512)
5849        assert series.dtype == numpy.uint8
5850        assert series.axes == 'ZCYX'
5851        assert series.get_axes(False) == 'TZCYX'
5852        if 1:
5853            series = tif.series[1]
5854            assert series.shape == (19, 3, 128, 128)
5855            assert series.get_shape(False) == (1, 19, 3, 128, 128)
5856            assert series.dtype == numpy.uint8
5857            assert series.axes == 'ZSYX'
5858            assert series.get_axes(False) == 'TZSYX'
5859        # assert data
5860        data = tif.asarray()
5861        assert isinstance(data, numpy.ndarray)
5862        assert data.flags['C_CONTIGUOUS']
5863        assert data.shape == (19, 3, 512, 512)
5864        assert data.dtype == numpy.uint8
5865        assert tuple(data[18, :, 200, 320]) == (17, 22, 21)
5866        assert_aszarr_method(tif, data)
5867        if 1:
5868            data = tif.asarray(series=1)
5869            assert isinstance(data, numpy.ndarray)
5870            assert data.shape == (19, 3, 128, 128)
5871            assert data.dtype == numpy.uint8
5872            assert tuple(data[18, :, 64, 64]) == (25, 5, 33)
5873            assert_aszarr_method(tif, series=1)
5874        # assert lsm_info tags
5875        tags = tif.lsm_metadata
5876        assert tags['DimensionX'] == 512
5877        assert tags['DimensionY'] == 512
5878        assert tags['DimensionZ'] == 19
5879        assert tags['DimensionTime'] == 1
5880        assert tags['DimensionChannels'] == 3
5881        # assert lsm_scan_info tags
5882        tags = tif.lsm_metadata['ScanInformation']
5883        assert tags['ScanMode'] == 'Stack'
5884        assert tags['User'] == 'megason'
5885        assert__str__(tif)
5886
5887
5888@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS or SKIP_LARGE, reason=REASON)
5889def test_read_lsm_mb231paxgfp_060214():
5890    """Test read LSM with many LZW compressed pages."""
5891    # TZCYX (Stack mode), (60, 31, 2, 512, 512), 3720
5892    fname = public_file('tifffile/MB231paxgfp_060214.lzw.lsm')
5893    with TiffFile(fname) as tif:
5894        assert tif.is_lsm
5895        assert tif.byteorder == '<'
5896        assert len(tif.pages) == 3720
5897        assert len(tif.series) == 2
5898        # assert page properties
5899        page = tif.pages[0]
5900        assert page.is_lsm
5901        assert not page.is_contiguous
5902        assert page.compression == LZW
5903        assert page.imagewidth == 512
5904        assert page.imagelength == 512
5905        assert page.bitspersample == 16
5906        assert page.samplesperpixel == 2
5907        page = tif.pages[1]
5908        assert page.is_reduced
5909        assert page.photometric == RGB
5910        assert page.planarconfig == SEPARATE
5911        assert page.compression == NONE
5912        assert page.imagewidth == 128
5913        assert page.imagelength == 128
5914        assert page.samplesperpixel == 3
5915        assert page.bitspersample == 8
5916        # assert series properties
5917        series = tif.series[0]
5918        assert series.dtype == numpy.uint16
5919        assert series.shape == (60, 31, 2, 512, 512)
5920        assert series.get_shape(False) == (60, 31, 2, 512, 512)
5921        assert series.axes == 'TZCYX'
5922        assert series.get_axes(False) == 'TZCYX'
5923        if 1:
5924            series = tif.series[1]
5925            assert series.dtype == numpy.uint8
5926            assert series.shape == (60, 31, 3, 128, 128)
5927            assert series.axes == 'TZSYX'
5928        # assert data
5929        data = tif.asarray(out='memmap', maxworkers=None)
5930        assert isinstance(data, numpy.core.memmap)
5931        assert data.flags['C_CONTIGUOUS']
5932        assert data.shape == (60, 31, 2, 512, 512)
5933        assert data.dtype == numpy.dtype('<u2')
5934        assert data[59, 30, 1, 256, 256] == 222
5935        del data
5936        # assert lsm_info tags
5937        tags = tif.lsm_metadata
5938        assert tags['DimensionX'] == 512
5939        assert tags['DimensionY'] == 512
5940        assert tags['DimensionZ'] == 31
5941        assert tags['DimensionTime'] == 60
5942        assert tags['DimensionChannels'] == 2
5943        # assert some lsm_scan_info tags
5944        tags = tif.lsm_metadata['ScanInformation']
5945        assert tags['ScanMode'] == 'Stack'
5946        assert tags['User'] == 'lfdguest1'
5947        assert__str__(tif, 0)
5948
5949
5950@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
5951def test_read_lsm_lzw_no_eoi():
5952    """Test read LSM with LZW compressed strip without EOI."""
5953    # The first LZW compressed strip in page 834 has no EOI
5954    # such that too much data is returned from the decoder and
5955    # the data of the 2nd channel was getting corrupted
5956    fname = public_file('tifffile/MB231paxgfp_060214.lzw.lsm')
5957    with TiffFile(fname) as tif:
5958        assert tif.is_lsm
5959        assert tif.byteorder == '<'
5960        assert len(tif.pages) == 3720
5961        assert len(tif.series) == 2
5962        # assert page properties
5963        page = tif.pages[0]
5964        assert not page.is_contiguous
5965        assert page.photometric == RGB
5966        assert page.compression == LZW
5967        assert page.imagewidth == 512
5968        assert page.imagelength == 512
5969        assert page.bitspersample == 16
5970        assert page.samplesperpixel == 2
5971        page = tif.pages[834]
5972        assert isinstance(page, TiffFrame)
5973        assert page.dataoffsets == (344655101, 345109987)
5974        assert page.databytecounts == (454886, 326318)
5975        # assert second channel is not corrupted
5976        data = page.asarray()
5977        assert tuple(data[:, 0, 0]) == (288, 238)
5978        assert__str__(tif, 0)
5979
5980
5981@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
5982def test_read_stk_zseries():
5983    """Test read MetaMorph STK z-series."""
5984    fname = private_file('stk/zseries.stk')
5985    with TiffFile(fname) as tif:
5986        assert tif.is_stk
5987        assert tif.byteorder == '<'
5988        assert len(tif.pages) == 1
5989        assert len(tif.series) == 1
5990        # assert page properties
5991        page = tif.pages[0]
5992        assert page.is_contiguous
5993        assert page.compression == NONE
5994        assert page.imagewidth == 320
5995        assert page.imagelength == 256
5996        assert page.bitspersample == 16
5997        assert page.samplesperpixel == 1
5998        assert page.tags['Software'].value == 'MetaMorph'
5999        assert page.tags['DateTime'].value == '2000:01:02 15:06:33'
6000        assert page.description.startswith('Acquired from MV-1500')
6001        # assert uic tags
6002        tags = tif.stk_metadata
6003        assert tags['Name'] == 'Z Series'
6004        assert tags['NumberPlanes'] == 11
6005        assert ''.join(tags['StageLabel']) == ''
6006        assert tags['ZDistance'][10] == 2.5
6007        assert len(tags['Wavelengths']) == 11
6008        assert tags['Wavelengths'][10] == 490.0
6009        assert len(tags['AbsoluteZ']) == 11
6010        assert tags['AbsoluteZ'][10] == 150.0
6011        assert tuple(tags['StagePosition'][10]) == (0.0, 0.0)
6012        assert tuple(tags['CameraChipOffset'][10]) == (0.0, 0.0)
6013        assert tags['PlaneDescriptions'][0].startswith('Acquired from MV-1500')
6014        assert str(tags['DatetimeCreated'][0]) == (
6015            '2000-02-02T15:06:02.000783000'
6016        )
6017        # assert series properties
6018        series = tif.series[0]
6019        assert series.shape == (11, 256, 320)
6020        assert series.dtype == numpy.uint16
6021        assert series.axes == 'ZYX'
6022        # assert data
6023        data = tif.asarray()
6024        assert isinstance(data, numpy.ndarray)
6025        assert data.shape == (11, 256, 320)
6026        assert data.dtype == numpy.uint16
6027        assert data[8, 159, 255] == 1156
6028        assert_aszarr_method(tif, data)
6029        assert_decode_method(page)
6030        assert__str__(tif)
6031
6032
6033@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6034def test_read_stk_zser24():
6035    """Test read MetaMorph STK RGB z-series."""
6036    fname = private_file('stk/zser24.stk')
6037    with TiffFile(fname) as tif:
6038        assert tif.is_stk
6039        assert tif.byteorder == '<'
6040        assert len(tif.pages) == 1
6041        assert len(tif.series) == 1
6042        # assert page properties
6043        page = tif.pages[0]
6044        assert page.is_contiguous
6045        assert page.photometric == RGB
6046        assert page.compression == NONE
6047        assert page.imagewidth == 160
6048        assert page.imagelength == 128
6049        assert page.bitspersample == 8
6050        assert page.samplesperpixel == 3
6051        assert page.tags['Software'].value == 'MetaMorph'
6052        assert page.tags['DateTime'].value == '2000:01:02 15:11:23'
6053        # assert uic tags
6054        tags = tif.stk_metadata
6055        assert tags['Name'] == 'Color Encoded'
6056        assert tags['NumberPlanes'] == 11
6057        assert ''.join(tags['StageLabel']) == ''
6058        assert tags['ZDistance'][10] == 2.5
6059        assert len(tags['Wavelengths']) == 11
6060        assert tags['Wavelengths'][10] == 510.0
6061        assert len(tags['AbsoluteZ']) == 11
6062        assert tags['AbsoluteZ'][10] == 150.0
6063        assert tuple(tags['StagePosition'][10]) == (0.0, 0.0)
6064        assert tuple(tags['CameraChipOffset'][10]) == (320.0, 256.0)
6065        assert str(tags['DatetimeCreated'][0]) == (
6066            '2000-02-02T15:10:34.000264000'
6067        )
6068        # assert series properties
6069        series = tif.series[0]
6070        assert series.shape == (11, 128, 160, 3)
6071        assert series.dtype == numpy.uint8
6072        assert series.axes == 'ZYXS'
6073        # assert data
6074        data = tif.asarray()
6075        assert isinstance(data, numpy.ndarray)
6076        assert data.shape == (11, 128, 160, 3)
6077        assert data.dtype == numpy.uint8
6078        assert tuple(data[8, 100, 135]) == (70, 63, 0)
6079        assert_aszarr_method(tif, data)
6080        assert_decode_method(page)
6081        assert__str__(tif)
6082
6083
6084@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6085def test_read_stk_diatoms3d():
6086    """Test read MetaMorph STK time-series."""
6087    fname = private_file('stk/diatoms3d.stk')
6088    with TiffFile(fname) as tif:
6089        assert tif.is_stk
6090        assert tif.byteorder == '<'
6091        assert len(tif.pages) == 1
6092        assert len(tif.series) == 1
6093        # assert page properties
6094        page = tif.pages[0]
6095        assert page.is_contiguous
6096        assert page.compression == NONE
6097        assert page.imagewidth == 196
6098        assert page.imagelength == 191
6099        assert page.bitspersample == 8
6100        assert page.samplesperpixel == 1
6101        assert page.tags['Software'].value == 'MetaMorph'
6102        assert page.tags['DateTime'].value == '2000:01:04 14:57:22'
6103        # assert uic tags
6104        tags = tif.stk_metadata
6105        assert tags['Name'] == 'diatoms3d'
6106        assert tags['NumberPlanes'] == 10
6107        assert ''.join(tags['StageLabel']) == ''
6108        assert tags['ZDistance'][9] == 3.54545
6109        assert len(tags['Wavelengths']) == 10
6110        assert tags['Wavelengths'][9] == 440.0
6111        assert len(tags['AbsoluteZ']) == 10
6112        assert tags['AbsoluteZ'][9] == 12898.15
6113        assert tuple(tags['StagePosition'][9]) == (0.0, 0.0)
6114        assert tuple(tags['CameraChipOffset'][9]) == (206.0, 148.0)
6115        assert tags['PlaneDescriptions'][0].startswith(
6116            'Acquired from Flashbus.'
6117        )
6118        assert str(tags['DatetimeCreated'][0]) == (
6119            '2000-02-04T14:38:37.000738000'
6120        )
6121        # assert series properties
6122        series = tif.series[0]
6123        assert series.shape == (10, 191, 196)
6124        assert series.dtype == numpy.uint8
6125        assert series.axes == 'ZYX'
6126        # assert data
6127        data = tif.asarray()
6128        assert isinstance(data, numpy.ndarray)
6129        assert data.shape == (10, 191, 196)
6130        assert data.dtype == numpy.uint8
6131        assert data[8, 100, 135] == 223
6132        assert_aszarr_method(tif, data)
6133        assert_decode_method(page)
6134        assert__str__(tif)
6135
6136
6137@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6138def test_read_stk_greenbeads():
6139    """Test read MetaMorph STK time-series, but time_created is corrupt (?)."""
6140    # 8bit palette is present but should not be applied
6141    fname = private_file('stk/greenbeads.stk')
6142    with TiffFile(fname) as tif:
6143        assert tif.is_stk
6144        assert tif.byteorder == '<'
6145        assert len(tif.pages) == 1
6146        assert len(tif.series) == 1
6147        # assert page properties
6148        page = tif.pages[0]
6149        assert page.is_contiguous
6150        assert page.photometric == PALETTE
6151        assert page.compression == NONE
6152        assert page.imagewidth == 298
6153        assert page.imagelength == 322
6154        assert page.bitspersample == 8
6155        assert page.samplesperpixel == 1
6156        assert page.tags['Software'].value == 'MetaMorph 7.5.3.0'
6157        assert page.tags['DateTime'].value == '2008:05:09 17:35:32'
6158        # assert uic tags
6159        tags = tif.stk_metadata
6160        assert tags['Name'] == 'Green'
6161        assert tags['NumberPlanes'] == 79
6162        assert tags['ZDistance'][1] == 0.0
6163        assert len(tags['Wavelengths']) == 79
6164        assert tuple(tags['CameraChipOffset'][0]) == (0.0, 0.0)
6165        assert str(tags['DatetimeModified'][0]) == (
6166            '2008-05-09T17:35:33.000274000'
6167        )
6168        assert 'AbsoluteZ' not in tags
6169        # assert series properties
6170        series = tif.series[0]
6171        assert series.shape == (79, 322, 298)
6172        assert series.dtype == numpy.uint8
6173        assert series.axes == 'IYX'  # corrupt time_created
6174        # assert data
6175        data = tif.asarray()
6176        assert isinstance(data, numpy.ndarray)
6177        assert data.shape == (79, 322, 298)
6178        assert data.dtype == numpy.uint8
6179        assert data[43, 180, 102] == 205
6180        assert_aszarr_method(tif, data)
6181        assert__str__(tif)
6182
6183
6184@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6185def test_read_stk_10xcalib():
6186    """Test read MetaMorph STK two planes, not Z or T series."""
6187    fname = private_file('stk/10xcalib.stk')
6188    with TiffFile(fname) as tif:
6189        assert tif.is_stk
6190        assert tif.byteorder == '<'
6191        assert len(tif.pages) == 1
6192        assert len(tif.series) == 1
6193        # assert page properties
6194        page = tif.pages[0]
6195        assert page.is_contiguous
6196        assert page.photometric != PALETTE
6197        assert page.compression == NONE
6198        assert page.imagewidth == 640
6199        assert page.imagelength == 480
6200        assert page.bitspersample == 8
6201        assert page.samplesperpixel == 1
6202        assert page.tags['Software'].value == 'MetaMorph'
6203        assert page.tags['DateTime'].value == '2000:03:28 09:24:37'
6204        # assert uic tags
6205        tags = tif.stk_metadata
6206        assert tags['Name'] == '10xcalib'
6207        assert tags['NumberPlanes'] == 2
6208        assert tuple(tags['Wavelengths']) == (440.0, 440.0)
6209        assert tags['XCalibration'] == 1.24975007
6210        assert tags['YCalibration'] == 1.24975007
6211        # assert series properties
6212        series = tif.series[0]
6213        assert series.shape == (2, 480, 640)
6214        assert series.dtype == numpy.uint8
6215        assert series.axes == 'IYX'
6216        # assert data
6217        data = tif.asarray()
6218        assert isinstance(data, numpy.ndarray)
6219        assert data.shape == (2, 480, 640)
6220        assert data.dtype == numpy.uint8
6221        assert data[1, 339, 579] == 56
6222        assert_aszarr_method(tif, data)
6223        assert__str__(tif)
6224
6225
6226@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
6227def test_read_stk_112508h100():
6228    """Test read MetaMorph STK large time-series."""
6229    fname = private_file('stk/112508h100.stk')
6230    with TiffFile(fname) as tif:
6231        assert tif.is_stk
6232        assert tif.byteorder == '<'
6233        assert len(tif.pages) == 1
6234        assert len(tif.series) == 1
6235        # assert page properties
6236        page = tif.pages[0]
6237        assert page.is_contiguous
6238        assert page.photometric != PALETTE
6239        assert page.compression == NONE
6240        assert page.imagewidth == 512
6241        assert page.imagelength == 128
6242        assert page.bitspersample == 16
6243        assert page.samplesperpixel == 1
6244        assert page.tags['Software'].value == 'MetaMorph 7.5.3.0'
6245        assert page.tags['DateTime'].value == '2008:11:25 18:59:20'
6246        # assert uic tags
6247        tags = tif.stk_metadata
6248        assert tags['Name'] == 'Photometrics'
6249        assert tags['NumberPlanes'] == 2048
6250        assert len(tags['PlaneDescriptions']) == 2048
6251        assert tags['PlaneDescriptions'][0].startswith(
6252            'Acquired from Photometrics\r\n'
6253        )
6254        assert tags['CalibrationUnits'] == 'pixel'
6255        # assert series properties
6256        series = tif.series[0]
6257        assert series.shape == (2048, 128, 512)
6258        assert series.dtype == numpy.uint16
6259        assert series.axes == 'TYX'
6260        # assert data
6261        data = tif.asarray()
6262        assert isinstance(data, numpy.ndarray)
6263        assert data.shape == (2048, 128, 512)
6264        assert data.dtype == numpy.uint16
6265        assert data[2047, 64, 128] == 7132
6266        assert_aszarr_method(tif, data)
6267        assert__str__(tif)
6268
6269
6270@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
6271def test_read_stk_noname():
6272    """Test read MetaMorph STK with no name in metadata."""
6273    # https://forum.image.sc/t/metamorph-stack-issue-with-ome-metadata-
6274    # bioformats-and-omero/48416
6275    fname = private_file('stk/60x_2well_diffexpos1_w1sdcGFP_s1_t1.stk')
6276    with TiffFile(fname) as tif:
6277        assert tif.is_stk
6278        assert tif.byteorder == '<'
6279        assert len(tif.pages) == 1
6280        assert len(tif.series) == 1
6281        # assert page properties
6282        page = tif.pages[0]
6283        assert page.is_contiguous
6284        assert page.photometric == MINISBLACK
6285        assert page.compression == NONE
6286        assert page.imagewidth == 1148
6287        assert page.imagelength == 1112
6288        assert page.bitspersample == 16
6289        assert page.samplesperpixel == 1
6290        assert page.tags['Software'].value == 'VisiView 4.5.0'
6291        assert page.tags['DateTime'].value == '2021:01:27 13:29:51'
6292        # assert uic tags
6293        tags = tif.stk_metadata
6294        assert 'Name' not in tags
6295        assert tags['NumberPlanes'] == 5
6296        assert len(tags['PlaneDescriptions']) == 5
6297        assert tags['PlaneDescriptions'][0].startswith('Exposure: 50 ms\r\n')
6298        # assert series properties
6299        series = tif.series[0]
6300        assert series.shape == (5, 1112, 1148)
6301        assert series.dtype == numpy.uint16
6302        assert series.axes == 'ZYX'
6303        # assert data
6304        data = tif.asarray()
6305        assert isinstance(data, numpy.ndarray)
6306        assert data.shape == (5, 1112, 1148)
6307        assert data.dtype == numpy.uint16
6308        assert data[4, 64, 128] == 98
6309        assert_aszarr_method(tif, data)
6310        assert__str__(tif)
6311
6312
6313@pytest.mark.skipif(
6314    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
6315)
6316def test_read_ndpi_cmu1():
6317    """Test read Hamamatsu NDPI slide, JPEG."""
6318    fname = private_file('HamamatsuNDPI/CMU-1.ndpi')
6319    with TiffFile(fname) as tif:
6320        assert tif.is_ndpi
6321        assert len(tif.pages) == 5
6322        assert len(tif.series) == 2
6323        for page in tif.pages:
6324            assert page.ndpi_tags['Model'] == 'NanoZoomer'
6325        # first page
6326        page = tif.pages[0]
6327        assert page.is_ndpi
6328        assert page.photometric == YCBCR
6329        assert page.compression == JPEG
6330        assert page.shape == (38144, 51200, 3)
6331        assert page.ndpi_tags['Magnification'] == 20.0
6332        # page 4
6333        page = tif.pages[4]
6334        assert page.is_ndpi
6335        assert page.photometric == YCBCR
6336        assert page.compression == JPEG
6337        assert page.shape == (408, 1191, 3)
6338        assert page.ndpi_tags['Magnification'] == -1.0
6339        assert page.asarray()[226, 629, 0] == 167
6340        assert_aszarr_method(page)
6341        assert__str__(tif)
6342
6343
6344@pytest.mark.skipif(
6345    SKIP_PRIVATE or SKIP_CODECS or SKIP_LARGE or not imagecodecs.JPEG,
6346    reason=REASON,
6347)
6348def test_read_ndpi_cmu2():
6349    """Test read Hamamatsu NDPI slide, JPEG."""
6350    # JPEG stream too large to be opened with unpatched libjpeg
6351    fname = private_file('HamamatsuNDPI/CMU-2.ndpi')
6352    with TiffFile(fname) as tif:
6353        assert tif.is_ndpi
6354        assert len(tif.pages) == 6
6355        assert len(tif.series) == 2
6356        for page in tif.pages:
6357            assert page.ndpi_tags['Model'] == 'NanoZoomer'
6358        # first page
6359        page = tif.pages[0]
6360        assert page.is_ndpi
6361        assert page.photometric == YCBCR
6362        assert page.compression == JPEG
6363        assert page.shape == (33792, 79872, 3)
6364        assert page.ndpi_tags['Magnification'] == 20.0
6365        # with pytest.raises(RuntimeError):
6366        if not SKIP_PYPY:
6367            data = page.asarray()
6368            assert data.shape == (33792, 79872, 3)
6369            assert data.dtype == numpy.uint8
6370        # page 5
6371        page = tif.pages[5]
6372        assert page.is_ndpi
6373        assert page.photometric == YCBCR
6374        assert page.compression == JPEG
6375        assert page.shape == (408, 1191, 3)
6376        assert page.ndpi_tags['Magnification'] == -1.0
6377        assert page.asarray()[226, 629, 0] == 181
6378        assert_aszarr_method(page)
6379        assert__str__(tif)
6380
6381
6382@pytest.mark.skipif(
6383    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
6384)
6385def test_read_ndpi_4gb():
6386    """Test read > 4GB Hamamatsu NDPI slide, JPEG 103680x188160."""
6387    fname = private_file('HamamatsuNDPI/103680x188160.ndpi')
6388    with TiffFile(fname) as tif:
6389        assert tif.is_ndpi
6390        assert len(tif.pages) == 8
6391        assert len(tif.series) == 3
6392        for page in tif.pages:
6393            assert page.ndpi_tags['Model'] == 'C13220'
6394        # first page
6395        page = tif.pages[0]
6396        assert page.offset == 4466602683
6397        assert page.is_ndpi
6398        assert page.databytecounts[0] == 5105  # not 4461521316
6399        assert page.photometric == YCBCR
6400        assert page.compression == JPEG
6401        assert page.shape == (103680, 188160, 3)
6402        assert (
6403            page.tags['ImageLength'].offset - page.tags['ImageWidth'].offset
6404            == 12
6405        )
6406        assert page.tags['ImageWidth'].offset == 4466602685
6407        assert page.tags['ImageWidth'].valueoffset == 4466602693
6408        assert page.tags['ImageLength'].offset == 4466602697
6409        assert page.tags['ImageLength'].valueoffset == 4466602705
6410        assert page.tags['ReferenceBlackWhite'].offset == 4466602889
6411        assert page.tags['ReferenceBlackWhite'].valueoffset == 1003
6412        assert page.ndpi_tags['Magnification'] == 40.0
6413        assert page.ndpi_tags['McuStarts'][-1] == 4461516507  # corrected
6414        if not SKIP_ZARR:
6415            # data = page.asarray()  # 55 GB
6416            with page.aszarr() as store:
6417                data = zarr.open(store, mode='r')
6418                assert data[38061, 121978].tolist() == [220, 167, 187]
6419        # page 7
6420        page = tif.pages[7]
6421        assert page.is_ndpi
6422        assert page.photometric == MINISBLACK
6423        assert page.compression == NONE
6424        assert page.shape == (200, 600)
6425        assert page.ndpi_tags['Magnification'] == -2.0
6426        # assert page.asarray()[226, 629, 0] == 167
6427        # first series
6428        series = tif.series[0]
6429        assert series.kind == 'NDPI'
6430        assert series.name == 'S10533009'
6431        assert series.shape == (103680, 188160, 3)
6432        assert series.is_pyramidal
6433        assert len(series.levels) == 6
6434        assert len(series.pages) == 1
6435        # pyramid levels
6436        assert series.levels[1].shape == (51840, 94080, 3)
6437        assert series.levels[2].shape == (25920, 47040, 3)
6438        assert series.levels[3].shape == (12960, 23520, 3)
6439        assert series.levels[4].shape == (6480, 11760, 3)
6440        assert series.levels[5].shape == (3240, 5880, 3)
6441        data = series.levels[5].asarray()
6442        assert tuple(data[1000, 1000]) == (222, 165, 200)
6443        # cannot decode base levels since JPEG compressed size > 2 GB
6444        # series.levels[0].asarray()
6445        assert_aszarr_method(series.levels[5], data)
6446        assert__str__(tif)
6447
6448
6449@pytest.mark.skipif(
6450    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEGXR, reason=REASON
6451)
6452def test_read_ndpi_jpegxr():
6453    """Test read Hamamatsu NDPI slide with JPEG XR compression."""
6454    # https://downloads.openmicroscopy.org/images/Hamamatsu-NDPI/hamamatsu/
6455    fname = private_file('HamamatsuNDPI/DM0014 - 2020-04-02 10.25.21.ndpi')
6456    with TiffFile(fname) as tif:
6457        assert tif.is_ndpi
6458        assert len(tif.pages) == 6
6459        assert len(tif.series) == 3
6460        for page in tif.pages:
6461            assert page.ndpi_tags['Model'] == 'C13210'
6462
6463        for page in tif.pages[:4]:
6464            # check that all levels are corrected
6465            assert page.is_ndpi
6466            assert page.tags['PhotometricInterpretation'].value == YCBCR
6467            assert page.tags['BitsPerSample'].value == (8, 8, 8)
6468            assert page.samplesperpixel == 1  # not 3
6469            assert page.bitspersample == 16  # not 8
6470            assert page.photometric == MINISBLACK  # not YCBCR
6471            assert page.compression == TIFF.COMPRESSION.JPEGXR_NDPI
6472
6473        # first page
6474        page = tif.pages[0]
6475        assert page.shape == (34944, 69888)  # not (34944, 69888, 3)
6476        assert page.databytecounts[0] == 632009
6477        assert page.ndpi_tags['CaptureMode'] == 17
6478        assert page.ndpi_tags['Magnification'] == 20.0
6479        if not SKIP_ZARR:
6480            with page.aszarr() as store:
6481                data = zarr.open(store, mode='r')
6482                assert data[28061, 41978] == 6717
6483        # page 5
6484        page = tif.pages[5]
6485        assert page.is_ndpi
6486        assert page.photometric == MINISBLACK
6487        assert page.compression == NONE
6488        assert page.shape == (192, 566)
6489        assert page.ndpi_tags['Magnification'] == -2.0
6490        # first series
6491        series = tif.series[0]
6492        assert series.kind == 'NDPI'
6493        assert series.name == 'DM0014'
6494        assert series.shape == (34944, 69888)
6495        assert series.is_pyramidal
6496        assert len(series.levels) == 4
6497        assert len(series.pages) == 1
6498        # pyramid levels
6499        assert series.levels[1].shape == (17472, 34944)
6500        assert series.levels[2].shape == (8736, 17472)
6501        assert series.levels[3].shape == (4368, 8736)
6502        data = series.levels[3].asarray()
6503        assert data[1000, 1000] == 1095
6504        assert_aszarr_method(series.levels[3], data)
6505        assert__str__(tif)
6506
6507
6508@pytest.mark.skipif(
6509    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
6510)
6511def test_read_svs_cmu1():
6512    """Test read Aperio SVS slide, JPEG and LZW."""
6513    fname = private_file('AperioSVS/CMU-1.svs')
6514    with TiffFile(fname) as tif:
6515        assert tif.is_svs
6516        assert not tif.is_scanimage
6517        assert len(tif.pages) == 6
6518        assert len(tif.series) == 4
6519        for page in tif.pages:
6520            svs_description_metadata(page.description)
6521        # first page
6522        page = tif.pages[0]
6523        assert page.is_svs
6524        assert page.is_subsampled
6525        assert page.photometric == RGB
6526        assert page.is_tiled
6527        assert page.compression == JPEG
6528        assert page.shape == (32914, 46000, 3)
6529        metadata = svs_description_metadata(page.description)
6530        assert metadata['Header'].startswith('Aperio Image Library')
6531        assert metadata['Originalheight'] == 33014
6532        # page 4
6533        page = tif.pages[4]
6534        assert page.is_svs
6535        assert page.is_reduced
6536        assert page.photometric == RGB
6537        assert page.compression == LZW
6538        assert page.shape == (463, 387, 3)
6539        metadata = svs_description_metadata(page.description)
6540        assert 'label 387x463' in metadata['Header']
6541        assert_aszarr_method(page)
6542        assert__str__(tif)
6543
6544
6545@pytest.mark.skipif(
6546    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG2K, reason=REASON
6547)
6548def test_read_svs_jp2k_33003_1():
6549    """Test read Aperio SVS slide, JP2000 and LZW."""
6550    fname = private_file('AperioSVS/JP2K-33003-1.svs')
6551    with TiffFile(fname) as tif:
6552        assert tif.is_svs
6553        assert not tif.is_scanimage
6554        assert len(tif.pages) == 6
6555        assert len(tif.series) == 4
6556        for page in tif.pages:
6557            svs_description_metadata(page.description)
6558        # first page
6559        page = tif.pages[0]
6560        assert page.is_svs
6561        assert not page.is_subsampled
6562        assert page.photometric == RGB
6563        assert page.is_tiled
6564        assert page.compression == APERIO_JP2000_YCBC
6565        assert page.shape == (17497, 15374, 3)
6566        metadata = svs_description_metadata(page.description)
6567        assert metadata['Header'].startswith('Aperio Image Library')
6568        assert metadata['Originalheight'] == 17597
6569        # page 4
6570        page = tif.pages[4]
6571        assert page.is_svs
6572        assert page.is_reduced
6573        assert page.photometric == RGB
6574        assert page.compression == LZW
6575        assert page.shape == (422, 415, 3)
6576        metadata = svs_description_metadata(page.description)
6577        assert 'label 415x422' in metadata['Header']
6578        assert_aszarr_method(page)
6579        assert__str__(tif)
6580
6581
6582@pytest.mark.skipif(
6583    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
6584)
6585def test_read_bif(caplog):
6586    """Test read Ventana BIF slide."""
6587    fname = private_file('VentanaBIF/OS-2.bif')
6588    with TiffFile(fname) as tif:
6589        assert tif.is_bif
6590        assert len(tif.pages) == 12
6591        assert len(tif.series) == 3
6592        # first page
6593        page = tif.pages[0]
6594        assert page.is_bif
6595        assert page.photometric == YCBCR
6596        assert page.is_tiled
6597        assert page.compression == JPEG
6598        assert page.shape == (3008, 1008, 3)
6599
6600        series = tif.series
6601        assert 'not stiched' in caplog.text
6602        # baseline
6603        series = tif.series[0]
6604        assert series.name == 'Baseline'
6605        assert len(series.levels) == 10
6606        assert series.shape == (82960, 128000, 3)
6607        assert series.dtype == numpy.uint8
6608        # level 0
6609        page = series.pages[0]
6610        assert page.is_bif
6611        assert page.is_tiled
6612        assert page.photometric == YCBCR
6613        assert page.compression == JPEG
6614        assert page.shape == (82960, 128000, 3)
6615        assert page.description == 'level=0 mag=40 quality=90'
6616        # level 5
6617        page = series.levels[5].pages[0]
6618        assert not page.is_bif
6619        assert page.is_tiled
6620        assert page.photometric == YCBCR
6621        assert page.compression == JPEG
6622        assert page.shape == (2600, 4000, 3)
6623        assert page.description == 'level=5 mag=1.25 quality=90'
6624
6625        assert_aszarr_method(page)
6626        assert__str__(tif)
6627
6628
6629@pytest.mark.skipif(
6630    SKIP_PRIVATE or SKIP_LARGE or SKIP_CODECS or not imagecodecs.JPEG,
6631    reason=REASON,
6632)
6633def test_read_scn_collection():
6634    """Test read Leica SCN slide, JPEG."""
6635    # collection of 43 CZYX images
6636    # https://forum.image.sc/t/43585
6637    fname = private_file(
6638        'LeicaSCN/19-3-12_b5992c2e-5b6e-46f2-bf9b-d5872bdebdc1.SCN'
6639    )
6640    with TiffFile(fname) as tif:
6641        assert tif.is_scn
6642        assert tif.is_bigtiff
6643        assert len(tif.pages) == 5358
6644        assert len(tif.series) == 46
6645        # first page
6646        page = tif.pages[0]
6647        assert page.is_scn
6648        assert page.is_tiled
6649        assert page.photometric == YCBCR
6650        assert page.compression == JPEG
6651        assert page.shape == (12990, 5741, 3)
6652        metadata = tif.scn_metadata
6653        assert metadata.startswith('<?xml version="1.0" encoding="utf-8"?>')
6654        for series in tif.series[2:]:
6655            assert series.kind == 'SCN'
6656            assert series.axes == 'CZYX'
6657            assert series.shape[:2] == (4, 8)
6658            assert len(series.levels) in (2, 3, 4, 5)
6659            assert len(series.pages) == 32
6660        # third series
6661        series = tif.series[2]
6662        assert series.shape == (4, 8, 946, 993)
6663        assert_aszarr_method(series)
6664        assert__str__(tif)
6665
6666
6667@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6668def test_read_scanimage_metadata():
6669    """Test read ScanImage metadata."""
6670    fname = private_file('ScanImage/TS_UnitTestImage_BigTIFF.tif')
6671    with open(fname, 'rb') as fh:
6672        frame_data, roi_data, version = read_scanimage_metadata(fh)
6673    assert version == 3
6674    assert frame_data['SI.hChannels.channelType'] == ['stripe', 'stripe']
6675    assert roi_data['RoiGroups']['imagingRoiGroup']['ver'] == 1
6676
6677
6678@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6679def test_read_scanimage_2021():
6680    """Test read ScanImage metadata."""
6681    # https://github.com/cgohlke/tifffile/issues/46
6682    fname = private_file('ScanImage/ScanImage2021_3frames.tif')
6683    with open(fname, 'rb') as fh:
6684        frame_data, roi_data, version = read_scanimage_metadata(fh)
6685    assert frame_data['SI.hChannels.channelType'] == [
6686        'stripe',
6687        'stripe',
6688        'stripe',
6689        'stripe',
6690    ]
6691    assert version == 4
6692    assert roi_data['RoiGroups']['imagingRoiGroup']['ver'] == 1
6693
6694    with TiffFile(fname) as tif:
6695        assert tif.is_scanimage
6696        assert len(tif.pages) == 3
6697        assert len(tif.series) == 1
6698        assert tif.series[0].shape == (3, 256, 256)
6699        assert tif.series[0].axes == 'TYX'
6700        # non-varying scanimage_metadata
6701        assert tif.scanimage_metadata['version'] == 4
6702        assert 'FrameData' in tif.scanimage_metadata
6703        assert 'RoiGroups' in tif.scanimage_metadata
6704        # assert page properties
6705        page = tif.pages[0]
6706        assert page.is_scanimage
6707        assert page.is_contiguous
6708        assert page.compression == NONE
6709        assert page.imagewidth == 256
6710        assert page.imagelength == 256
6711        assert page.bitspersample == 16
6712        assert page.samplesperpixel == 1
6713        # description tags
6714        metadata = scanimage_description_metadata(page.description)
6715        assert metadata['epoch'] == [2021, 3, 1, 17, 31, 28.047]
6716        assert_aszarr_method(tif)
6717        assert__str__(tif)
6718
6719
6720@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6721def test_read_scanimage_no_framedata():
6722    """Test read ScanImage no FrameData."""
6723    fname = private_file('ScanImage/PSF001_ScanImage36.tif')
6724    with TiffFile(fname) as tif:
6725        assert tif.is_scanimage
6726        assert len(tif.pages) == 100
6727        assert len(tif.series) == 1
6728        # no non-tiff scanimage_metadata
6729        assert not tif.scanimage_metadata
6730        # assert page properties
6731        page = tif.pages[0]
6732        assert page.is_scanimage
6733        assert page.is_contiguous
6734        assert page.compression == NONE
6735        assert page.imagewidth == 256
6736        assert page.imagelength == 256
6737        assert page.bitspersample == 16
6738        assert page.samplesperpixel == 1
6739        # description tags
6740        metadata = scanimage_description_metadata(page.description)
6741        assert metadata['state.software.version'] == 3.6
6742        assert_aszarr_method(tif)
6743        assert__str__(tif)
6744
6745
6746@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
6747def test_read_scanimage_2gb():
6748    """Test read ScanImage non-BigTIFF > 2 GB.
6749
6750    https://github.com/MouseLand/suite2p/issues/149
6751
6752    """
6753    fname = private_file('ScanImage/M161209TH_01__001.tif')
6754    with TiffFile(fname) as tif:
6755        assert tif.is_scanimage
6756        assert len(tif.pages) == 5980
6757        assert len(tif.series) == 1
6758        # no non-tiff scanimage_metadata
6759        assert 'version' not in tif.scanimage_metadata
6760        assert 'FrameData' not in tif.scanimage_metadata
6761        assert 'RoiGroups' not in tif.scanimage_metadata
6762        # assert page properties
6763        page = tif.pages[0]
6764        assert page.is_scanimage
6765        assert page.is_contiguous
6766        assert page.compression == NONE
6767        assert page.imagewidth == 512
6768        assert page.imagelength == 512
6769        assert page.bitspersample == 16
6770        assert page.samplesperpixel == 1
6771        # using virtual frames
6772        frame = tif.pages[-1]
6773        assert isinstance(frame, TiffFrame)
6774        assert frame.offset is None
6775        assert frame.index == 5979
6776        assert frame.dataoffsets[0] == 3163182856
6777        assert frame.databytecounts[0] == 8192  # 524288
6778        assert len(frame.dataoffsets) == 64
6779        assert len(frame.databytecounts) == 64
6780        # description tags
6781        metadata = scanimage_description_metadata(page.description)
6782        assert metadata['scanimage.SI5.VERSION_MAJOR'] == 5
6783        # assert data
6784        data = tif.asarray()
6785        assert data[5979, 256, 256] == 71
6786        data = frame.asarray()
6787        assert data[256, 256] == 71
6788        assert_aszarr_method(tif)
6789        assert__str__(tif)
6790
6791
6792@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
6793def test_read_scanimage_bigtiff():
6794    """Test read ScanImage BigTIFF."""
6795    # https://github.com/cgohlke/tifffile/issues/29
6796    fname = private_file('ScanImage/area1__00001.tif')
6797    with TiffFile(fname) as tif:
6798        assert tif.is_scanimage
6799        assert len(tif.pages) == 162
6800        assert len(tif.series) == 1
6801        # assert page properties
6802        page = tif.pages[0]
6803        assert page.is_scanimage
6804        assert page.is_contiguous
6805        assert page.compression == NONE
6806        assert page.imagewidth == 512
6807        assert page.imagelength == 512
6808        assert page.bitspersample == 16
6809        assert page.samplesperpixel == 1
6810        # metadata in description, software, artist tags
6811        metadata = scanimage_description_metadata(page.description)
6812        assert metadata['frameNumbers'] == 1
6813        metadata = scanimage_description_metadata(page.tags['Software'].value)
6814        assert metadata['SI.TIFF_FORMAT_VERSION'] == 3
6815        metadata = scanimage_artist_metadata(page.tags['Artist'].value)
6816        assert metadata['RoiGroups']['imagingRoiGroup']['ver'] == 1
6817        metadata = tif.scanimage_metadata
6818        assert metadata['version'] == 3
6819        assert metadata['FrameData']['SI.TIFF_FORMAT_VERSION'] == 3
6820        assert metadata['RoiGroups']['imagingRoiGroup']['ver'] == 1
6821        assert 'Description' not in metadata
6822        # assert page offsets are correct
6823        assert tif.pages[-1].offset == 84527590  # not 84526526 (calculated)
6824        # read image data
6825        assert_aszarr_method(tif)
6826        assert__str__(tif)
6827
6828
6829@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
6830def test_read_ome_single_channel():
6831    """Test read OME image."""
6832    # 2D (single image)
6833    # OME-TIFF reference images from
6834    # https://www.openmicroscopy.org/site/support/ome-model/ome-tiff
6835    fname = public_file('OME/bioformats-artificial/single-channel.ome.tif')
6836    with TiffFile(fname) as tif:
6837        assert tif.is_ome
6838        assert tif.byteorder == '>'
6839        assert len(tif.pages) == 1
6840        assert len(tif.series) == 1
6841        # assert page properties
6842        page = tif.pages[0]
6843        assert page.is_contiguous
6844        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
6845        assert page.compression == NONE
6846        assert page.imagewidth == 439
6847        assert page.imagelength == 167
6848        assert page.bitspersample == 8
6849        assert page.samplesperpixel == 1
6850        # assert series properties
6851        series = tif.series[0]
6852        assert not series.is_multifile
6853        assert series.dtype == numpy.int8
6854        assert series.shape == (167, 439)
6855        assert series.axes == 'YX'
6856        assert series.get_shape(False) == (1, 1, 1, 167, 439, 1)
6857        assert series.get_axes(False) == 'TCZYXS'
6858        # assert data
6859        data = tif.asarray()
6860        assert isinstance(data, numpy.ndarray)
6861        assert data.shape == (167, 439)
6862        assert data.dtype == numpy.int8
6863        assert data[158, 428] == 91
6864        assert_aszarr_method(tif, data)
6865        assert__str__(tif)
6866
6867
6868@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
6869def test_read_ome_multi_channel():
6870    """Test read OME multi channel image."""
6871    # 2D (3 channels)
6872    fname = public_file('OME/bioformats-artificial/multi-channel.ome.tiff')
6873    with TiffFile(fname) as tif:
6874        assert tif.is_ome
6875        assert tif.byteorder == '>'
6876        assert len(tif.pages) == 3
6877        assert len(tif.series) == 1
6878        # assert page properties
6879        page = tif.pages[0]
6880        assert page.is_contiguous
6881        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
6882        assert page.compression == NONE
6883        assert page.imagewidth == 439
6884        assert page.imagelength == 167
6885        assert page.bitspersample == 8
6886        assert page.samplesperpixel == 1
6887        # assert series properties
6888        series = tif.series[0]
6889        assert series.shape == (3, 167, 439)
6890        assert series.dtype == numpy.int8
6891        assert series.axes == 'CYX'
6892        assert series.get_shape(False) == (1, 3, 1, 167, 439, 1)
6893        assert series.get_axes(False) == 'TCZYXS'
6894        assert not series.is_multifile
6895        # assert data
6896        data = tif.asarray()
6897        assert isinstance(data, numpy.ndarray)
6898        assert data.shape == (3, 167, 439)
6899        assert data.dtype == numpy.int8
6900        assert data[2, 158, 428] == 91
6901        assert_aszarr_method(tif, data)
6902        # don't squeeze
6903        data = tif.asarray(squeeze=False)
6904        assert_aszarr_method(tif, data, squeeze=False)
6905        assert__str__(tif)
6906
6907
6908@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
6909def test_read_ome_z_series():
6910    """Test read OME volume."""
6911    # 3D (5 focal planes)
6912    fname = public_file('OME/bioformats-artificial/z-series.ome.tif')
6913    with TiffFile(fname) as tif:
6914        assert tif.is_ome
6915        assert tif.byteorder == '>'
6916        assert len(tif.pages) == 5
6917        assert len(tif.series) == 1
6918        # assert page properties
6919        page = tif.pages[0]
6920        assert page.is_contiguous
6921        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
6922        assert page.compression == NONE
6923        assert page.imagewidth == 439
6924        assert page.imagelength == 167
6925        assert page.bitspersample == 8
6926        assert page.samplesperpixel == 1
6927        # assert series properties
6928        series = tif.series[0]
6929        assert series.shape == (5, 167, 439)
6930        assert series.dtype == numpy.int8
6931        assert series.axes == 'ZYX'
6932        assert series.get_shape(False) == (1, 1, 5, 167, 439, 1)
6933        assert series.get_axes(False) == 'TCZYXS'
6934        assert not series.is_multifile
6935        # assert data
6936        data = tif.asarray()
6937        assert isinstance(data, numpy.ndarray)
6938        assert data.shape == (5, 167, 439)
6939        assert data.dtype == numpy.int8
6940        assert data[4, 158, 428] == 91
6941        assert_aszarr_method(tif, data)
6942        assert__str__(tif)
6943
6944
6945@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
6946def test_read_ome_multi_channel_z_series():
6947    """Test read OME multi-channel volume."""
6948    # 3D (5 focal planes, 3 channels)
6949    fname = public_file(
6950        'OME/bioformats-artificial/multi-channel-z-series.ome.tiff'
6951    )
6952    with TiffFile(fname) as tif:
6953        assert tif.is_ome
6954        assert tif.byteorder == '>'
6955        assert len(tif.pages) == 15
6956        assert len(tif.series) == 1
6957        # assert page properties
6958        page = tif.pages[0]
6959        assert page.is_contiguous
6960        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
6961        assert page.compression == NONE
6962        assert page.imagewidth == 439
6963        assert page.imagelength == 167
6964        assert page.bitspersample == 8
6965        assert page.samplesperpixel == 1
6966        # assert series properties
6967        series = tif.series[0]
6968        assert series.shape == (3, 5, 167, 439)
6969        assert series.dtype == numpy.int8
6970        assert series.axes == 'CZYX'
6971        assert series.get_shape(False) == (1, 3, 5, 167, 439, 1)
6972        assert series.get_axes(False) == 'TCZYXS'
6973        assert not series.is_multifile
6974        # assert data
6975        data = tif.asarray()
6976        assert isinstance(data, numpy.ndarray)
6977        assert data.shape == (3, 5, 167, 439)
6978        assert data.dtype == numpy.int8
6979        assert data[2, 4, 158, 428] == 91
6980        assert_aszarr_method(tif, data)
6981        assert__str__(tif)
6982
6983
6984@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
6985def test_read_ome_time_series():
6986    """Test read OME time-series of images."""
6987    # 3D (7 time points)
6988    fname = public_file('OME/bioformats-artificial/time-series.ome.tiff')
6989    with TiffFile(fname) as tif:
6990        assert tif.is_ome
6991        assert tif.byteorder == '>'
6992        assert len(tif.pages) == 7
6993        assert len(tif.series) == 1
6994        # assert page properties
6995        page = tif.pages[0]
6996        assert page.is_contiguous
6997        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
6998        assert page.compression == NONE
6999        assert page.imagewidth == 439
7000        assert page.imagelength == 167
7001        assert page.bitspersample == 8
7002        assert page.samplesperpixel == 1
7003        # assert series properties
7004        series = tif.series[0]
7005        assert series.shape == (7, 167, 439)
7006        assert series.dtype == numpy.int8
7007        assert series.axes == 'TYX'
7008        assert series.get_shape(False) == (7, 1, 1, 167, 439, 1)
7009        assert series.get_axes(False) == 'TCZYXS'
7010        assert not series.is_multifile
7011        # assert data
7012        data = tif.asarray()
7013        assert isinstance(data, numpy.ndarray)
7014        assert data.shape == (7, 167, 439)
7015        assert data.dtype == numpy.int8
7016        assert data[6, 158, 428] == 91
7017        assert_aszarr_method(tif, data)
7018        assert__str__(tif)
7019
7020
7021@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7022def test_read_ome_multi_channel_time_series():
7023    """Test read OME time-series of multi-channel images."""
7024    # 3D (7 time points, 3 channels)
7025    fname = public_file(
7026        'OME/bioformats-artificial/multi-channel-time-series.ome.tiff'
7027    )
7028    with TiffFile(fname) as tif:
7029        assert tif.is_ome
7030        assert tif.byteorder == '>'
7031        assert len(tif.pages) == 21
7032        assert len(tif.series) == 1
7033        # assert page properties
7034        page = tif.pages[0]
7035        assert page.is_contiguous
7036        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7037        assert page.compression == NONE
7038        assert page.imagewidth == 439
7039        assert page.imagelength == 167
7040        assert page.bitspersample == 8
7041        assert page.samplesperpixel == 1
7042        # assert series properties
7043        series = tif.series[0]
7044        assert series.shape == (7, 3, 167, 439)
7045        assert series.dtype == numpy.int8
7046        assert series.axes == 'TCYX'
7047        assert series.get_shape(False) == (7, 3, 1, 167, 439, 1)
7048        assert series.get_axes(False) == 'TCZYXS'
7049        assert not series.is_multifile
7050        # assert data
7051        data = tif.asarray()
7052        assert isinstance(data, numpy.ndarray)
7053        assert data.shape == (7, 3, 167, 439)
7054        assert data.dtype == numpy.int8
7055        assert data[6, 2, 158, 428] == 91
7056        assert_aszarr_method(tif, data)
7057        # don't squeeze
7058        data = tif.asarray(squeeze=False)
7059        assert_aszarr_method(tif, data, squeeze=False)
7060        assert__str__(tif)
7061
7062
7063@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7064def test_read_ome_4d_series():
7065    """Test read OME time-series of volumes."""
7066    # 4D (7 time points, 5 focal planes)
7067    fname = public_file('OME/bioformats-artificial/4D-series.ome.tiff')
7068    with TiffFile(fname) as tif:
7069        assert tif.is_ome
7070        assert tif.byteorder == '>'
7071        assert len(tif.pages) == 35
7072        assert len(tif.series) == 1
7073        # assert page properties
7074        page = tif.pages[0]
7075        assert page.is_contiguous
7076        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7077        assert page.compression == NONE
7078        assert page.imagewidth == 439
7079        assert page.imagelength == 167
7080        assert page.bitspersample == 8
7081        assert page.samplesperpixel == 1
7082        # assert series properties
7083        series = tif.series[0]
7084        assert series.shape == (7, 5, 167, 439)
7085        assert series.dtype == numpy.int8
7086        assert series.axes == 'TZYX'
7087        assert not series.is_multifile
7088        # assert data
7089        data = tif.asarray()
7090        assert isinstance(data, numpy.ndarray)
7091        assert data.shape == (7, 5, 167, 439)
7092        assert data.dtype == numpy.int8
7093        assert data[6, 4, 158, 428] == 91
7094        assert_aszarr_method(tif, data)
7095        assert__str__(tif)
7096
7097
7098@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7099def test_read_ome_multi_channel_4d_series():
7100    """Test read OME time-series of multi-channel volumes."""
7101    # 4D (7 time points, 5 focal planes, 3 channels)
7102    fname = public_file(
7103        'OME/bioformats-artificial/multi-channel-4D-series.ome.tiff'
7104    )
7105    with TiffFile(fname) as tif:
7106        assert tif.is_ome
7107        assert tif.byteorder == '>'
7108        assert len(tif.pages) == 105
7109        assert len(tif.series) == 1
7110        # assert page properties
7111        page = tif.pages[0]
7112        assert page.is_contiguous
7113        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7114        assert page.compression == NONE
7115        assert page.imagewidth == 439
7116        assert page.imagelength == 167
7117        assert page.bitspersample == 8
7118        assert page.samplesperpixel == 1
7119        # assert series properties
7120        series = tif.series[0]
7121        assert series.shape == (7, 3, 5, 167, 439)
7122        assert series.dtype == numpy.int8
7123        assert series.axes == 'TCZYX'
7124        assert series.get_shape(False) == (7, 3, 5, 167, 439, 1)
7125        assert series.get_axes(False) == 'TCZYXS'
7126        assert not series.is_multifile
7127        # assert data
7128        data = tif.asarray()
7129        assert isinstance(data, numpy.ndarray)
7130        assert data.shape == (7, 3, 5, 167, 439)
7131        assert data.dtype == numpy.int8
7132        assert data[6, 0, 4, 158, 428] == 91
7133        assert_aszarr_method(tif, data)
7134        # don't squeeze
7135        data = tif.asarray(squeeze=False)
7136        assert_aszarr_method(tif, data, squeeze=False)
7137        assert__str__(tif)
7138
7139
7140@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7141def test_read_ome_modulo_flim():
7142    """Test read OME modulo FLIM."""
7143    fname = public_file('OME/modulo/FLIM-ModuloAlongC.ome.tiff')
7144    with TiffFile(fname) as tif:
7145        assert tif.is_ome
7146        assert tif.byteorder == '>'
7147        assert len(tif.pages) == 16
7148        assert len(tif.series) == 1
7149        # assert page properties
7150        page = tif.pages[0]
7151        assert page.is_contiguous
7152        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7153        assert page.compression == NONE
7154        assert page.imagewidth == 180
7155        assert page.imagelength == 150
7156        assert page.bitspersample == 8
7157        assert page.samplesperpixel == 1
7158        # assert series properties
7159        series = tif.series[0]
7160        assert series.shape == (2, 8, 150, 180)
7161        assert series.dtype == numpy.int8
7162        assert series.axes == 'CHYX'
7163        assert series.get_shape(False) == (1, 2, 8, 1, 150, 180, 1)
7164        assert series.get_axes(False) == 'TCHZYXS'
7165        assert not series.is_multifile
7166        # assert data
7167        data = tif.asarray()
7168        assert isinstance(data, numpy.ndarray)
7169        assert data.shape == (2, 8, 150, 180)
7170        assert data.dtype == numpy.int8
7171        assert data[1, 7, 143, 172] == 92
7172        assert_aszarr_method(tif, data)
7173        # don't squeeze
7174        data = tif.asarray(squeeze=False)
7175        assert_aszarr_method(tif, data, squeeze=False)
7176        assert__str__(tif)
7177
7178
7179@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7180def test_read_ome_modulo_flim_tcspc():
7181    """Test read OME modulo FLIM TSCPC."""
7182    # Two channels each recorded at two timepoints and eight histogram bins
7183    fname = public_file('OME/modulo/FLIM-ModuloAlongT-TSCPC.ome.tiff')
7184    with TiffFile(fname) as tif:
7185        assert tif.is_ome
7186        assert tif.byteorder == '<'
7187        assert len(tif.pages) == 32
7188        assert len(tif.series) == 1
7189        # assert page properties
7190        page = tif.pages[0]
7191        assert page.is_contiguous
7192        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7193        assert page.compression == NONE
7194        assert page.imagewidth == 180
7195        assert page.imagelength == 200
7196        assert page.bitspersample == 8
7197        assert page.samplesperpixel == 1
7198        # assert series properties
7199        series = tif.series[0]
7200        assert series.shape == (2, 8, 2, 200, 180)
7201        assert series.dtype == numpy.int8
7202        assert series.axes == 'THCYX'
7203        assert not series.is_multifile
7204        # assert data
7205        data = tif.asarray()
7206        assert isinstance(data, numpy.ndarray)
7207        assert data.shape == (2, 8, 2, 200, 180)
7208        assert data.dtype == numpy.int8
7209        assert data[1, 7, 1, 190, 161] == 92
7210        assert_aszarr_method(tif, data)
7211        assert__str__(tif)
7212
7213
7214@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7215def test_read_ome_modulo_spim():
7216    """Test read OME modulo SPIM."""
7217    # 2x2 tile of planes each recorded at 4 angles
7218    fname = public_file('OME/modulo/SPIM-ModuloAlongZ.ome.tiff')
7219    with TiffFile(fname) as tif:
7220        assert tif.is_ome
7221        assert tif.byteorder == '<'
7222        assert len(tif.pages) == 192
7223        assert len(tif.series) == 1
7224        # assert page properties
7225        page = tif.pages[0]
7226        assert page.is_contiguous
7227        assert page.tags['Software'].value == 'OME Bio-Formats 5.2.0-SNAPSHOT'
7228        assert page.compression == NONE
7229        assert page.imagewidth == 160
7230        assert page.imagelength == 220
7231        assert page.bitspersample == 8
7232        assert page.samplesperpixel == 1
7233        # assert series properties
7234        series = tif.series[0]
7235        assert series.shape == (3, 4, 2, 4, 2, 220, 160)
7236        assert series.dtype == numpy.uint8
7237        assert series.axes == 'TRZACYX'
7238        assert not series.is_multifile
7239        # assert data
7240        data = tif.asarray()
7241        assert isinstance(data, numpy.ndarray)
7242        assert data.shape == (3, 4, 2, 4, 2, 220, 160)
7243        assert data.dtype == numpy.uint8
7244        assert data[2, 3, 1, 3, 1, 210, 151] == 92
7245        assert_aszarr_method(tif, data)
7246        assert__str__(tif)
7247
7248
7249@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7250def test_read_ome_modulo_lambda():
7251    """Test read OME modulo LAMBDA."""
7252    # Excitation of 5 wavelength [big-lambda] each recorded at 10 emission
7253    # wavelength ranges [lambda].
7254    fname = public_file('OME/modulo/LAMBDA-ModuloAlongZ-ModuloAlongT.ome.tiff')
7255    with TiffFile(fname) as tif:
7256        assert tif.is_ome
7257        assert tif.byteorder == '<'
7258        assert len(tif.pages) == 50
7259        assert len(tif.series) == 1
7260        # assert page properties
7261        page = tif.pages[0]
7262        assert page.is_contiguous
7263        assert page.tags['Software'].value == 'OME Bio-Formats 5.2.0-SNAPSHOT'
7264        assert page.compression == NONE
7265        assert page.imagewidth == 200
7266        assert page.imagelength == 200
7267        assert page.bitspersample == 8
7268        assert page.samplesperpixel == 1
7269        # assert series properties
7270        series = tif.series[0]
7271        assert series.shape == (10, 5, 200, 200)
7272        assert series.dtype == numpy.uint8
7273        assert series.axes == 'EPYX'
7274        assert not series.is_multifile
7275        # assert data
7276        data = tif.asarray()
7277        assert isinstance(data, numpy.ndarray)
7278        assert data.shape == (10, 5, 200, 200)
7279        assert data.dtype == numpy.uint8
7280        assert data[9, 4, 190, 192] == 92
7281        assert_aszarr_method(tif, data)
7282        assert__str__(tif)
7283
7284
7285@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
7286def test_read_ome_multi_image_pixels():
7287    """Test read OME with three image series."""
7288    fname = public_file('OME/bioformats-artificial/multi-image-pixels.ome.tif')
7289    with TiffFile(fname) as tif:
7290        assert tif.is_ome
7291        assert tif.byteorder == '>'
7292        assert len(tif.pages) == 86
7293        assert len(tif.series) == 3
7294        # assert page properties
7295        for (i, axes, shape) in (
7296            (0, 'CTYX', (2, 7, 555, 431)),
7297            (1, 'TZYX', (6, 2, 461, 348)),
7298            (2, 'TZCYX', (4, 5, 3, 239, 517)),
7299        ):
7300            series = tif.series[i]
7301            page = series.pages[0]
7302            assert page.is_contiguous
7303            assert page.tags['Software'].value == 'LOCI Bio-Formats'
7304            assert page.compression == NONE
7305            assert page.imagewidth == shape[-1]
7306            assert page.imagelength == shape[-2]
7307            assert page.bitspersample == 8
7308            assert page.samplesperpixel == 1
7309            # assert series properties
7310            assert series.shape == shape
7311            assert series.dtype == numpy.uint8
7312            assert series.axes == axes
7313            assert not series.is_multifile
7314            # assert data
7315            data = tif.asarray(series=i)
7316            assert isinstance(data, numpy.ndarray)
7317            assert data.shape == shape
7318            assert data.dtype == numpy.uint8
7319            assert_aszarr_method(series, data)
7320            assert__str__(tif)
7321
7322
7323@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7324def test_read_ome_multi_image_nouuid():
7325    """Test read single-file, multi-image OME without UUID."""
7326    fname = private_file(
7327        'OMETIFF.jl/singles/181003_multi_pos_time_course_1_MMStack.ome.tif'
7328    )
7329    with TiffFile(fname) as tif:
7330        assert tif.is_ome
7331        assert tif.byteorder == '<'
7332        assert len(tif.pages) == 20
7333        assert len(tif.series) == 2
7334        # assert page properties
7335        for i in (0, 1):
7336            series = tif.series[i]
7337            page = series.pages[0]
7338            assert bool(page.is_imagej) == (i == 0)
7339            assert page.is_ome == (i == 0)
7340            assert page.is_micromanager
7341            assert page.is_contiguous
7342            assert page.compression == NONE
7343            assert page.imagewidth == 256
7344            assert page.imagelength == 256
7345            assert page.bitspersample == 16
7346            assert page.samplesperpixel == 1
7347            # assert series properties
7348            assert series.shape == (10, 256, 256)
7349            assert series.dtype == numpy.uint16
7350            assert series.axes == 'TYX'
7351            assert not series.is_multifile
7352            # assert data
7353            data = tif.asarray(series=i)
7354            assert isinstance(data, numpy.ndarray)
7355            assert data.shape == (10, 256, 256)
7356            assert data.dtype == numpy.uint16
7357            assert data[5, 128, 128] == (18661, 16235)[i]
7358            assert_aszarr_method(series, data)
7359            assert__str__(tif)
7360
7361
7362@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7363def test_read_ome_zen_2chzt():
7364    """Test read OME time-series of two-channel volumes by ZEN 2011."""
7365    fname = private_file('OME/zen_2chzt.ome.tiff')
7366    with TiffFile(fname) as tif:
7367        assert tif.is_ome
7368        assert tif.byteorder == '<'
7369        assert len(tif.pages) == 798
7370        assert len(tif.series) == 1
7371        # assert page properties
7372        page = tif.pages[0]
7373        assert page.is_contiguous
7374        assert page.tags['Software'].value == 'ZEN 2011 (blue edition)'
7375        assert page.compression == NONE
7376        assert page.imagewidth == 400
7377        assert page.imagelength == 300
7378        assert page.bitspersample == 8
7379        assert page.samplesperpixel == 1
7380        # assert series properties
7381        series = tif.series[0]
7382        assert series.shape == (2, 19, 21, 300, 400)
7383        assert series.dtype == numpy.uint8
7384        assert series.axes == 'CTZYX'
7385        assert not series.is_multifile
7386        # assert data
7387        data = tif.asarray()
7388        assert isinstance(data, numpy.ndarray)
7389        assert data.shape == (2, 19, 21, 300, 400)
7390        assert data.dtype == numpy.uint8
7391        assert data[1, 10, 10, 100, 245] == 78
7392        assert_aszarr_method(tif, data)
7393        assert__str__(tif, 0)
7394
7395
7396@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
7397def test_read_ome_multifile():
7398    """Test read OME CTZYX series in 86 files."""
7399    # (2, 43, 10, 512, 512) CTZYX uint8 in 86 files, 10 pages each
7400    fname = public_file('OME/tubhiswt-4D/tubhiswt_C0_TP10.ome.tif')
7401    with TiffFile(fname) as tif:
7402        assert tif.is_ome
7403        assert tif.byteorder == '<'
7404        assert len(tif.pages) == 10
7405        assert len(tif.series) == 1
7406        # assert page properties
7407        page = tif.pages[0]
7408        assert page.is_contiguous
7409        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7410        assert page.compression == NONE
7411        assert page.imagewidth == 512
7412        assert page.imagelength == 512
7413        assert page.bitspersample == 8
7414        assert page.samplesperpixel == 1
7415        # assert series properties
7416        series = tif.series[0]
7417        assert series.shape == (2, 43, 10, 512, 512)
7418        assert series.dtype == numpy.uint8
7419        assert series.axes == 'CTZYX'
7420        assert series.is_multifile
7421        # assert other files are closed after TiffFile._series_ome
7422        for page in tif.series[0].pages:
7423            assert bool(page.parent.filehandle._fh) == (page.parent == tif)
7424        # assert data
7425        data = tif.asarray(out='memmap')
7426        assert isinstance(data, numpy.core.memmap)
7427        assert data.shape == (2, 43, 10, 512, 512)
7428        assert data.dtype == numpy.uint8
7429        assert data[1, 42, 9, 426, 272] == 123
7430        # assert other files are still closed after TiffFile.asarray
7431        for page in tif.series[0].pages:
7432            assert bool(page.parent.filehandle._fh) == (page.parent == tif)
7433        assert__str__(tif)
7434        # test aszarr
7435        assert_aszarr_method(tif, data)
7436        assert_aszarr_method(tif, data, chunkmode='page')
7437        del data
7438        # assert other files are still closed after ZarrStore.close
7439        for page in tif.series[0].pages:
7440            assert bool(page.parent.filehandle._fh) == (page.parent == tif)
7441
7442    # assert all files stay open
7443    # with TiffFile(fname) as tif:
7444    #     for page in tif.series[0].pages:
7445    #         self.assertTrue(page.parent.filehandle._fh)
7446    #     data = tif.asarray(out='memmap')
7447    #     for page in tif.series[0].pages:
7448    #         self.assertTrue(page.parent.filehandle._fh)
7449
7450
7451@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
7452def test_read_ome_multifile_missing(caplog):
7453    """Test read OME referencing missing files."""
7454    # (2, 43, 10, 512, 512) CTZYX uint8, 85 files missing
7455    fname = private_file('OME/tubhiswt_C0_TP34.ome.tif')
7456    with TiffFile(fname) as tif:
7457        assert tif.is_ome
7458        assert tif.byteorder == '<'
7459        assert len(tif.pages) == 10
7460        assert len(tif.series) == 1
7461        assert 'failed to read' in caplog.text
7462        # assert page properties
7463        page = tif.pages[0]
7464        TiffPage.__str__(page, 4)
7465        assert page.is_contiguous
7466        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7467        assert page.compression == NONE
7468        assert page.imagewidth == 512
7469        assert page.imagelength == 512
7470        assert page.bitspersample == 8
7471        assert page.samplesperpixel == 1
7472        page = tif.pages[-1]
7473        TiffPage.__str__(page, 4)
7474        assert page.shape == (512, 512)
7475        # assert series properties
7476        series = tif.series[0]
7477        assert series.shape == (2, 43, 10, 512, 512)
7478        assert series.dtype == numpy.uint8
7479        assert series.axes == 'CTZYX'
7480        assert series.is_multifile
7481        # assert data
7482        data = tif.asarray(out='memmap')
7483        assert isinstance(data, numpy.core.memmap)
7484        assert data.shape == (2, 43, 10, 512, 512)
7485        assert data.dtype == numpy.uint8
7486        assert data[0, 34, 4, 303, 206] == 82
7487        assert data[1, 25, 2, 425, 272] == 196
7488        assert_aszarr_method(tif, data)
7489        assert_aszarr_method(tif, data, chunkmode='page')
7490        del data
7491        assert__str__(tif)
7492
7493
7494@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7495def test_read_ome_rgb():
7496    """Test read OME RGB image."""
7497    # https://github.com/openmicroscopy/bioformats/pull/1986
7498    fname = private_file('OME/test_rgb.ome.tif')
7499    with TiffFile(fname) as tif:
7500        assert tif.is_ome
7501        assert tif.byteorder == '<'
7502        assert len(tif.pages) == 1
7503        assert len(tif.series) == 1
7504        # assert page properties
7505        page = tif.pages[0]
7506        assert page.is_contiguous
7507        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7508        assert page.compression == NONE
7509        assert page.imagewidth == 1280
7510        assert page.imagelength == 720
7511        assert page.bitspersample == 8
7512        assert page.samplesperpixel == 3
7513        # assert series properties
7514        series = tif.series[0]
7515        assert series.shape == (3, 720, 1280)
7516        assert series.dtype == numpy.uint8
7517        assert series.axes == 'SYX'
7518        assert series.offset == 17524
7519        assert not series.is_multifile
7520        # assert data
7521        data = tif.asarray()
7522        assert data.shape == (3, 720, 1280)
7523        assert data.dtype == numpy.uint8
7524        assert data[1, 158, 428] == 253
7525        assert_aszarr_method(tif, data)
7526        assert_aszarr_method(tif, data, chunkmode='page')
7527        assert__str__(tif)
7528
7529
7530@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
7531def test_read_ome_samplesperpixel():
7532    """Test read OME image stack with SamplesPerPixel>1."""
7533    # Reported by Grzegorz Bokota on 2019.1.30
7534    fname = private_file('OME/test_samplesperpixel.ome.tif')
7535    with TiffFile(fname) as tif:
7536        assert tif.is_ome
7537        assert tif.byteorder == '>'
7538        assert len(tif.pages) == 6
7539        assert len(tif.series) == 1
7540        # assert page properties
7541        page = tif.pages[0]
7542        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7543        assert page.compression == LZW
7544        assert page.imagewidth == 1024
7545        assert page.imagelength == 1024
7546        assert page.bitspersample == 8
7547        assert page.samplesperpixel == 3
7548        # assert series properties
7549        series = tif.series[0]
7550        assert series.shape == (6, 3, 1024, 1024)
7551        assert series.dtype == numpy.uint8
7552        assert series.axes == 'ZSYX'
7553        assert not series.is_multifile
7554        # assert data
7555        data = tif.asarray()
7556        assert data.shape == (6, 3, 1024, 1024)
7557        assert data.dtype == numpy.uint8
7558        assert tuple(data[5, :, 191, 449]) == (253, 0, 28)
7559        assert_aszarr_method(tif, data)
7560        assert_aszarr_method(tif, data, chunkmode='page')
7561        assert__str__(tif)
7562
7563
7564@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7565def test_read_ome_float_modulo_attributes():
7566    """Test read OME with floating point modulo attributes."""
7567    # reported by Start Berg. File by Lorenz Maier.
7568    fname = private_file('OME/float_modulo_attributes.ome.tiff')
7569    with TiffFile(fname) as tif:
7570        assert tif.is_ome
7571        assert tif.byteorder == '>'
7572        assert len(tif.pages) == 2
7573        assert len(tif.series) == 1
7574        # assert page properties
7575        page = tif.pages[0]
7576        assert page.is_contiguous
7577        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7578        assert page.compression == NONE
7579        assert page.imagewidth == 512
7580        assert page.imagelength == 512
7581        assert page.bitspersample == 16
7582        assert page.samplesperpixel == 1
7583        # assert series properties
7584        series = tif.series[0]
7585        assert series.shape == (2, 512, 512)
7586        assert series.dtype == numpy.uint16
7587        assert series.axes == 'QYX'
7588        assert not series.is_multifile
7589        # assert data
7590        data = tif.asarray()
7591        assert isinstance(data, numpy.ndarray)
7592        assert data.shape == (2, 512, 512)
7593        assert data.dtype == numpy.uint16
7594        assert data[1, 158, 428] == 51
7595        assert_aszarr_method(tif, data)
7596        assert_aszarr_method(tif, data, chunkmode='page')
7597        assert__str__(tif)
7598
7599
7600@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7601def test_read_ome_cropped(caplog):
7602    """Test read bad OME by ImageJ cropping."""
7603    # ImageJ produces invalid ome-xml when cropping
7604    # http://lists.openmicroscopy.org.uk/pipermail/ome-devel/2013-December
7605    #  /002631.html
7606    # Reported by Hadrien Mary on Dec 11, 2013
7607    fname = private_file('ome/cropped.ome.tif')
7608    with TiffFile(fname) as tif:
7609        assert tif.is_ome
7610        assert tif.byteorder == '<'
7611        assert len(tif.pages) == 100
7612        assert len(tif.series) == 1
7613        assert 'invalid TiffData index' in caplog.text
7614        # assert page properties
7615        page = tif.pages[0]
7616        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7617        assert page.imagewidth == 324
7618        assert page.imagelength == 249
7619        assert page.bitspersample == 16
7620        # assert series properties
7621        series = tif.series[0]
7622        assert series.shape == (5, 10, 2, 249, 324)
7623        assert series.dtype == numpy.uint16
7624        assert series.axes == 'TZCYX'
7625        assert not series.is_multifile
7626        # assert data
7627        data = tif.asarray()
7628        assert data.shape == (5, 10, 2, 249, 324)
7629        assert data.dtype == numpy.uint16
7630        assert data[4, 9, 1, 175, 123] == 9605
7631        assert_aszarr_method(tif, data)
7632        assert_aszarr_method(tif, data, chunkmode='page')
7633        del data
7634        assert__str__(tif)
7635
7636
7637@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS or SKIP_LARGE, reason=REASON)
7638def test_read_ome_corrupted_page(caplog):
7639    """Test read OME with corrupted but not referenced page."""
7640    # https://forum.image.sc/t/qupath-0-2-0-not-able-to-open-ome-tiff/23821/3
7641    fname = private_file('ome/2019_02_19__7760_s1.ome.tiff')
7642    with TiffFile(fname) as tif:
7643        assert tif.is_ome
7644        assert tif.is_bigtiff
7645        assert tif.byteorder == '<'
7646        assert len(tif.pages) == 5
7647        assert len(tif.series) == 1
7648        assert 'TiffFrame 4: missing required tags' in caplog.text
7649        # assert page properties
7650        page = tif.pages[0]
7651        assert page.imagewidth == 7506
7652        assert page.imagelength == 7506
7653        assert page.bitspersample == 16
7654        # assert series properties
7655        series = tif.series[0]
7656        assert series.shape == (4, 7506, 7506)
7657        assert series.dtype == numpy.uint16
7658        assert series.axes == 'CYX'
7659        assert not series.is_multifile
7660        # assert data
7661        data = tif.asarray()
7662        assert data.shape == (4, 7506, 7506)
7663        assert data.dtype == numpy.uint16
7664        assert tuple(data[:, 2684, 2684]) == (496, 657, 7106, 469)
7665        assert_aszarr_method(tif, data)
7666        assert_aszarr_method(tif, data, chunkmode='page')
7667        del data
7668        assert__str__(tif)
7669
7670
7671@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7672def test_read_ome_nikon(caplog):
7673    """Test read bad OME by Nikon."""
7674    # OME-XML references only first image
7675    # received from E. Gratton
7676    fname = private_file('OME/Nikon-cell011.ome.tif')
7677    with TiffFile(fname) as tif:
7678        assert tif.is_ome
7679        assert tif.byteorder == '<'
7680        assert len(tif.pages) == 1000
7681        assert len(tif.series) == 1
7682        # assert 'index out of range' in caplog.text
7683        # assert page properties
7684        page = tif.pages[0]
7685        assert page.photometric != RGB
7686        assert page.imagewidth == 1982
7687        assert page.imagelength == 1726
7688        assert page.bitspersample == 16
7689        assert page.is_contiguous
7690        assert (
7691            page.tags['ImageLength'].offset - page.tags['ImageWidth'].offset
7692            == 20
7693        )
7694        assert page.tags['ImageWidth'].offset == 6856262146
7695        assert page.tags['ImageWidth'].valueoffset == 6856262158
7696        assert page.tags['ImageLength'].offset == 6856262166
7697        assert page.tags['ImageLength'].valueoffset == 6856262178
7698        assert page.tags['StripByteCounts'].offset == 6856262366
7699        assert page.tags['StripByteCounts'].valueoffset == 6856262534
7700        # assert series properties
7701        series = tif.series[0]
7702        assert len(series._pages) == 1
7703        assert len(series.pages) == 1
7704        assert series.offset == 16  # contiguous
7705        assert series.shape == (1726, 1982)
7706        assert series.dtype == numpy.uint16
7707        assert series.axes == 'YX'
7708        assert__str__(tif)
7709
7710    with TiffFile(fname, is_ome=False) as tif:
7711        assert not tif.is_ome
7712        # assert series properties
7713        series = tif.series[0]
7714        assert len(series.pages) == 1000
7715        assert series.offset is None  # not contiguous
7716        assert series.shape == (1000, 1726, 1982)
7717        assert series.dtype == numpy.uint16
7718        assert series.axes == 'IYX'
7719        assert__str__(tif)
7720
7721
7722@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7723def test_read_ome_shape_mismatch(caplog):
7724    """Test read OME with page shape mismatch."""
7725    # TCX (20000, 2, 500) is stored in 2 pages of (20000, 500)
7726    # probably exported by ZEN Software
7727    fname = private_file('OME/Image 7.ome_h00.tiff')
7728    with TiffFile(fname) as tif:
7729        assert tif.is_ome
7730        assert tif.byteorder == '<'
7731        assert len(tif.pages) == 2
7732        assert len(tif.series) == 2
7733        assert 'OME series: cannot handle discontiguous storage' in caplog.text
7734        # assert page properties
7735        page = tif.pages[0]
7736        assert page.is_contiguous
7737        assert page.photometric == MINISBLACK
7738        assert page.imagewidth == 500
7739        assert page.imagelength == 20000
7740        assert page.bitspersample == 16
7741        assert page.samplesperpixel == 1
7742        page = tif.pages[1]
7743        assert page.is_contiguous
7744        assert page.photometric == PALETTE
7745        assert page.imagewidth == 500
7746        assert page.imagelength == 20000
7747        assert page.bitspersample == 8
7748        assert page.samplesperpixel == 1
7749        # assert series properties
7750        series = tif.series[0]
7751        assert series.shape == (20000, 500)
7752        assert series.dtype == numpy.uint16
7753        assert series.axes == 'YX'
7754        assert series.offset == 8
7755        assert series.kind == 'Generic'
7756
7757
7758@pytest.mark.skipif(
7759    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG2K, reason=REASON
7760)
7761def test_read_ome_jpeg2000_be():
7762    """Test read JPEG2000 compressed big-endian OME-TIFF."""
7763    fname = private_file('OME/mitosis.jpeg2000.ome.tif')
7764    with TiffFile(fname) as tif:
7765        assert tif.is_ome
7766        assert tif.byteorder == '>'
7767        assert len(tif.pages) == 510
7768        assert len(tif.series) == 1
7769        # assert page properties
7770        page = tif.pages[0]
7771        assert not page.is_contiguous
7772        assert page.tags['Software'].value[:15] == 'OME Bio-Formats'
7773        assert page.compression == APERIO_JP2000_YCBC
7774        assert page.imagewidth == 171
7775        assert page.imagelength == 196
7776        assert page.bitspersample == 16
7777        assert page.samplesperpixel == 1
7778        # assert series properties
7779        series = tif.series[0]
7780        assert series.shape == (51, 5, 2, 196, 171)
7781        assert series.dtype == numpy.uint16
7782        assert series.axes == 'TZCYX'
7783        # assert data
7784        data = page.asarray()
7785        assert isinstance(data, numpy.ndarray)
7786        assert data.shape == (196, 171)
7787        assert data.dtype == numpy.uint16
7788        assert data[0, 0] == 1904
7789        assert_aszarr_method(page, data)
7790        assert_aszarr_method(page, data, chunkmode='page')
7791        assert__str__(tif)
7792
7793
7794@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
7795def test_read_ome_samplesperpixel_mismatch(caplog):
7796    """Test read OME with SamplesPerPixel mismatch: OME=1, TIFF=4."""
7797    # https://forum.image.sc/t/ilastik-refuses-to-load-image-file/48541/1
7798    fname = private_file('OME/MismatchSamplesPerPixel.ome.tif')
7799    with TiffFile(fname) as tif:
7800        assert tif.is_ome
7801        assert tif.byteorder == '<'
7802        assert len(tif.pages) == 1
7803        assert len(tif.series) == 1
7804        # assert page properties
7805        page = tif.pages[0]
7806        assert page.photometric == RGB
7807        assert page.compression == LZW
7808        assert page.imagewidth == 2080
7809        assert page.imagelength == 1552
7810        assert page.bitspersample == 8
7811        assert page.samplesperpixel == 4
7812        # assert series properties
7813        series = tif.series[0]
7814        assert 'OME series: cannot handle discontiguous storage' in caplog.text
7815        assert series.kind == 'Generic'
7816        assert series.shape == (1552, 2080, 4)
7817        assert series.dtype == numpy.uint8
7818        assert series.axes == 'YXS'
7819        assert not series.is_multifile
7820        # assert data
7821        data = tif.asarray()
7822        assert data.shape == (1552, 2080, 4)
7823        assert_aszarr_method(tif, data)
7824        assert__str__(tif)
7825
7826
7827@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7828def test_read_andor_light_sheet_512p():
7829    """Test read Andor."""
7830    # 12113x13453, uint16
7831    fname = private_file('andor/light sheet 512px.tif')
7832    with TiffFile(fname) as tif:
7833        assert tif.byteorder == '<'
7834        assert len(tif.pages) == 100
7835        assert len(tif.series) == 1
7836        assert tif.is_andor
7837        # assert page properties
7838        page = tif.pages[0]
7839        assert page.is_andor
7840        assert page.is_contiguous
7841        assert page.compression == NONE
7842        assert page.imagewidth == 512
7843        assert page.imagelength == 512
7844        assert page.bitspersample == 16
7845        assert page.samplesperpixel == 1
7846        # assert metadata
7847        t = page.andor_tags
7848        assert t['SoftwareVersion'] == '4.23.30014.0'
7849        assert t['Frames'] == 100.0
7850        # assert series properties
7851        series = tif.series[0]
7852        assert series.shape == (100, 512, 512)
7853        assert series.dtype == numpy.uint16
7854        assert series.axes == 'IYX'
7855        # assert data
7856        data = tif.asarray()
7857        assert data.shape == (100, 512, 512)
7858        assert data.dtype == numpy.uint16
7859        assert round(abs(data[50, 256, 256] - 703), 7) == 0
7860        assert_aszarr_method(tif, data)
7861        assert_aszarr_method(tif, data, chunkmode='page')
7862        assert__str__(tif, 0)
7863
7864
7865@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7866def test_read_nih_morph():
7867    """Test read NIH."""
7868    # 388x252 uint8
7869    fname = private_file('nihimage/morph.tiff')
7870    with TiffFile(fname) as tif:
7871        assert tif.is_nih
7872        assert tif.byteorder == '>'
7873        assert len(tif.pages) == 1
7874        assert len(tif.series) == 1
7875        # assert page properties
7876        page = tif.pages[0]
7877        assert page.imagewidth == 388
7878        assert page.imagelength == 252
7879        assert page.bitspersample == 8
7880        # assert series properties
7881        series = tif.series[0]
7882        assert series.shape == (252, 388)
7883        assert series.dtype == numpy.uint8
7884        assert series.axes == 'YX'
7885        # assert NIH tags
7886        tags = tif.nih_metadata
7887        assert tags['FileID'] == 'IPICIMAG'
7888        assert tags['PixelsPerLine'] == 388
7889        assert tags['nLines'] == 252
7890        assert tags['ForegroundIndex'] == 255
7891        # assert data
7892        data = tif.asarray()
7893        assert isinstance(data, numpy.ndarray)
7894        assert data.shape == (252, 388)
7895        assert data.dtype == numpy.uint8
7896        assert data[195, 144] == 41
7897        assert_aszarr_method(tif, data)
7898        assert_aszarr_method(tif, data, chunkmode='page')
7899        assert__str__(tif)
7900
7901
7902@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7903def test_read_nih_silver_lake():
7904    """Test read NIH palette."""
7905    # 259x187 16 bit palette
7906    fname = private_file('nihimage/silver lake.tiff')
7907    with TiffFile(fname) as tif:
7908        assert tif.is_nih
7909        assert tif.byteorder == '>'
7910        assert len(tif.pages) == 1
7911        assert len(tif.series) == 1
7912        # assert page properties
7913        page = tif.pages[0]
7914        assert page.is_contiguous
7915        assert page.photometric == PALETTE
7916        assert page.imagewidth == 259
7917        assert page.imagelength == 187
7918        assert page.bitspersample == 8
7919        # assert series properties
7920        series = tif.series[0]
7921        assert series.shape == (187, 259)
7922        assert series.dtype == numpy.uint8
7923        assert series.axes == 'YX'
7924        # assert NIH tags
7925        tags = tif.nih_metadata
7926        assert tags['FileID'] == 'IPICIMAG'
7927        assert tags['PixelsPerLine'] == 259
7928        assert tags['nLines'] == 187
7929        assert tags['ForegroundIndex'] == 109
7930        # assert data
7931        data = page.asrgb()
7932        assert isinstance(data, numpy.ndarray)
7933        assert data.shape == (187, 259, 3)
7934        assert data.dtype == numpy.uint16
7935        assert tuple(data[86, 102, :]) == (26214, 39321, 39321)
7936        assert__str__(tif)
7937
7938
7939@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
7940def test_read_nih_scala_media():
7941    """Test read multi-page NIH."""
7942    # 36x54x84 palette
7943    fname = private_file('nihimage/scala-media.tif')
7944    with TiffFile(fname) as tif:
7945        assert tif.is_nih
7946        assert tif.byteorder == '>'
7947        assert len(tif.pages) == 36
7948        assert len(tif.series) == 1
7949        # assert page properties
7950        page = tif.pages[0]
7951        assert page.is_contiguous
7952        assert page.photometric == PALETTE
7953        assert page.imagewidth == 84
7954        assert page.imagelength == 54
7955        assert page.bitspersample == 8
7956        # assert series properties
7957        series = tif.series[0]
7958        assert series.shape == (36, 54, 84)
7959        assert series.dtype == numpy.uint8
7960        assert series.axes == 'IYX'
7961        assert series.kind == 'NIHImage'
7962        # assert NIH tags
7963        tags = tif.nih_metadata
7964        assert tags['Version'] == 160
7965        assert tags['nLines'] == 54
7966        # assert data
7967        data = tif.asarray()
7968        assert isinstance(data, numpy.ndarray)
7969        assert data.shape == (36, 54, 84)
7970        assert data.dtype == numpy.uint8
7971        assert data[35, 35, 65] == 171
7972        assert_aszarr_method(tif, data)
7973        assert_aszarr_method(tif, data, chunkmode='page')
7974        assert__str__(tif)
7975
7976
7977@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
7978def test_read_imagej_rrggbb():
7979    """Test read planar RGB ImageJ file created by Bio-Formats."""
7980    fname = public_file('tifffile/rrggbb.ij.tif')
7981    with TiffFile(fname) as tif:
7982        assert tif.is_imagej
7983        assert tif.byteorder == '<'
7984        assert len(tif.pages) == 1
7985        assert len(tif.series) == 1
7986        # assert page properties
7987        page = tif.pages[0]
7988        assert page.photometric == RGB
7989        assert page.compression == LZW
7990        assert page.imagewidth == 31
7991        assert page.imagelength == 32
7992        assert page.bitspersample == 16
7993        # assert series properties
7994        series = tif.series[0]
7995        assert series.dtype == numpy.uint16
7996        assert series.shape == (3, 32, 31)
7997        assert series.axes == 'CYX'
7998        assert series.get_shape(False) == (1, 1, 3, 32, 31, 1)
7999        assert series.get_axes(False) == 'TZCYXS'
8000        assert len(series._pages) == 1
8001        assert len(series.pages) == 1
8002        # assert ImageJ tags
8003        ijtags = tif.imagej_metadata
8004        assert ijtags['ImageJ'] == ''
8005        assert ijtags['images'] == 3
8006        assert ijtags['channels'] == 3
8007        assert ijtags['slices'] == 1
8008        assert ijtags['frames'] == 1
8009        assert ijtags['hyperstack']
8010        # assert data
8011        data = tif.asarray()
8012        assert isinstance(data, numpy.ndarray)
8013        assert data.shape == (3, 32, 31)
8014        assert data.dtype == numpy.uint16
8015        assert tuple(data[:, 15, 15]) == (812, 1755, 648)
8016        assert_decode_method(page)
8017        assert_aszarr_method(series, data)
8018        assert_aszarr_method(series, data, chunkmode='page')
8019        # don't squeeze
8020        data = tif.asarray(squeeze=False)
8021        assert data.shape == (1, 1, 3, 32, 31, 1)
8022        assert_aszarr_method(series, data, squeeze=False)
8023        assert__str__(tif, 0)
8024
8025
8026@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8027def test_read_imagej_focal1():
8028    """Test read ImageJ 205x434x425 uint8."""
8029    fname = private_file('imagej/focal1.tif')
8030    with TiffFile(fname) as tif:
8031        assert tif.is_imagej
8032        assert tif.byteorder == '>'
8033        assert len(tif.pages) == 205
8034        assert len(tif.series) == 1
8035        # assert page properties
8036        page = tif.pages[0]
8037        assert page.photometric != RGB
8038        assert page.imagewidth == 425
8039        assert page.imagelength == 434
8040        assert page.bitspersample == 8
8041        assert page.is_contiguous
8042        # assert series properties
8043        series = tif.series[0]
8044        assert series.offset == 768
8045        assert series.shape == (205, 434, 425)
8046        assert series.dtype == numpy.uint8
8047        assert series.axes == 'IYX'
8048        assert series.get_shape(False) == (205, 1, 1, 1, 434, 425, 1)
8049        assert series.get_axes(False) == 'ITZCYXS'
8050        assert len(series._pages) == 1
8051        assert len(series.pages) == 205
8052        # assert ImageJ tags
8053        ijtags = tif.imagej_metadata
8054        assert ijtags['ImageJ'] == '1.34k'
8055        assert ijtags['images'] == 205
8056        # assert data
8057        data = tif.asarray()
8058        assert isinstance(data, numpy.ndarray)
8059        assert data.shape == (205, 434, 425)
8060        assert data.dtype == numpy.uint8
8061        assert data[102, 216, 212] == 120
8062        assert_aszarr_method(series, data)
8063        assert_aszarr_method(series, data, chunkmode='page')
8064        assert__str__(tif, 0)
8065
8066
8067@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8068def test_read_imagej_hela_cells():
8069    """Test read ImageJ 512x672 RGB uint16."""
8070    fname = private_file('imagej/hela-cells.tif')
8071    with TiffFile(fname) as tif:
8072        assert tif.is_imagej
8073        assert tif.byteorder == '>'
8074        assert len(tif.pages) == 1
8075        assert len(tif.series) == 1
8076        # assert page properties
8077        page = tif.pages[0]
8078        assert page.photometric == RGB
8079        assert page.imagewidth == 672
8080        assert page.imagelength == 512
8081        assert page.bitspersample == 16
8082        assert page.is_contiguous
8083        # assert series properties
8084        series = tif.series[0]
8085        assert series.shape == (512, 672, 3)
8086        assert series.dtype == numpy.uint16
8087        assert series.axes == 'YXS'
8088        assert series.get_shape(False) == (1, 1, 1, 512, 672, 3)
8089        assert series.get_axes(False) == 'TZCYXS'
8090        # assert ImageJ tags
8091        ijtags = tif.imagej_metadata
8092        assert ijtags['ImageJ'] == '1.46i'
8093        assert ijtags['channels'] == 3
8094        # assert data
8095        data = tif.asarray()
8096        assert isinstance(data, numpy.ndarray)
8097        assert data.shape == (512, 672, 3)
8098        assert data.dtype == numpy.uint16
8099        assert tuple(data[255, 336]) == (440, 378, 298)
8100        assert_aszarr_method(series, data)
8101        assert_aszarr_method(series, data, chunkmode='page')
8102        # don't squeeze
8103        data = tif.asarray(squeeze=False)
8104        assert data.shape == (1, 1, 1, 512, 672, 3)
8105        assert_aszarr_method(series, data, squeeze=False)
8106        assert__str__(tif)
8107
8108
8109@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8110def test_read_imagej_flybrain():
8111    """Test read ImageJ 57x256x256 RGB."""
8112    fname = private_file('imagej/flybrain.tif')
8113    with TiffFile(fname) as tif:
8114        assert tif.is_imagej
8115        assert tif.byteorder == '>'
8116        assert len(tif.pages) == 57
8117        assert len(tif.series) == 1  # hyperstack
8118        # assert page properties
8119        page = tif.pages[0]
8120        assert page.photometric == RGB
8121        assert page.imagewidth == 256
8122        assert page.imagelength == 256
8123        assert page.bitspersample == 8
8124        # assert series properties
8125        series = tif.series[0]
8126        assert series.shape == (57, 256, 256, 3)
8127        assert series.dtype == numpy.uint8
8128        assert series.axes == 'ZYXS'
8129        assert series.get_shape(False) == (1, 57, 1, 256, 256, 3)
8130        assert series.get_axes(False) == 'TZCYXS'
8131        # assert ImageJ tags
8132        ijtags = tif.imagej_metadata
8133        assert ijtags['ImageJ'] == '1.43d'
8134        assert ijtags['slices'] == 57
8135        # assert data
8136        data = tif.asarray()
8137        assert isinstance(data, numpy.ndarray)
8138        assert data.shape == (57, 256, 256, 3)
8139        assert data.dtype == numpy.uint8
8140        assert tuple(data[18, 108, 97]) == (165, 157, 0)
8141        assert_aszarr_method(series, data)
8142        assert_aszarr_method(series, data, chunkmode='page')
8143        # don't squeeze
8144        data = tif.asarray(squeeze=False)
8145        assert data.shape == (1, 57, 1, 256, 256, 3)
8146        assert_aszarr_method(series, data, squeeze=False)
8147        assert__str__(tif)
8148
8149
8150@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8151def test_read_imagej_confocal_series():
8152    """Test read ImageJ 25x2x400x400 ZCYX."""
8153    fname = private_file('imagej/confocal-series.tif')
8154    with TiffFile(fname) as tif:
8155        assert tif.is_imagej
8156        assert tif.byteorder == '>'
8157        assert len(tif.pages) == 50
8158        assert len(tif.series) == 1  # hyperstack
8159        # assert page properties
8160        page = tif.pages[0]
8161        assert page.imagewidth == 400
8162        assert page.imagelength == 400
8163        assert page.bitspersample == 8
8164        assert page.is_contiguous
8165        # assert series properties
8166        series = tif.series[0]
8167        assert series.shape == (25, 2, 400, 400)
8168        assert series.dtype == numpy.uint8
8169        assert series.axes == 'ZCYX'
8170        assert len(series._pages) == 1
8171        assert len(series.pages) == 50
8172        # assert ImageJ tags
8173        ijtags = tif.imagej_metadata
8174        assert ijtags['ImageJ'] == '1.43d'
8175        assert ijtags['images'] == len(tif.pages)
8176        assert ijtags['channels'] == 2
8177        assert ijtags['slices'] == 25
8178        assert ijtags['hyperstack']
8179        # assert data
8180        data = tif.asarray()
8181        assert isinstance(data, numpy.ndarray)
8182        assert data.shape == (25, 2, 400, 400)
8183        assert data.dtype == numpy.uint8
8184        assert tuple(data[12, :, 100, 300]) == (6, 66)
8185        # assert only two pages are loaded
8186        assert isinstance(tif.pages.pages[0], TiffPage)
8187        if tif.pages.cache:
8188            assert isinstance(tif.pages.pages[1], TiffFrame)
8189        else:
8190            assert tif.pages.pages[1] == 8000911
8191        assert tif.pages.pages[2] == 8001073
8192        assert tif.pages.pages[-1] == 8008687
8193        assert_aszarr_method(series, data)
8194        assert_aszarr_method(series, data, chunkmode='page')
8195        # don't squeeze
8196        data = tif.asarray(squeeze=False)
8197        assert data.shape == (1, 25, 2, 400, 400, 1)
8198        assert_aszarr_method(series, data, squeeze=False)
8199        assert__str__(tif)
8200
8201
8202@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8203def test_read_imagej_graphite():
8204    """Test read ImageJ 1024x593 float32."""
8205    fname = private_file('imagej/graphite1-1024.tif')
8206    with TiffFile(fname) as tif:
8207        assert tif.is_imagej
8208        assert tif.byteorder == '>'
8209        assert len(tif.pages) == 1
8210        assert len(tif.series) == 1
8211        # assert page properties
8212        page = tif.pages[0]
8213        assert page.imagewidth == 1024
8214        assert page.imagelength == 593
8215        assert page.bitspersample == 32
8216        assert page.is_contiguous
8217        # assert series properties
8218        series = tif.series[0]
8219        assert len(series._pages) == 1
8220        assert len(series.pages) == 1
8221        assert series.shape == (593, 1024)
8222        assert series.dtype == numpy.float32
8223        assert series.axes == 'YX'
8224        # assert ImageJ tags
8225        ijtags = tif.imagej_metadata
8226        assert ijtags['ImageJ'] == '1.47t'
8227        assert round(abs(ijtags['max'] - 1686.10949707), 7) == 0
8228        assert round(abs(ijtags['min'] - 852.08605957), 7) == 0
8229        # assert data
8230        data = tif.asarray()
8231        assert isinstance(data, numpy.ndarray)
8232        assert data.shape == (593, 1024)
8233        assert data.dtype == numpy.float32
8234        assert round(abs(data[443, 656] - 2203.040771484375), 7) == 0
8235        assert_aszarr_method(series, data)
8236        # don't squeeze
8237        data = tif.asarray(squeeze=False)
8238        assert data.shape == (1, 1, 1, 593, 1024, 1)
8239        assert_aszarr_method(series, data, squeeze=False)
8240        assert__str__(tif)
8241
8242
8243@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8244def test_read_imagej_bat_cochlea_volume():
8245    """Test read ImageJ 114 images, no frames, slices, channels specified."""
8246    fname = private_file('imagej/bat-cochlea-volume.tif')
8247    with TiffFile(fname) as tif:
8248        assert tif.is_imagej
8249        assert tif.byteorder == '>'
8250        assert len(tif.pages) == 114
8251        assert len(tif.series) == 1
8252        # assert page properties
8253        page = tif.pages[0]
8254        assert page.photometric != RGB
8255        assert page.imagewidth == 121
8256        assert page.imagelength == 154
8257        assert page.bitspersample == 8
8258        assert page.is_contiguous
8259        # assert series properties
8260        series = tif.series[0]
8261        assert len(series._pages) == 1
8262        assert len(series.pages) == 114
8263        assert series.shape == (114, 154, 121)
8264        assert series.dtype == numpy.uint8
8265        assert series.axes == 'IYX'
8266        # assert ImageJ tags
8267        ijtags = tif.imagej_metadata
8268        assert ijtags['ImageJ'] == '1.20n'
8269        assert ijtags['images'] == 114
8270        # assert data
8271        data = tif.asarray()
8272        assert isinstance(data, numpy.ndarray)
8273        assert data.shape == (114, 154, 121)
8274        assert data.dtype == numpy.uint8
8275        assert data[113, 97, 61] == 255
8276        assert_aszarr_method(series, data)
8277        # don't squeeze
8278        data = tif.asarray(squeeze=False)
8279        assert data.shape == (114, 1, 1, 1, 154, 121, 1)
8280        assert_aszarr_method(series, data, squeeze=False)
8281        assert__str__(tif)
8282
8283
8284@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8285def test_read_imagej_first_instar_brain():
8286    """Test read ImageJ 56x256x256x3 ZYXS."""
8287    fname = private_file('imagej/first-instar-brain.tif')
8288    with TiffFile(fname) as tif:
8289        assert tif.is_imagej
8290        assert tif.byteorder == '>'
8291        assert len(tif.pages) == 56
8292        assert len(tif.series) == 1
8293        # assert page properties
8294        page = tif.pages[0]
8295        assert page.photometric == RGB
8296        assert page.imagewidth == 256
8297        assert page.imagelength == 256
8298        assert page.bitspersample == 8
8299        assert page.is_contiguous
8300        # assert series properties
8301        series = tif.series[0]
8302        assert len(series._pages) == 1
8303        assert len(series.pages) == 56
8304        assert series.shape == (56, 256, 256, 3)
8305        assert series.dtype == numpy.uint8
8306        assert series.axes == 'ZYXS'
8307        # assert ImageJ tags
8308        ijtags = tif.imagej_metadata
8309        assert ijtags['ImageJ'] == '1.44j'
8310        assert ijtags['images'] == 56
8311        assert ijtags['slices'] == 56
8312        # assert data
8313        data = tif.asarray()
8314        assert isinstance(data, numpy.ndarray)
8315        assert data.shape == (56, 256, 256, 3)
8316        assert data.dtype == numpy.uint8
8317        assert tuple(data[55, 151, 112]) == (209, 8, 58)
8318        assert_aszarr_method(series, data)
8319        assert__str__(tif)
8320
8321
8322@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8323def test_read_imagej_fluorescentcells():
8324    """Test read ImageJ three channels."""
8325    fname = private_file('imagej/FluorescentCells.tif')
8326    with TiffFile(fname) as tif:
8327        assert tif.is_imagej
8328        assert tif.byteorder == '>'
8329        assert len(tif.pages) == 3
8330        assert len(tif.series) == 1
8331        # assert page properties
8332        page = tif.pages[0]
8333        assert page.photometric == PALETTE
8334        assert page.imagewidth == 512
8335        assert page.imagelength == 512
8336        assert page.bitspersample == 8
8337        assert page.is_contiguous
8338        # assert series properties
8339        series = tif.series[0]
8340        assert series.shape == (3, 512, 512)
8341        assert series.dtype == numpy.uint8
8342        assert series.axes == 'CYX'
8343        # assert ImageJ tags
8344        ijtags = tif.imagej_metadata
8345        assert ijtags['ImageJ'] == '1.40c'
8346        assert ijtags['images'] == 3
8347        assert ijtags['channels'] == 3
8348        # assert data
8349        data = tif.asarray()
8350        assert isinstance(data, numpy.ndarray)
8351        assert data.shape == (3, 512, 512)
8352        assert data.dtype == numpy.uint8
8353        assert tuple(data[:, 256, 256]) == (57, 120, 13)
8354        assert_aszarr_method(series, data)
8355        assert__str__(tif)
8356
8357
8358@pytest.mark.skipif(SKIP_PUBLIC or SKIP_LARGE, reason=REASON)
8359def test_read_imagej_100000_pages():
8360    """Test read ImageJ with 100000 pages."""
8361    # 100000x64x64
8362    # file is big endian, memory mapped
8363    fname = public_file('tifffile/100000_pages.tif')
8364    with TiffFile(fname) as tif:
8365        assert tif.is_imagej
8366        assert tif.byteorder == '>'
8367        assert len(tif.pages) == 100000
8368        assert len(tif.series) == 1
8369        # assert page properties
8370        page = tif.pages[0]
8371        assert page.imagewidth == 64
8372        assert page.imagelength == 64
8373        assert page.bitspersample == 16
8374        assert page.is_contiguous
8375        # assert series properties
8376        series = tif.series[0]
8377        assert len(series._pages) == 1
8378        assert len(series.pages) == 100000
8379        assert series.shape == (100000, 64, 64)
8380        assert series.dtype == numpy.uint16
8381        assert series.axes == 'TYX'
8382        # assert ImageJ tags
8383        ijtags = tif.imagej_metadata
8384        assert ijtags['ImageJ'] == '1.48g'
8385        assert round(abs(ijtags['max'] - 119.0), 7) == 0
8386        assert round(abs(ijtags['min'] - 86.0), 7) == 0
8387        # assert data
8388        data = tif.asarray(out='memmap')
8389        assert isinstance(data, numpy.core.memmap)
8390        assert data.shape == (100000, 64, 64)
8391        assert data.dtype == numpy.dtype('>u2')
8392        assert round(abs(data[7310, 25, 25] - 100), 7) == 0
8393        # too slow: assert_aszarr_method(series, data)
8394        assert__str__(tif, 0)
8395        del data
8396
8397
8398@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8399def test_read_imagej_invalid_metadata(caplog):
8400    """Test read bad ImageJ metadata."""
8401    # file contains 1 page but metadata claims 3500 images
8402    # memory map big endian data
8403    fname = private_file('sima/0.tif')
8404    with TiffFile(fname) as tif:
8405        assert tif.is_imagej
8406        assert tif.byteorder == '>'
8407        assert len(tif.pages) == 1
8408        assert len(tif.series) == 1
8409        assert 'invalid metadata or corrupted file' in caplog.text
8410        # assert page properties
8411        page = tif.pages[0]
8412        assert page.photometric != RGB
8413        assert page.imagewidth == 173
8414        assert page.imagelength == 173
8415        assert page.bitspersample == 16
8416        assert page.is_contiguous
8417        # assert series properties
8418        series = tif.series[0]
8419        assert series.offset == 8  # 8
8420        assert series.shape == (173, 173)
8421        assert series.dtype == numpy.uint16
8422        assert series.axes == 'YX'
8423        # assert ImageJ tags
8424        ijtags = tif.imagej_metadata
8425        assert ijtags['ImageJ'] == '1.49i'
8426        assert ijtags['images'] == 3500
8427        # assert data
8428        data = tif.asarray(out='memmap')
8429        assert isinstance(data, numpy.core.memmap)
8430        assert data.shape == (173, 173)
8431        assert data.dtype == numpy.dtype('>u2')
8432        assert data[94, 34] == 1257
8433        assert_aszarr_method(series, data)
8434        assert_aszarr_method(series, data, chunkmode='page')
8435        assert__str__(tif)
8436        del data
8437
8438
8439@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8440def test_read_imagej_invalid_hyperstack():
8441    """Test read bad ImageJ hyperstack."""
8442    # file claims to be a hyperstack but is not stored as such
8443    # produced by OME writer
8444    # reported by Taras Golota on 10/27/2016
8445    fname = private_file('imagej/X0.ome.CTZ.perm.tif')
8446    with TiffFile(fname) as tif:
8447        assert tif.is_imagej
8448        assert tif.byteorder == '<'
8449        assert len(tif.pages) == 48  # not a hyperstack
8450        assert len(tif.series) == 1
8451        # assert page properties
8452        page = tif.pages[0]
8453        assert page.photometric != RGB
8454        assert page.imagewidth == 1392
8455        assert page.imagelength == 1040
8456        assert page.bitspersample == 16
8457        assert page.is_contiguous
8458        # assert series properties
8459        series = tif.series[0]
8460        assert series.offset is None  # not contiguous
8461        assert series.shape == (2, 4, 6, 1040, 1392)
8462        assert series.dtype == numpy.uint16
8463        assert series.axes == 'TZCYX'
8464        # assert ImageJ tags
8465        ijtags = tif.imagej_metadata
8466        assert ijtags['hyperstack']
8467        assert ijtags['images'] == 48
8468        assert__str__(tif)
8469
8470
8471@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8472def test_read_fluoview_lsp1_v_laser():
8473    """Test read FluoView CTYX."""
8474    # raises 'UnicodeWarning: Unicode equal comparison failed' on Python 2
8475    fname = private_file('fluoview/lsp1-V-laser0.3-1.tif')
8476    with TiffFile(fname) as tif:
8477        assert tif.byteorder == '<'
8478        assert len(tif.pages) == 100
8479        assert len(tif.series) == 1
8480        assert tif.is_fluoview
8481        # assert page properties
8482        page = tif.pages[0]
8483        assert page.is_fluoview
8484        assert page.is_contiguous
8485        assert page.compression == NONE
8486        assert page.imagewidth == 256
8487        assert page.imagelength == 256
8488        assert page.bitspersample == 16
8489        assert page.samplesperpixel == 1
8490        # assert metadata
8491        m = fluoview_description_metadata(page.description)
8492        assert m['Version Info']['FLUOVIEW Version'] == (
8493            'FV10-ASW ,ValidBitColunt=12'
8494        )
8495        assert tuple(m['LUT Ch1'][255]) == (255, 255, 255)
8496        mm = tif.fluoview_metadata
8497        assert mm['ImageName'] == 'lsp1-V-laser0.3-1.oib'
8498        # assert series properties
8499        series = tif.series[0]
8500        assert series.shape == (2, 50, 256, 256)
8501        assert series.dtype == numpy.uint16
8502        assert series.axes == 'CTYX'
8503        # assert data
8504        data = tif.asarray()
8505        assert data.shape == (2, 50, 256, 256)
8506        assert data.dtype == numpy.uint16
8507        assert round(abs(data[1, 36, 128, 128] - 824), 7) == 0
8508        assert_aszarr_method(series, data)
8509        assert_aszarr_method(series, data, chunkmode='page')
8510        assert__str__(tif)
8511
8512
8513@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
8514def test_read_fluoview_120816_bf_f0000():
8515    """Test read FluoView TZYX."""
8516    fname = private_file('fluoview/120816_bf_f0000.tif')
8517    with TiffFile(fname) as tif:
8518        assert tif.byteorder == '<'
8519        assert len(tif.pages) == 864
8520        assert len(tif.series) == 1
8521        assert tif.is_fluoview
8522        # assert page properties
8523        page = tif.pages[0]
8524        assert page.is_fluoview
8525        assert page.is_contiguous
8526        assert page.compression == NONE
8527        assert page.imagewidth == 1024
8528        assert page.imagelength == 1024
8529        assert page.bitspersample == 16
8530        assert page.samplesperpixel == 1
8531        # assert metadata
8532        m = fluoview_description_metadata(page.description)
8533        assert m['Environment']['User'] == 'admin'
8534        assert m['Region Info (Fields) Field']['Width'] == 1331.2
8535        m = tif.fluoview_metadata
8536        assert m['ImageName'] == '120816_bf'
8537        # assert series properties
8538        series = tif.series[0]
8539        assert series.shape == (144, 6, 1024, 1024)
8540        assert series.dtype == numpy.uint16
8541        assert series.axes == 'TZYX'
8542        # assert data
8543        data = tif.asarray()
8544        assert data.shape == (144, 6, 1024, 1024)
8545        assert data.dtype == numpy.uint16
8546        assert round(abs(data[1, 2, 128, 128] - 8317), 7) == 0
8547        # too slow: assert_aszarr_method(series, data)
8548        assert__str__(tif)
8549
8550
8551@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
8552def test_read_metaseries():
8553    """Test read MetaSeries 1040x1392 uint16, LZW."""
8554    # Strips do not contain an EOI code as required by the TIFF spec.
8555    fname = private_file('metaseries/metaseries.tif')
8556    with TiffFile(fname) as tif:
8557        assert tif.byteorder == '<'
8558        assert len(tif.pages) == 1
8559        assert len(tif.series) == 1
8560        # assert page properties
8561        page = tif.pages[0]
8562        assert page.imagewidth == 1392
8563        assert page.imagelength == 1040
8564        assert page.bitspersample == 16
8565        # assert metadata
8566        assert page.description.startswith('<MetaData>')
8567        # assert series properties
8568        series = tif.series[0]
8569        assert series.shape == (1040, 1392)
8570        assert series.dtype == numpy.uint16
8571        assert series.axes == 'YX'
8572        # assert data
8573        data = tif.asarray()
8574        assert data.shape == (1040, 1392)
8575        assert data.dtype == numpy.uint16
8576        assert data[256, 256] == 1917
8577        assert_aszarr_method(series, data)
8578        assert_aszarr_method(series, data, chunkmode='page')
8579        assert__str__(tif)
8580
8581
8582@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8583def test_read_metaseries_g4d7r():
8584    """Test read Metamorph/Metaseries."""
8585    # 12113x13453, uint16
8586    fname = private_file('metaseries/g4d7r.tif')
8587    with TiffFile(fname) as tif:
8588        assert tif.byteorder == '<'
8589        assert len(tif.pages) == 1
8590        assert len(tif.series) == 1
8591        assert tif.is_metaseries
8592        # assert page properties
8593        page = tif.pages[0]
8594        assert page.is_metaseries
8595        assert page.is_contiguous
8596        assert page.compression == NONE
8597        assert page.imagewidth == 13453
8598        assert page.imagelength == 12113
8599        assert page.bitspersample == 16
8600        assert page.samplesperpixel == 1
8601        # assert metadata
8602        m = metaseries_description_metadata(page.description)
8603        assert m['ApplicationVersion'] == '7.8.6.0'
8604        assert m['PlaneInfo']['pixel-size-x'] == 13453
8605        assert m['SetInfo']['number-of-planes'] == 1
8606        # assert series properties
8607        series = tif.series[0]
8608        assert series.shape == (12113, 13453)
8609        assert series.dtype == numpy.uint16
8610        assert series.axes == 'YX'
8611        # assert data
8612        data = tif.asarray(out='memmap')
8613        assert isinstance(data, numpy.core.memmap)
8614        assert data.shape == (12113, 13453)
8615        assert data.dtype == numpy.dtype('<u2')
8616        assert round(abs(data[512, 2856] - 4095), 7) == 0
8617        if not SKIP_LARGE:
8618            assert_aszarr_method(series, data)
8619            assert_aszarr_method(series, data, chunkmode='page')
8620        assert__str__(tif)
8621
8622
8623@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8624def test_read_mdgel_rat():
8625    """Test read Molecular Dynamics GEL."""
8626    # Second page does not contain data, only private tags
8627    fname = private_file('mdgel/rat.gel')
8628    with TiffFile(fname) as tif:
8629        assert tif.byteorder == '<'
8630        assert len(tif.pages) == 2
8631        assert len(tif.series) == 1
8632        # assert page properties
8633        page = tif.pages[0]
8634        assert page.is_contiguous
8635        assert page.compression == NONE
8636        assert page.imagewidth == 1528
8637        assert page.imagelength == 413
8638        assert page.bitspersample == 16
8639        assert page.samplesperpixel == 1
8640        assert page.tags['Software'].value == (
8641            'ImageQuant Software Release Version 2.0'
8642        )
8643        assert page.tags['PageName'].value == r'C:\DATA\RAT.GEL'
8644
8645        # assert 2nd page properties
8646        page = tif.pages[1]
8647        assert page.is_mdgel
8648        assert page.imagewidth == 0
8649        assert page.imagelength == 0
8650        assert page.bitspersample == 1
8651        assert page.samplesperpixel == 1
8652        assert page.tags['MDFileTag'].value == 2
8653        assert page.tags['MDScalePixel'].value == (1, 21025)
8654        assert len(page.tags['MDColorTable'].value) == 17
8655        md = tif.mdgel_metadata
8656        assert md['SampleInfo'] == 'Rat slices from Dr. Schweitzer'
8657        assert md['PrepDate'] == '12 July 90'
8658        assert md['PrepTime'] == '40hr'
8659        assert md['FileUnits'] == 'Counts'
8660
8661        # assert series properties
8662        series = tif.series[0]
8663        assert series.shape == (413, 1528)
8664        assert series.dtype == numpy.float32
8665        assert series.axes == 'YX'
8666        # assert data
8667        data = series.asarray()
8668        assert isinstance(data, numpy.ndarray)
8669        assert data.shape == (413, 1528)
8670        assert data.dtype == numpy.float32
8671        assert round(abs(data[260, 740] - 399.1728515625), 7) == 0
8672        assert_aszarr_method(series, data)
8673        assert_aszarr_method(series, data, chunkmode='page')
8674        assert__str__(tif)
8675
8676
8677@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8678def test_read_mediacy_imagepro():
8679    """Test read Media Cybernetics SEQ."""
8680    # TZYX, uint16, OME multifile TIFF
8681    fname = private_file('mediacy/imagepro.tif')
8682    with TiffFile(fname) as tif:
8683        assert tif.byteorder == '<'
8684        assert len(tif.pages) == 1
8685        assert len(tif.series) == 1
8686        # assert page properties
8687        page = tif.pages[0]
8688        assert page.is_mediacy
8689        assert page.is_contiguous
8690        assert page.compression == NONE
8691        assert page.imagewidth == 201
8692        assert page.imagelength == 201
8693        assert page.bitspersample == 8
8694        assert page.samplesperpixel == 1
8695        assert page.tags['Software'].value == 'Image-Pro Plus'
8696        assert page.tags['MC_Id'].value[:-1] == b'MC TIFF 4.0'
8697        # assert series properties
8698        series = tif.series[0]
8699        assert series.shape == (201, 201)
8700        assert series.dtype == numpy.uint8
8701        assert series.axes == 'YX'
8702        # assert data
8703        data = tif.asarray()
8704        assert data.shape == (201, 201)
8705        assert data.dtype == numpy.uint8
8706        assert round(abs(data[120, 34] - 4), 7) == 0
8707        assert_aszarr_method(series, data)
8708        assert_aszarr_method(series, data, chunkmode='page')
8709        assert__str__(tif)
8710
8711
8712@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8713def test_read_pilatus_100k():
8714    """Test read Pilatus."""
8715    fname = private_file('TvxPilatus/Pilatus100K_scan030_033.tiff')
8716    with TiffFile(fname) as tif:
8717        assert tif.byteorder == '<'
8718        assert len(tif.pages) == 1
8719        assert tif.is_pilatus
8720        # assert page properties
8721        page = tif.pages[0]
8722        assert page.imagewidth == 487
8723        assert page.imagelength == 195
8724        assert page.bitspersample == 32
8725        assert page.samplesperpixel == 1
8726        # assert metadata
8727        assert page.tags['Model'].value == (
8728            'PILATUS 100K, S/N 1-0230, Cornell University'
8729        )
8730        attr = pilatus_description_metadata(page.description)
8731        assert attr['Tau'] == 1.991e-07
8732        assert attr['Silicon'] == 0.000320
8733        assert_aszarr_method(page)
8734        assert_aszarr_method(page, chunkmode='page')
8735        assert__str__(tif)
8736
8737
8738@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8739def test_read_pilatus_gibuf2():
8740    """Test read Pilatus."""
8741    fname = private_file('TvxPilatus/GIbuf2_A9_18_001_0009.tiff')
8742    with TiffFile(fname) as tif:
8743        assert tif.byteorder == '<'
8744        assert len(tif.pages) == 1
8745        assert tif.is_pilatus
8746        # assert page properties
8747        page = tif.pages[0]
8748        assert page.imagewidth == 487
8749        assert page.imagelength == 195
8750        assert page.bitspersample == 32
8751        assert page.samplesperpixel == 1
8752        # assert metadata
8753        assert page.tags['Model'].value == 'PILATUS 100K-S, S/N 1-0299,'
8754        attr = pilatus_description_metadata(page.description)
8755        assert attr['Filter_transmission'] == 1.0
8756        assert attr['Silicon'] == 0.000320
8757        assert_aszarr_method(page)
8758        assert__str__(tif)
8759
8760
8761@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8762def test_read_epics_attrib():
8763    """Test read EPICS."""
8764    fname = private_file('epics/attrib.tif')
8765    with TiffFile(fname) as tif:
8766        assert tif.is_epics
8767        assert tif.byteorder == '<'
8768        assert len(tif.pages) == 1
8769        assert len(tif.series) == 1
8770        # assert series properties
8771        series = tif.series[0]
8772        assert series.shape == (2048, 2048)
8773        assert series.dtype == numpy.uint16
8774        assert series.axes == 'YX'
8775        # assert page properties
8776        page = tif.pages[0]
8777        assert page.shape == (2048, 2048)
8778        assert page.imagewidth == 2048
8779        assert page.imagelength == 2048
8780        assert page.bitspersample == 16
8781        assert page.is_contiguous
8782        # assert EPICS tags
8783        tags = tif.epics_metadata
8784        assert tags['timeStamp'] == 802117891.5714135
8785        assert tags['uniqueID'] == 15
8786        assert tags['Focus'] == 0.6778
8787        assert epics_datetime(
8788            tags['epicsTSSec'], tags['epicsTSNsec']
8789        ) == datetime.datetime(2015, 6, 2, 11, 31, 56, 103746)
8790        assert_aszarr_method(page)
8791        assert_aszarr_method(page, chunkmode='page')
8792        assert__str__(tif)
8793
8794
8795@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8796def test_read_tvips_tietz_16bit():
8797    """Test read TVIPS metadata."""
8798    # file provided by Marco Oster on 10/26/2016
8799    fname = private_file('tvips/test_tietz_16bit.tif')
8800    with TiffFile(fname) as tif:
8801        assert tif.is_tvips
8802        tvips = tif.tvips_metadata
8803        assert tvips['Magic'] == 0xAAAAAAAA
8804        assert tvips['ImageFolder'] == 'B:\\4Marco\\Images\\Tiling_EMTOOLS\\'
8805        assert_aszarr_method(tif)
8806        assert__str__(tif)
8807
8808
8809@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8810def test_read_geotiff_dimapdocument():
8811    """Test read GeoTIFF with 43 MB XML tag value."""
8812    # tag 65000  45070067s @487  "<Dimap_Document...
8813    fname = private_file('geotiff/DimapDocument.tif')
8814    with TiffFile(fname) as tif:
8815        assert tif.is_geotiff
8816        assert tif.byteorder == '>'
8817        assert len(tif.pages) == 1
8818        assert len(tif.series) == 1
8819        # assert series properties
8820        series = tif.series[0]
8821        assert series.shape == (1830, 1830)
8822        assert series.dtype == numpy.uint16
8823        assert series.axes == 'YX'
8824        # assert page properties
8825        page = tif.pages[0]
8826        assert page.shape == (1830, 1830)
8827        assert page.imagewidth == 1830
8828        assert page.imagelength == 1830
8829        assert page.bitspersample == 16
8830        assert page.is_contiguous
8831        assert page.tags['65000'].value.startswith(
8832            '<?xml version="1.0" encoding="ISO-8859-1"?>'
8833        )
8834        # assert GeoTIFF tags
8835        tags = tif.geotiff_metadata
8836        assert tags['GTCitationGeoKey'] == 'WGS 84 / UTM zone 29N'
8837        assert tags['ProjectedCSTypeGeoKey'] == 32629
8838        assert_array_almost_equal(
8839            tags['ModelTransformation'],
8840            [
8841                [60.0, 0.0, 0.0, 6.0e5],
8842                [0.0, -60.0, 0.0, 5900040.0],
8843                [0.0, 0.0, 0.0, 0.0],
8844                [0.0, 0.0, 0.0, 1.0],
8845            ],
8846        )
8847        assert_aszarr_method(page)
8848        assert__str__(tif)
8849
8850
8851@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8852def test_read_geotiff_spaf27_markedcorrect():
8853    """Test read GeoTIFF."""
8854    fname = private_file('geotiff/spaf27_markedcorrect.tif')
8855    with TiffFile(fname) as tif:
8856        assert tif.is_geotiff
8857        assert tif.byteorder == '<'
8858        assert len(tif.pages) == 1
8859        assert len(tif.series) == 1
8860        # assert series properties
8861        series = tif.series[0]
8862        assert series.shape == (20, 20)
8863        assert series.dtype == numpy.uint8
8864        assert series.axes == 'YX'
8865        # assert page properties
8866        page = tif.pages[0]
8867        assert page.shape == (20, 20)
8868        assert page.imagewidth == 20
8869        assert page.imagelength == 20
8870        assert page.bitspersample == 8
8871        assert page.is_contiguous
8872        # assert GeoTIFF tags
8873        tags = tif.geotiff_metadata
8874        assert tags['GTCitationGeoKey'] == 'NAD27 / California zone VI'
8875        assert tags['GeogAngularUnitsGeoKey'] == 9102
8876        assert tags['ProjFalseOriginLatGeoKey'] == 32.1666666666667
8877        assert_array_almost_equal(
8878            tags['ModelPixelScale'], [195.509321, 198.32184, 0]
8879        )
8880        assert_aszarr_method(page)
8881        assert__str__(tif)
8882
8883
8884@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8885def test_read_geotiff_cint16():
8886    """Test read complex integer images."""
8887    fname = private_file('geotiff/cint16.tif')
8888    with TiffFile(fname) as tif:
8889        assert tif.is_geotiff
8890        assert tif.byteorder == '<'
8891        assert len(tif.pages) == 1
8892        assert len(tif.series) == 1
8893        # assert page properties
8894        page = tif.pages[0]
8895        assert page.sampleformat == 5
8896        assert page.bitspersample == 32
8897        assert page.dtype == numpy.complex64
8898        assert page.shape == (100, 100)
8899        assert page.imagewidth == 100
8900        assert page.imagelength == 100
8901        assert page.compression == ADOBE_DEFLATE
8902        assert not page.is_contiguous
8903        data = page.asarray()
8904        data[9, 11] == 0 + 0j
8905        assert_aszarr_method(page, data)
8906        assert__str__(tif)
8907
8908
8909@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
8910@pytest.mark.parametrize('bits', [16, 32])
8911def test_read_complexint(bits):
8912    """Test read complex integer images."""
8913    fname = private_file(f'gdal/cint{bits}.tif')
8914    with TiffFile(fname) as tif:
8915        assert tif.is_geotiff
8916        assert tif.byteorder == '<'
8917        assert len(tif.pages) == 1
8918        assert len(tif.series) == 1
8919        # assert page properties
8920        page = tif.pages[0]
8921        assert page.sampleformat == 5
8922        assert page.bitspersample == bits * 2
8923        assert page.dtype == f'complex{bits * 4}'
8924        assert page.shape == (20, 20)
8925        assert page.imagewidth == 20
8926        assert page.imagelength == 20
8927        assert not page.is_contiguous
8928        data = page.asarray()
8929        data[9, 11] == 107 + 0j
8930        # assert GeoTIFF tags
8931        tags = tif.geotiff_metadata
8932        assert tags['GTCitationGeoKey'] == 'NAD27 / UTM zone 11N'
8933        assert_aszarr_method(page, data)
8934        assert__str__(tif)
8935
8936
8937@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
8938def test_read_qpi():
8939    """Test read PerkinElmer-QPI, non Pyramid."""
8940    fname = private_file(
8941        'PerkinElmer-QPI/LuCa-7color_[13860,52919]_1x1component_data.tiff'
8942    )
8943    with TiffFile(fname) as tif:
8944        assert len(tif.series) == 2
8945        assert len(tif.pages) == 9
8946        assert tif.is_qpi
8947        page = tif.pages[0]
8948        assert page.compression == LZW
8949        assert page.photometric == MINISBLACK
8950        assert page.planarconfig == CONTIG
8951        assert page.imagewidth == 1868
8952        assert page.imagelength == 1400
8953        assert page.bitspersample == 32
8954        assert page.samplesperpixel == 1
8955        assert page.tags['Software'].value == 'PerkinElmer-QPI'
8956        series = tif.series[0]
8957        assert series.shape == (8, 1400, 1868)
8958        assert series.dtype == numpy.float32
8959        assert not series.is_pyramidal
8960        series = tif.series[1]
8961        assert series.shape == (350, 467, 3)
8962        assert series.dtype == numpy.uint8
8963        assert not series.is_pyramidal
8964        # assert data
8965        image = tif.asarray()
8966        assert image.shape == (8, 1400, 1868)
8967        assert image.dtype == numpy.float32
8968        assert image[7, 1200, 1500] == 2.2132580280303955
8969        image = tif.asarray(series=1)
8970        assert image.shape == (350, 467, 3)
8971        assert image.dtype == numpy.uint8
8972        assert image[300, 400, 1] == 48
8973        assert_aszarr_method(tif, image, series=1)
8974        assert_aszarr_method(tif, image, series=1, chunkmode='page')
8975        assert__str__(tif)
8976
8977
8978@pytest.mark.skipif(
8979    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
8980)
8981def test_read_philips():
8982    """Test read Philips DP pyramid."""
8983    # https://camelyon17.grand-challenge.org/Data/
8984    fname = private_file('PhilipsDP/test_001.tif')
8985    with TiffFile(fname) as tif:
8986        assert len(tif.series) == 1
8987        assert len(tif.pages) == 9
8988        assert tif.is_philips
8989        assert tif.philips_metadata.endswith('</DataObject>')
8990        page = tif.pages[0]
8991        assert page.compression == JPEG
8992        assert page.photometric == YCBCR
8993        assert page.planarconfig == CONTIG
8994        assert page.tags['ImageWidth'].value == 86016
8995        assert page.tags['ImageLength'].value == 89600
8996        assert page.imagewidth == 85654
8997        assert page.imagelength == 89225
8998        assert page.bitspersample == 8
8999        assert page.samplesperpixel == 3
9000        assert page.tags['Software'].value == 'Philips DP v1.0'
9001        series = tif.series[0]
9002        assert series.shape == (89225, 85654, 3)
9003        assert len(series.levels) == 9
9004        assert series.is_pyramidal
9005        # assert data
9006        image = tif.asarray(series=0, level=5)
9007        assert image.shape == (2789, 2677, 3)
9008        assert image[300, 400, 1] == 206
9009        assert_aszarr_method(series, image, level=5)
9010        assert_aszarr_method(series, image, level=5, chunkmode='page')
9011        assert__str__(tif)
9012
9013
9014@pytest.mark.skipif(
9015    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
9016)
9017def test_read_zif():
9018    """Test read Zoomable Image Format ZIF."""
9019    fname = private_file('zif/ZoomifyImageExample.zif')
9020    with TiffFile(fname) as tif:
9021        # assert tif.is_zif
9022        assert len(tif.pages) == 5
9023        assert len(tif.series) == 1
9024        for page in tif.pages:
9025            assert page.description == (
9026                'Created by Objective ' 'Pathology Services'
9027            )
9028        # first page
9029        page = tif.pages[0]
9030        assert page.photometric == YCBCR
9031        assert page.compression == JPEG
9032        assert page.shape == (3120, 2080, 3)
9033        assert tuple(page.asarray()[3110, 2070, :]) == (27, 45, 59)
9034        # page 4
9035        page = tif.pages[-1]
9036        assert page.photometric == YCBCR
9037        assert page.compression == JPEG
9038        assert page.shape == (195, 130, 3)
9039        assert tuple(page.asarray()[191, 127, :]) == (30, 49, 66)
9040        # series
9041        series = tif.series[0]
9042        assert series.is_pyramidal
9043        assert len(series.levels) == 5
9044        assert series.shape == (3120, 2080, 3)
9045        assert tuple(series.asarray()[3110, 2070, :]) == (27, 45, 59)
9046        assert series.levels[-1].shape == (195, 130, 3)
9047        assert tuple(series.asarray(level=-1)[191, 127, :]) == (30, 49, 66)
9048        assert_aszarr_method(series, level=-1)
9049        assert__str__(tif)
9050
9051
9052@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9053def test_read_sis():
9054    """Test read Olympus SIS."""
9055    fname = private_file('sis/4A5IE8EM_F00000409.tif')
9056    with TiffFile(fname) as tif:
9057        assert tif.is_sis
9058        assert tif.byteorder == '<'
9059        assert len(tif.pages) == 122
9060        assert len(tif.series) == 1
9061        # assert page properties
9062        page = tif.pages[0]
9063        assert page.is_contiguous
9064        assert page.imagewidth == 353
9065        assert page.imagelength == 310
9066        assert page.bitspersample == 16
9067        assert page.samplesperpixel == 1
9068        assert page.tags['Software'].value == 'analySIS 5.0'
9069        # assert data
9070        data = tif.asarray()
9071        assert data.shape == (61, 2, 310, 353)
9072        assert data[30, 1, 256, 256] == 210
9073        # assert metadata
9074        sis = tif.sis_metadata
9075        assert sis['axes'] == 'TC'
9076        assert sis['shape'] == (61, 2)
9077        assert sis['Band'][1]['BandName'] == 'Fura380'
9078        assert sis['Band'][0]['LUT'].shape == (256, 3)
9079        assert sis['Time']['TimePos'].shape == (61,)
9080        assert sis['name'] == 'Hela-Zellen'
9081        assert sis['magnification'] == 60.0
9082        assert_aszarr_method(tif, data)
9083        assert_aszarr_method(tif, data, chunkmode='page')
9084        assert__str__(tif)
9085
9086
9087@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9088def test_read_sis_noini():
9089    """Test read Olympus SIS without INI tag."""
9090    fname = private_file('sis/110.tif')
9091    with TiffFile(fname) as tif:
9092        assert tif.is_sis
9093        assert tif.byteorder == '<'
9094        assert len(tif.pages) == 1
9095        assert len(tif.series) == 1
9096        # assert page properties
9097        page = tif.pages[0]
9098        assert page.imagewidth == 2560
9099        assert page.imagelength == 1920
9100        assert page.bitspersample == 8
9101        assert page.samplesperpixel == 3
9102        # assert metadata
9103        sis = tif.sis_metadata
9104        assert 'axes' not in sis
9105        assert sis['magnification'] == 20.0
9106        assert__str__(tif)
9107
9108
9109@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9110def test_read_sem_metadata():
9111    """Test read Zeiss SEM metadata."""
9112    # file from hyperspy tests
9113    fname = private_file('hyperspy/test_tiff_Zeiss_SEM_1k.tif')
9114    with TiffFile(fname) as tif:
9115        assert tif.is_sem
9116        assert tif.byteorder == '<'
9117        assert len(tif.pages) == 1
9118        assert len(tif.series) == 1
9119        # assert page properties
9120        page = tif.pages[0]
9121        assert page.is_contiguous
9122        assert page.photometric == PALETTE
9123        assert page.imagewidth == 1024
9124        assert page.imagelength == 768
9125        assert page.bitspersample == 8
9126        assert page.samplesperpixel == 1
9127        # assert data and metadata
9128        data = page.asrgb()
9129        assert tuple(data[563, 320]) == (38550, 38550, 38550)
9130        sem = tif.sem_metadata
9131        assert sem[''][3] == 2.614514e-06
9132        assert sem['ap_date'] == ('Date', '23 Dec 2015')
9133        assert sem['ap_time'] == ('Time', '9:40:32')
9134        assert sem['dp_image_store'] == ('Store resolution', '1024 * 768')
9135        assert sem['ap_fib_fg_emission_actual'] == (
9136            'Flood Gun Emission Actual',
9137            0.0,
9138            'µA',
9139        )
9140        assert_aszarr_method(tif)
9141        assert__str__(tif)
9142
9143
9144@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9145def test_read_sem_bad_metadata():
9146    """Test read Zeiss SEM metadata with wrong length."""
9147    # reported by Klaus Schwarzburg on 8/27/2018
9148    fname = private_file('issues/sem_bad_metadata.tif')
9149    with TiffFile(fname) as tif:
9150        assert tif.is_sem
9151        assert tif.byteorder == '<'
9152        assert len(tif.pages) == 1
9153        assert len(tif.series) == 1
9154        # assert page properties
9155        page = tif.pages[0]
9156        assert page.is_contiguous
9157        assert page.photometric == PALETTE
9158        assert page.imagewidth == 1024
9159        assert page.imagelength == 768
9160        assert page.bitspersample == 8
9161        assert page.samplesperpixel == 1
9162        # assert data and metadata
9163        data = page.asrgb()
9164        assert tuple(data[350, 150]) == (17476, 17476, 17476)
9165        sem = tif.sem_metadata
9166        assert sem['sv_version'][1] == 'V05.07.00.00 : 08-Jul-14'
9167        assert_aszarr_method(tif)
9168        assert__str__(tif)
9169
9170
9171@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9172def test_read_fei_metadata():
9173    """Test read Helios FEI metadata."""
9174    # file from hyperspy tests
9175    fname = private_file('hyperspy/test_tiff_FEI_SEM.tif')
9176    with TiffFile(fname) as tif:
9177        assert tif.is_fei
9178        assert tif.byteorder == '<'
9179        assert len(tif.pages) == 1
9180        assert len(tif.series) == 1
9181        # assert page properties
9182        page = tif.pages[0]
9183        assert page.is_contiguous
9184        assert page.photometric != PALETTE
9185        assert page.imagewidth == 1536
9186        assert page.imagelength == 1103
9187        assert page.bitspersample == 8
9188        assert page.samplesperpixel == 1
9189        # assert data and metadata
9190        data = page.asarray()
9191        assert data[563, 320] == 220
9192        fei = tif.fei_metadata
9193        assert fei['User']['User'] == 'supervisor'
9194        assert fei['System']['DisplayHeight'] == 0.324
9195        assert_aszarr_method(tif)
9196        assert__str__(tif)
9197
9198
9199@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9200def test_read_ndtiffstorage():
9201    """Test read NDTiffStorage/MagellanStack."""
9202    # https://github.com/cgohlke/tifffile/issues/23
9203    fname = private_file(
9204        'NDTiffStorage/MagellanStack/Full resolution/democam_MagellanStack.tif'
9205    )
9206    with TiffFile(fname) as tif:
9207        assert tif.is_micromanager
9208        assert len(tif.pages) == 12
9209        # with pytest.warns(UserWarning):
9210        assert 'Comments' not in tif.micromanager_metadata
9211        meta = tif.pages[-1].tags['MicroManagerMetadata'].value
9212        assert meta['Axes']['repetition'] == 2
9213        assert meta['Axes']['exposure'] == 3
9214
9215
9216@pytest.mark.skipif(SKIP_PUBLIC or SKIP_ZARR, reason=REASON)
9217def test_read_zarr():
9218    """Test read TIFF with zarr."""
9219    fname = public_file('imagecodecs/gray.u1.tif')
9220    with TiffFile(fname) as tif:
9221        image = tif.asarray()
9222        store = tif.aszarr()
9223    try:
9224        data = zarr.open(store, mode='r')
9225        assert_array_equal(image, data)
9226        del data
9227    finally:
9228        store.close()
9229
9230
9231@pytest.mark.skipif(SKIP_PUBLIC or SKIP_ZARR, reason=REASON)
9232def test_read_zarr_multifile():
9233    """Test read multifile OME-TIFF with zarr."""
9234    fname = public_file('OME/multifile/multifile-Z1.ome.tiff')
9235    with TiffFile(fname) as tif:
9236        image = tif.asarray()
9237        store = tif.aszarr()
9238    try:
9239        data = zarr.open(store, mode='r')
9240        assert_array_equal(image, data)
9241        del data
9242    finally:
9243        store.close()
9244
9245
9246@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9247def test_read_eer(caplog):
9248    """Test read EER metadata."""
9249    # https://github.com/fei-company/EerReaderLib/issues/1
9250    fname = private_file('EER/Example_1.eer')
9251    with TiffFile(fname) as tif:
9252        assert not caplog.text  # no warning
9253        assert tif.is_bigtiff
9254        assert tif.is_eer
9255        assert tif.byteorder == '<'
9256        assert len(tif.pages) == 238
9257        assert len(tif.series) == 1
9258        # assert page properties
9259        page = tif.pages[0]
9260        assert not page.is_contiguous
9261        assert page.photometric == MINISBLACK
9262        assert page.compression == 65001
9263        assert page.imagewidth == 4096
9264        assert page.imagelength == 4096
9265        assert page.bitspersample == 1
9266        assert page.samplesperpixel == 1
9267        # assert data and metadata
9268        with pytest.raises(ValueError):
9269            page.asarray()
9270        meta = tif.eer_metadata
9271        assert meta.startswith('<metadata>')
9272        assert__str__(tif)
9273
9274
9275###############################################################################
9276
9277# Test TiffWriter
9278
9279WRITE_DATA = numpy.arange(3 * 219 * 301).astype(numpy.uint16)
9280WRITE_DATA.shape = (3, 219, 301)
9281
9282
9283@pytest.mark.skipif(SKIP_EXTENDED, reason=REASON)
9284@pytest.mark.parametrize(
9285    'shape',
9286    [
9287        (219, 301),
9288        (219, 301, 2),
9289        (219, 301, 3),
9290        (219, 301, 4),
9291        (2, 219, 301),
9292        (3, 219, 301),
9293        (4, 219, 301),
9294        (5, 219, 301),
9295        (4, 3, 219, 301),
9296        (4, 219, 301, 3),
9297        (3, 4, 219, 301),
9298        (3, 4, 219, 301, 1),
9299    ],
9300)
9301@pytest.mark.parametrize('dtype', list('?bhiqefdBHIQFD'))
9302@pytest.mark.parametrize('byteorder', ['>', '<'])
9303@pytest.mark.parametrize('bigtiff', ['plaintiff', 'bigtiff'])
9304@pytest.mark.parametrize('tile', [None, (64, 64)])
9305@pytest.mark.parametrize('data', ['random', None])
9306def test_write(data, byteorder, bigtiff, dtype, shape, tile):
9307    """Test TiffWriter with various options."""
9308    # TODO: test compression ?
9309    fname = '{}_{}_{}_{}{}{}'.format(
9310        bigtiff,
9311        {'<': 'le', '>': 'be'}[byteorder],
9312        numpy.dtype(dtype).name,
9313        str(shape).replace(' ', ''),
9314        '_tiled' if tile is not None else '',
9315        '_empty' if data is None else '',
9316    )
9317    bigtiff = bigtiff == 'bigtiff'
9318    if (3 in shape or 4 in shape) and shape[-1] != 1 and dtype != '?':
9319        photometric = 'rgb'
9320    else:
9321        photometric = None
9322
9323    with TempFileName(fname) as fname:
9324        if data is None:
9325            with TiffWriter(
9326                fname, byteorder=byteorder, bigtiff=bigtiff
9327            ) as tif:
9328                if tile is not None or dtype == '?':
9329                    # cannot write non-contiguous empty file
9330                    with pytest.raises(ValueError):
9331                        tif.write(
9332                            shape=shape,
9333                            dtype=dtype,
9334                            tile=tile,
9335                            photometric=photometric,
9336                        )
9337                    return
9338                else:
9339                    tif.write(
9340                        shape=shape,
9341                        dtype=dtype,
9342                        tile=tile,
9343                        photometric=photometric,
9344                    )
9345            with TiffFile(fname) as tif:
9346                assert__str__(tif)
9347                image = tif.asarray()
9348        else:
9349            data = random_data(dtype, shape)
9350            imwrite(
9351                fname,
9352                data,
9353                byteorder=byteorder,
9354                bigtiff=bigtiff,
9355                tile=tile,
9356                photometric=photometric,
9357            )
9358            image = imread(fname)
9359            assert image.flags['C_CONTIGUOUS']
9360            assert_array_equal(data.squeeze(), image.squeeze())
9361            if not SKIP_ZARR:
9362                with imread(fname, aszarr=True) as store:
9363                    data = zarr.open(store, mode='r')
9364                    assert_array_equal(data, image)
9365
9366        assert shape == image.shape
9367        assert dtype == image.dtype
9368        if not bigtiff:
9369            assert_valid_tiff(fname)
9370
9371
9372@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
9373@pytest.mark.parametrize('tile', [False, True])
9374@pytest.mark.parametrize(
9375    'codec',
9376    [
9377        'deflate',
9378        'lzma',
9379        'packbits',
9380        'zstd',  # TODO: 'lzw'
9381        'webp',
9382        'png',
9383        'jpeg',
9384        'jpegxl',
9385        'jpegxr',
9386        'jpeg2000',
9387    ],
9388)
9389@pytest.mark.parametrize('mode', ['gray', 'rgb', 'planar'])
9390def test_write_codecs(mode, tile, codec):
9391    """Test write various compression."""
9392    if mode in ('gray', 'planar') and codec == 'webp':
9393        pytest.xfail("WebP doesn't support grayscale or planar mode")
9394    level = {'webp': -1, 'jpeg': 99}.get(codec, None)
9395    tile = (16, 16) if tile else None
9396    data = numpy.load(public_file('tifffile/rgb.u1.npy'))
9397    if mode == 'rgb':
9398        photometric = RGB
9399        planarconfig = CONTIG
9400    elif mode == 'planar':
9401        photometric = RGB
9402        planarconfig = SEPARATE
9403        data = numpy.moveaxis(data, -1, 0).copy()
9404    else:
9405        planarconfig = None
9406        photometric = MINISBLACK
9407        data = data[..., :1].copy()
9408    data = numpy.repeat(data[numpy.newaxis], 3, axis=0)
9409    data[1] = 255 - data[1]
9410    shape = data.shape
9411    with TempFileName(
9412        'codecs_{}_{}{}'.format(mode, codec, '_tile' if tile else '')
9413    ) as fname:
9414        imwrite(
9415            fname,
9416            data,
9417            compression=(codec, level),
9418            tile=tile,
9419            photometric=photometric,
9420            planarconfig=planarconfig,
9421            subsampling=(1, 1),
9422        )
9423        assert_valid_tiff(fname)
9424        with TiffFile(fname) as tif:
9425            assert len(tif.pages) == shape[0]
9426            page = tif.pages[0]
9427            assert not page.is_contiguous
9428            assert page.compression == enumarg(TIFF.COMPRESSION, codec)
9429            assert page.photometric in (photometric, YCBCR)
9430            if planarconfig is not None:
9431                assert page.planarconfig == planarconfig
9432            assert page.imagewidth == 31
9433            assert page.imagelength == 32
9434            assert page.samplesperpixel == 1 if mode == 'gray' else 3
9435            # samplesperpixel = page.samplesperpixel
9436            image = tif.asarray()
9437            if codec in ('jpeg',):
9438                assert_allclose(data, image, atol=10)
9439            else:
9440                assert_array_equal(data, image)
9441            assert_decode_method(page)
9442            assert__str__(tif)
9443        if (
9444            imagecodecs.TIFF
9445            and codec not in ('png', 'jpegxr', 'jpeg2000', 'jpegxl')
9446            and mode != 'planar'
9447        ):
9448            im = imagecodecs.imread(fname, index=None)
9449            # if codec == 'jpeg':
9450            #     # tiff_decode returns JPEG compressed TIFF as RGBA
9451            #     im = numpy.squeeze(im[..., :samplesperpixel])
9452            assert_array_equal(im, numpy.squeeze(image))
9453
9454
9455@pytest.mark.parametrize('mode', ['gray', 'rgb', 'planar'])
9456@pytest.mark.parametrize('tile', [False, True])
9457@pytest.mark.parametrize(
9458    'dtype', ['u1', 'u2', 'u4', 'i1', 'i2', 'i4', 'f2', 'f4', 'f8']
9459)
9460@pytest.mark.parametrize('byteorder', ['>', '<'])
9461def test_write_predictor(byteorder, dtype, tile, mode):
9462    """Test predictors."""
9463    tile = (32, 32) if tile else None
9464    f4 = imread(public_file('tifffile/gray.f4.tif'))
9465    if mode == 'rgb':
9466        photometric = RGB
9467        planarconfig = CONTIG
9468        data = numpy.empty((83, 111, 3), 'f4')
9469        data[..., 0] = f4
9470        data[..., 1] = f4[::-1]
9471        data[..., 2] = f4[::-1, ::-1]
9472    elif mode == 'planar':
9473        photometric = RGB
9474        planarconfig = SEPARATE
9475        data = numpy.empty((3, 83, 111), 'f4')
9476        data[0] = f4
9477        data[1] = f4[::-1]
9478        data[2] = f4[::-1, ::-1]
9479    else:
9480        planarconfig = None
9481        photometric = MINISBLACK
9482        data = f4
9483
9484    if dtype[0] in 'if':
9485        data -= 0.5
9486    if dtype in 'u1i1':
9487        data *= 255
9488    elif dtype in 'i2u2':
9489        data *= 2 ** 12
9490    elif dtype in 'i4u4':
9491        data *= 2 ** 21
9492    else:
9493        data *= 3.145
9494    data = data.astype(byteorder + dtype)
9495
9496    with TempFileName(
9497        'predictor_{}_{}_{}{}'.format(
9498            dtype,
9499            'be' if byteorder == '>' else 'le',
9500            mode,
9501            '_tile' if tile else '',
9502        )
9503    ) as fname:
9504        imwrite(
9505            fname,
9506            data,
9507            predictor=True,
9508            compression=ADOBE_DEFLATE,
9509            tile=tile,
9510            photometric=photometric,
9511            planarconfig=planarconfig,
9512            byteorder=byteorder,
9513        )
9514        assert_valid_tiff(fname)
9515
9516        with TiffFile(fname) as tif:
9517            assert tif.tiff.byteorder == byteorder
9518            assert len(tif.pages) == 1
9519            page = tif.pages[0]
9520            assert not page.is_contiguous
9521            assert page.compression == ADOBE_DEFLATE
9522            assert page.predictor == (3 if dtype[0] == 'f' else 2)
9523            assert page.photometric == photometric
9524            if planarconfig is not None:
9525                assert page.planarconfig == planarconfig
9526            assert page.imagewidth == 111
9527            assert page.imagelength == 83
9528            assert page.samplesperpixel == 1 if mode == 'gray' else 3
9529            # samplesperpixel = page.samplesperpixel
9530            image = tif.asarray()
9531            assert_array_equal(data, image)
9532            assert_decode_method(page)
9533            assert__str__(tif)
9534
9535        if imagecodecs.TIFF:
9536            im = imagecodecs.imread(fname, index=None)
9537            assert_array_equal(im, numpy.squeeze(image))
9538
9539
9540@pytest.mark.parametrize('bytecount', [16, 256])
9541@pytest.mark.parametrize('count', [1, 2, 4])
9542@pytest.mark.parametrize('compression', [0, 6])
9543@pytest.mark.parametrize('tiled', [0, 1])
9544@pytest.mark.parametrize('bigtiff', [0, 1])
9545def test_write_bytecount(bigtiff, tiled, compression, count, bytecount):
9546    """Test write bytecount formats."""
9547    if tiled:
9548        tag = 'TileByteCounts'
9549        rowsperstrip = None
9550        tile = (bytecount, bytecount)
9551        shape = {
9552            1: (bytecount, bytecount),
9553            2: (bytecount * 2, bytecount),
9554            4: (bytecount * 2, bytecount * 2),
9555        }[count]
9556    else:
9557        tag = 'StripByteCounts'
9558        tile = None
9559        rowsperstrip = bytecount
9560        shape = (bytecount * count, bytecount)
9561    data = random_data(numpy.uint8, shape)
9562
9563    if count == 1:
9564        dtype = TIFF.DATATYPES.LONG8 if bigtiff else TIFF.DATATYPES.LONG
9565    elif bytecount == 256:
9566        dtype = TIFF.DATATYPES.LONG
9567    else:
9568        dtype = TIFF.DATATYPES.SHORT
9569
9570    with TempFileName(
9571        'bytecounts_{}{}{}{}{}'.format(
9572            bigtiff, tiled, compression, count, bytecount
9573        )
9574    ) as fname:
9575        imwrite(
9576            fname,
9577            data,
9578            bigtiff=bigtiff,
9579            tile=tile,
9580            compression=(ADOBE_DEFLATE, compression)
9581            if compression
9582            else compression,
9583            rowsperstrip=rowsperstrip,
9584        )
9585        if not bigtiff:
9586            assert_valid_tiff(fname)
9587        with TiffFile(fname) as tif:
9588            assert len(tif.pages) == 1
9589            page = tif.pages[0]
9590            assert page.tags[tag].count == count
9591            assert page.tags[tag].dtype == dtype
9592            assert page.is_contiguous != bool(compression)
9593            assert page.planarconfig == CONTIG
9594            assert page.photometric == MINISBLACK
9595            assert page.imagewidth == shape[1]
9596            assert page.imagelength == shape[0]
9597            assert page.samplesperpixel == 1
9598            assert_array_equal(page.asarray(), data)
9599            assert_aszarr_method(page, data)
9600            assert__str__(tif)
9601
9602
9603@pytest.mark.skipif(SKIP_EXTENDED, reason=REASON)
9604@pytest.mark.parametrize('repeat', [1, 4])
9605@pytest.mark.parametrize('shape', [(1, 0), (0, 1), (3, 0, 2, 1)])
9606@pytest.mark.parametrize('data', ['random', 'empty'])
9607@pytest.mark.parametrize('shaped', [True, False])
9608def test_write_zeroshape(shaped, data, repeat, shape):
9609    """Test write arrays with zero shape."""
9610    dtype = numpy.uint8
9611    fname = 'shape_{}x{}{}{}'.format(
9612        repeat,
9613        str(shape).replace(' ', ''),
9614        '_shaped' if shaped else '',
9615        '_empty' if data == 'empty' else '',
9616    )
9617    metadata = {} if shaped else None
9618
9619    with TempFileName(fname) as fname:
9620        if data == 'empty':
9621            with TiffWriter(fname) as tif:
9622                with pytest.warns(UserWarning):
9623                    for _ in range(repeat):
9624                        tif.write(
9625                            shape=shape,
9626                            dtype=dtype,
9627                            contiguous=True,
9628                            metadata=metadata,
9629                        )
9630                    tif.write(numpy.zeros((16, 16), 'u2'), metadata=metadata)
9631            with TiffFile(fname) as tif:
9632                assert__str__(tif)
9633                image = zimage = tif.asarray()
9634                if not SKIP_ZARR:
9635                    zimage = zarr.open(tif.aszarr(), mode='r')
9636        else:
9637            data = random_data(dtype, shape)
9638            with TiffWriter(fname) as tif:
9639                with pytest.warns(UserWarning):
9640                    for _ in range(repeat):
9641                        tif.write(data, contiguous=True, metadata=metadata)
9642                    tif.write(numpy.zeros((16, 16), 'u2'), metadata=metadata)
9643            with TiffFile(fname) as tif:
9644                assert__str__(tif)
9645                image = zimage = tif.asarray()
9646                if not SKIP_ZARR:
9647                    zimage = zarr.open(tif.aszarr(), mode='r')
9648
9649            assert image.flags['C_CONTIGUOUS']
9650            if shaped:
9651                if repeat > 1:
9652                    for i in range(repeat):
9653                        assert_array_equal(image[i], data)
9654                        assert_array_equal(zimage[i], data)
9655                else:
9656                    assert_array_equal(image, data)
9657                    assert_array_equal(zimage, data)
9658            else:
9659                empty = numpy.empty((0, 0), dtype)
9660                if repeat > 1:
9661                    for i in range(repeat):
9662                        assert_array_equal(image[i], empty)
9663                        assert_array_equal(zimage[i], empty)
9664                else:
9665                    assert_array_equal(image.squeeze(), empty)
9666                    # assert_array_equal(zimage.squeeze(), empty)
9667
9668        if repeat > 1:
9669            assert image.shape[0] == repeat
9670            assert zimage.shape[0] == repeat
9671        elif shaped:
9672            assert shape == image.shape
9673            assert shape == zimage.shape
9674        else:
9675            assert image.shape == (0, 0)
9676            assert zimage.shape == (0, 0)
9677        assert dtype == image.dtype
9678        assert dtype == zimage.dtype
9679
9680
9681@pytest.mark.parametrize('repeats', [1, 2])
9682@pytest.mark.parametrize('series', [1, 2])
9683@pytest.mark.parametrize('subifds', [0, 1, 2])
9684@pytest.mark.parametrize('compressed', [False, True])
9685@pytest.mark.parametrize('tiled', [False, True])
9686@pytest.mark.parametrize('ome', [False, True])
9687def test_write_subidfs(ome, tiled, compressed, series, repeats, subifds):
9688    """Test writing SubIFDs."""
9689    if repeats > 1 and (compressed or tiled or ome):
9690        pytest.xfail('contiguous not working with compression, tiles, ome')
9691
9692    data = [
9693        (numpy.random.rand(5, 64, 64) * 1023).astype(numpy.uint16),
9694        (numpy.random.rand(5, 32, 32) * 1023).astype(numpy.uint16),
9695        (numpy.random.rand(5, 16, 16) * 1023).astype(numpy.uint16),
9696    ]
9697
9698    kwargs = {
9699        'tile': (16, 16) if tiled else None,
9700        'compression': (ADOBE_DEFLATE, 6) if compressed else None,
9701    }
9702
9703    with TempFileName(
9704        'write_subidfs_'
9705        f'{ome}-{tiled}-{compressed}-{subifds}-{series}-{repeats}'
9706    ) as fname:
9707        with TiffWriter(fname, ome=ome) as tif:
9708            for _ in range(series):
9709                for r in range(repeats):
9710                    kwargs['contiguous'] = r != 0
9711                    tif.write(data[0], subifds=subifds, **kwargs)
9712                for i in range(1, subifds + 1):
9713                    for r in range(repeats):
9714                        kwargs['contiguous'] = r != 0
9715                        tif.write(data[i], subfiletype=1, **kwargs)
9716
9717        with TiffFile(fname) as tif:
9718            for i, page in enumerate(tif.pages):
9719                if i % (5 * repeats):
9720                    assert page.description == ''
9721                elif ome:
9722                    if i == 0:
9723                        assert page.is_ome
9724                    else:
9725                        assert page.description == ''
9726                else:
9727                    assert page.is_shaped
9728
9729                assert_array_equal(page.asarray(), data[0][i % 5])
9730                assert_aszarr_method(page, data[0][i % 5])
9731                assert len(page.pages) == subifds
9732
9733                for j, subifd in enumerate(page.pages):
9734                    assert_array_equal(subifd.asarray(), data[j + 1][i % 5])
9735                    assert_aszarr_method(subifd, data[j + 1][i % 5])
9736
9737            for i, page in enumerate(tif.pages[:-1]):
9738                assert page._nextifd() == tif.pages[i + 1].offset
9739
9740                if subifds:
9741                    for j, subifd in enumerate(page.pages[:-1]):
9742                        assert subifd.subfiletype == 1
9743                        assert subifd._nextifd() == page.subifds[j + 1]
9744
9745                    assert page.pages[-1]._nextifd() == 0
9746
9747            assert len(tif.series) == series
9748
9749            if repeats > 1:
9750                for s in range(series):
9751                    assert tif.series[s].kind == 'OME' if ome else 'Shaped'
9752                    assert_array_equal(tif.series[s].asarray()[0], data[0])
9753                    for i in range(subifds):
9754                        assert_array_equal(
9755                            tif.series[s].levels[i + 1].asarray()[0],
9756                            data[i + 1],
9757                        )
9758            else:
9759                for s in range(series):
9760                    assert tif.series[s].kind == 'OME' if ome else 'Shaped'
9761                    assert_array_equal(tif.series[s].asarray(), data[0])
9762                    for i in range(subifds):
9763                        assert_array_equal(
9764                            tif.series[s].levels[i + 1].asarray(), data[i + 1]
9765                        )
9766
9767
9768def test_write_lists():
9769    """Test write lists."""
9770    array = numpy.arange(1000).reshape(10, 10, 10).astype(numpy.uint16)
9771    data = array.tolist()
9772    with TempFileName('write_lists') as fname:
9773        with TiffWriter(fname) as tif:
9774            tif.write(data, dtype=numpy.uint16)
9775            tif.write(data, compression=ADOBE_DEFLATE)
9776            tif.write([100.0])
9777            with pytest.warns(UserWarning):
9778                tif.write([])
9779        with TiffFile(fname) as tif:
9780            assert_array_equal(tif.series[0].asarray(), array)
9781            assert_array_equal(tif.series[1].asarray(), array)
9782            assert_array_equal(tif.series[2].asarray(), [100.0])
9783            assert_array_equal(tif.series[3].asarray(), [])
9784            assert_aszarr_method(tif.series[0], array)
9785            assert_aszarr_method(tif.series[1], array)
9786            assert_aszarr_method(tif.series[2], [100.0])
9787            # assert_aszarr_method(tif.series[3], [])
9788
9789
9790def test_write_nopages():
9791    """Test write TIFF with no pages."""
9792    with TempFileName('nopages') as fname:
9793        with TiffWriter(fname) as tif:
9794            pass
9795        with TiffFile(fname) as tif:
9796            assert len(tif.pages) == 0
9797            tif.asarray()
9798        if not SKIP_VALIDATE:
9799            with pytest.raises(ValueError):
9800                assert_valid_tiff(fname)
9801
9802
9803def test_write_append_not_exists():
9804    """Test append to non existing file."""
9805    with TempFileName('append_not_exists.bin') as fname:
9806        # with self.assertRaises(ValueError):
9807        with TiffWriter(fname, append=True):
9808            pass
9809
9810
9811def test_write_append_nontif():
9812    """Test fail to append to non-TIFF file."""
9813    with TempFileName('append_nontif.bin') as fname:
9814        with open(fname, 'wb') as fh:
9815            fh.write(b'not a TIFF file')
9816        with pytest.raises(TiffFileError):
9817            with TiffWriter(fname, append=True):
9818                pass
9819
9820
9821@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
9822def test_write_append_lsm():
9823    """Test fail to append to LSM file."""
9824    fname = private_file('lsm/take1.lsm')
9825    with pytest.raises(ValueError):
9826        with TiffWriter(fname, append=True):
9827            pass
9828
9829
9830def test_write_append_imwrite():
9831    """Test append using imwrite."""
9832    data = random_data(numpy.uint8, (21, 31))
9833    with TempFileName('imwrite_append') as fname:
9834        imwrite(fname, data, metadata=None)
9835        for _ in range(3):
9836            imwrite(fname, data, append=True, metadata=None)
9837        a = imread(fname)
9838        assert a.shape == (4, 21, 31)
9839        assert_array_equal(a[3], data)
9840
9841
9842def test_write_append():
9843    """Test append to existing TIFF file."""
9844    data = random_data(numpy.uint8, (21, 31))
9845    with TempFileName('append') as fname:
9846        with TiffWriter(fname) as tif:
9847            pass
9848        with TiffFile(fname) as tif:
9849            assert len(tif.pages) == 0
9850            assert__str__(tif)
9851
9852        with TiffWriter(fname, append=True) as tif:
9853            tif.write(data)
9854        with TiffFile(fname) as tif:
9855            assert len(tif.series) == 1
9856            assert len(tif.pages) == 1
9857            page = tif.pages[0]
9858            assert page.imagewidth == 31
9859            assert page.imagelength == 21
9860            assert__str__(tif)
9861
9862        with TiffWriter(fname, append=True) as tif:
9863            tif.write(data)
9864            tif.write(data, contiguous=True)
9865        with TiffFile(fname) as tif:
9866            assert len(tif.series) == 2
9867            assert len(tif.pages) == 3
9868            page = tif.pages[0]
9869            assert page.imagewidth == 31
9870            assert page.imagelength == 21
9871            assert_array_equal(tif.asarray(series=1)[1], data)
9872            assert__str__(tif)
9873
9874        assert_valid_tiff(fname)
9875
9876
9877def test_write_append_bytesio():
9878    """Test append to existing TIFF file in BytesIO."""
9879    data = random_data(numpy.uint8, (21, 31))
9880    offset = 11
9881    file = BytesIO()
9882    file.write(b'a' * offset)
9883
9884    with TiffWriter(file) as tif:
9885        pass
9886    file.seek(offset)
9887    with TiffFile(file) as tif:
9888        assert len(tif.pages) == 0
9889
9890    file.seek(offset)
9891    with TiffWriter(file, append=True) as tif:
9892        tif.write(data)
9893    file.seek(offset)
9894    with TiffFile(file) as tif:
9895        assert len(tif.series) == 1
9896        assert len(tif.pages) == 1
9897        page = tif.pages[0]
9898        assert page.imagewidth == 31
9899        assert page.imagelength == 21
9900        assert__str__(tif)
9901
9902    file.seek(offset)
9903    with TiffWriter(file, append=True) as tif:
9904        tif.write(data)
9905        tif.write(data, contiguous=True)
9906    file.seek(offset)
9907    with TiffFile(file) as tif:
9908        assert len(tif.series) == 2
9909        assert len(tif.pages) == 3
9910        page = tif.pages[0]
9911        assert page.imagewidth == 31
9912        assert page.imagelength == 21
9913        assert_array_equal(tif.asarray(series=1)[1], data)
9914        assert__str__(tif)
9915
9916
9917@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
9918def test_write_roundtrip_filename():
9919    """Test write and read using file name."""
9920    data = imread(public_file('tifffile/generic_series.tif'))
9921    with TempFileName('roundtrip_filename') as fname:
9922        imwrite(fname, data, photometric=RGB)
9923        assert_array_equal(imread(fname), data)
9924
9925
9926@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
9927def test_write_roundtrip_openfile():
9928    """Test write and read using open file."""
9929    pad = b'0' * 7
9930    data = imread(public_file('tifffile/generic_series.tif'))
9931    with TempFileName('roundtrip_openfile') as fname:
9932        with open(fname, 'wb') as fh:
9933            fh.write(pad)
9934            imwrite(fh, data, photometric=RGB)
9935            fh.write(pad)
9936        with open(fname, 'rb') as fh:
9937            fh.seek(len(pad))
9938            assert_array_equal(imread(fh), data)
9939
9940
9941@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
9942def test_write_roundtrip_bytesio():
9943    """Test write and read using BytesIO."""
9944    pad = b'0' * 7
9945    data = imread(public_file('tifffile/generic_series.tif'))
9946    buf = BytesIO()
9947    buf.write(pad)
9948    imwrite(buf, data, photometric=RGB)
9949    buf.write(pad)
9950    buf.seek(len(pad))
9951    assert_array_equal(imread(buf), data)
9952
9953
9954def test_write_pages():
9955    """Test write tags for contiguous data in all pages."""
9956    data = random_data(numpy.float32, (17, 219, 301))
9957    with TempFileName('pages') as fname:
9958        imwrite(fname, data, photometric=MINISBLACK)
9959        assert_valid_tiff(fname)
9960        # assert file
9961        with TiffFile(fname) as tif:
9962            assert len(tif.pages) == 17
9963            for i, page in enumerate(tif.pages):
9964                assert page.is_contiguous
9965                assert page.planarconfig == CONTIG
9966                assert page.photometric == MINISBLACK
9967                assert page.imagewidth == 301
9968                assert page.imagelength == 219
9969                assert page.samplesperpixel == 1
9970                image = page.asarray()
9971                assert_array_equal(data[i], image)
9972            # assert series
9973            series = tif.series[0]
9974            assert series.offset is not None
9975            image = series.asarray()
9976            assert_array_equal(data, image)
9977            assert__str__(tif)
9978
9979
9980def test_write_truncate():
9981    """Test only one page is written for truncated files."""
9982    shape = (4, 5, 6, 1)
9983    with TempFileName('truncate') as fname:
9984        imwrite(fname, random_data(numpy.uint8, shape), truncate=True)
9985        assert_valid_tiff(fname)
9986        with TiffFile(fname) as tif:
9987            assert len(tif.pages) == 1  # not 4
9988            page = tif.pages[0]
9989            assert page.is_shaped
9990            assert page.shape == (5, 6)
9991            assert '"shape": [4, 5, 6, 1]' in page.description
9992            assert '"truncated": true' in page.description
9993            series = tif.series[0]
9994            assert series.shape == shape
9995            assert len(series._pages) == 1
9996            assert len(series.pages) == 1
9997            data = tif.asarray()
9998            assert data.shape == shape
9999            assert_aszarr_method(tif, data)
10000            assert_aszarr_method(tif, data, chunkmode='page')
10001            assert__str__(tif)
10002
10003
10004def test_write_is_shaped():
10005    """Test files are written with shape."""
10006    with TempFileName('is_shaped') as fname:
10007        imwrite(fname, random_data(numpy.uint8, (4, 5, 6, 3)), photometric=RGB)
10008        assert_valid_tiff(fname)
10009        with TiffFile(fname) as tif:
10010            assert len(tif.pages) == 4
10011            page = tif.pages[0]
10012            assert page.is_shaped
10013            assert page.description == '{"shape": [4, 5, 6, 3]}'
10014            assert__str__(tif)
10015    with TempFileName('is_shaped_with_description') as fname:
10016        descr = 'test is_shaped_with_description'
10017        imwrite(
10018            fname,
10019            random_data(numpy.uint8, (5, 6, 3)),
10020            photometric=RGB,
10021            description=descr,
10022        )
10023        assert_valid_tiff(fname)
10024        with TiffFile(fname) as tif:
10025            assert len(tif.pages) == 1
10026            page = tif.pages[0]
10027            assert page.is_shaped
10028            assert page.description == descr
10029            assert_aszarr_method(page)
10030            assert_aszarr_method(page, chunkmode='page')
10031            assert__str__(tif)
10032
10033
10034def test_write_bytes_str():
10035    """Test write bytes in place of 7-bit ascii string."""
10036    micron = 'micron \xB5'.encode('latin-1')  # can't be encoded as 7-bit ascii
10037    data = numpy.arange(4, dtype=numpy.uint32).reshape((2, 2))
10038    with TempFileName('write_bytes_str') as fname:
10039        imwrite(
10040            fname,
10041            data,
10042            description=micron,
10043            software=micron,
10044            extratags=[(50001, 's', 8, micron, True)],
10045        )
10046        with TiffFile(fname) as tif:
10047            page = tif.pages[0]
10048            assert page.description == 'micron \xB5'
10049            assert page.software == 'micron \xB5'
10050            assert page.tags[50001].value == 'micron \xB5'
10051
10052
10053def test_write_extratags():
10054    """Test write extratags."""
10055    data = random_data(numpy.uint8, (2, 219, 301))
10056    description = 'Created by TestTiffWriter\nLorem ipsum dolor...'
10057    pagename = 'Page name'
10058    extratags = [
10059        (270, 's', 0, description, True),
10060        ('PageName', 's', 0, pagename, False),
10061        (50001, 'b', 1, b'1', True),
10062        (50002, 'b', 2, b'12', True),
10063        (50004, 'b', 4, b'1234', True),
10064        (50008, 'B', 8, b'12345678', True),
10065    ]
10066    with TempFileName('extratags') as fname:
10067        imwrite(fname, data, extratags=extratags)
10068        assert_valid_tiff(fname)
10069        with TiffFile(fname) as tif:
10070            assert len(tif.pages) == 2
10071            assert tif.pages[0].description1 == description
10072            assert 'ImageDescription' not in tif.pages[1].tags
10073            assert tif.pages[0].tags['PageName'].value == pagename
10074            assert tif.pages[1].tags['PageName'].value == pagename
10075            assert '50001' not in tif.pages[1].tags
10076            tags = tif.pages[0].tags
10077            assert tags['50001'].value == 49
10078            assert tags['50002'].value == (49, 50)
10079            assert tags['50004'].value == (49, 50, 51, 52)
10080            assert_array_equal(tags['50008'].value, b'12345678')
10081            #                   (49, 50, 51, 52, 53, 54, 55, 56))
10082            assert__str__(tif)
10083
10084
10085def test_write_double_tags():
10086    """Test write single and sequences of doubles."""
10087    # older versions of tifffile do not use offset to write doubles
10088    # reported by Eric Prestat on Feb 21, 2016
10089    data = random_data(numpy.uint8, (8, 8))
10090    value = math.pi
10091    extratags = [
10092        (34563, 'd', 1, value, False),
10093        (34564, 'd', 1, (value,), False),
10094        (34565, 'd', 2, (value, value), False),
10095        (34566, 'd', 2, [value, value], False),
10096        (34567, 'd', 2, numpy.array((value, value)), False),
10097    ]
10098    with TempFileName('double_tags') as fname:
10099        imwrite(fname, data, extratags=extratags)
10100        assert_valid_tiff(fname)
10101        with TiffFile(fname) as tif:
10102            assert len(tif.pages) == 1
10103            tags = tif.pages[0].tags
10104            assert tags['34563'].value == value
10105            assert tags['34564'].value == value
10106            assert tuple(tags['34565'].value) == (value, value)
10107            assert tuple(tags['34566'].value) == (value, value)
10108            assert tuple(tags['34567'].value) == (value, value)
10109            assert__str__(tif)
10110
10111    with TempFileName('double_tags_bigtiff') as fname:
10112        imwrite(fname, data, bigtiff=True, extratags=extratags)
10113        # assert_jhove(fname)
10114        with TiffFile(fname) as tif:
10115            assert len(tif.pages) == 1
10116            tags = tif.pages[0].tags
10117            assert tags['34563'].value == value
10118            assert tags['34564'].value == value
10119            assert tuple(tags['34565'].value) == (value, value)
10120            assert tuple(tags['34566'].value) == (value, value)
10121            assert tuple(tags['34567'].value) == (value, value)
10122            assert__str__(tif)
10123
10124
10125def test_write_short_tags():
10126    """Test write single and sequences of words."""
10127    data = random_data(numpy.uint8, (8, 8))
10128    value = 65531
10129    extratags = [
10130        (34564, 'H', 1, (value,) * 1, False),
10131        (34565, 'H', 2, (value,) * 2, False),
10132        (34566, 'H', 3, (value,) * 3, False),
10133        (34567, 'H', 4, (value,) * 4, False),
10134    ]
10135    with TempFileName('short_tags') as fname:
10136        imwrite(fname, data, extratags=extratags)
10137        assert_valid_tiff(fname)
10138        with TiffFile(fname) as tif:
10139            assert len(tif.pages) == 1
10140            tags = tif.pages[0].tags
10141            assert tags['34564'].value == value
10142            assert tuple(tags['34565'].value) == (value,) * 2
10143            assert tuple(tags['34566'].value) == (value,) * 3
10144            assert tuple(tags['34567'].value) == (value,) * 4
10145            assert__str__(tif)
10146
10147
10148@pytest.mark.parametrize('subfiletype', [0b1, 0b10, 0b100, 0b1000, 0b1111])
10149def test_write_subfiletype(subfiletype):
10150    """Test write subfiletype."""
10151    data = random_data(numpy.uint8, (16, 16))
10152    if subfiletype & 0b100:
10153        data = data.astype('bool')
10154    with TempFileName(f'subfiletype_{subfiletype}') as fname:
10155        imwrite(fname, data, subfiletype=subfiletype)
10156        assert_valid_tiff(fname)
10157        with TiffFile(fname) as tif:
10158            page = tif.pages[0]
10159            assert page.subfiletype == subfiletype
10160            assert page.is_reduced == subfiletype & 0b1
10161            assert page.is_multipage == subfiletype & 0b10
10162            assert page.is_mask == subfiletype & 0b100
10163            assert page.is_mrc == subfiletype & 0b1000
10164            assert_array_equal(data, page.asarray())
10165            assert__str__(tif)
10166
10167
10168@pytest.mark.parametrize('dt', [None, True, datetime, '2019:01:30 04:05:37'])
10169def test_write_datetime_tag(dt):
10170    """Test write datetime tag."""
10171    arg = dt
10172    if dt is datetime:
10173        arg = datetime.datetime.now()
10174    data = random_data(numpy.uint8, (31, 32))
10175    with TempFileName('datetime') as fname:
10176        imwrite(fname, data, datetime=arg)
10177        with TiffFile(fname) as tif:
10178            if dt is None:
10179                assert 'DateTime' not in tif.pages[0].tags
10180            elif dt is True:
10181                assert (
10182                    tif.pages[0]
10183                    .tags['DateTime']
10184                    .value.startswith(
10185                        datetime.datetime.now().strftime('%Y:%m:%d %H:')
10186                    )
10187                )
10188            elif dt is datetime:
10189                assert tif.pages[0].tags['DateTime'].value == arg.strftime(
10190                    '%Y:%m:%d %H:%M:%S'
10191                )
10192            else:
10193                assert tif.pages[0].tags['DateTime'].value == dt
10194            assert__str__(tif)
10195
10196
10197def test_write_description_tag():
10198    """Test write two description tags."""
10199    data = random_data(numpy.uint8, (2, 219, 301))
10200    description = 'Created by TestTiffWriter\nLorem ipsum dolor...'
10201    with TempFileName('description_tag') as fname:
10202        imwrite(fname, data, description=description)
10203        assert_valid_tiff(fname)
10204        with TiffFile(fname) as tif:
10205            assert len(tif.pages) == 2
10206            assert tif.pages[0].description == description
10207            assert tif.pages[0].description1 == '{"shape": [2, 219, 301]}'
10208            assert 'ImageDescription' not in tif.pages[1].tags
10209            assert__str__(tif)
10210
10211
10212def test_write_description_tag_nojson():
10213    """Test no JSON description is written with metatata=None."""
10214    data = random_data(numpy.uint8, (2, 219, 301))
10215    description = 'Created by TestTiffWriter\nLorem ipsum dolor...'
10216    with TempFileName('description_tag_nojson') as fname:
10217        imwrite(fname, data, description=description, metadata=None)
10218        assert_valid_tiff(fname)
10219        with TiffFile(fname) as tif:
10220            assert len(tif.pages) == 2
10221            assert tif.pages[0].description == description
10222            assert 'ImageDescription' not in tif.pages[1].tags
10223            assert 'ImageDescription1' not in tif.pages[0].tags
10224            assert__str__(tif)
10225
10226
10227def test_write_software_tag():
10228    """Test write Software tag."""
10229    data = random_data(numpy.uint8, (2, 219, 301))
10230    software = 'test_tifffile.py'
10231    with TempFileName('software_tag') as fname:
10232        imwrite(fname, data, software=software)
10233        assert_valid_tiff(fname)
10234        with TiffFile(fname) as tif:
10235            assert len(tif.pages) == 2
10236            assert tif.pages[0].software == software
10237            assert 'Software' not in tif.pages[1].tags
10238            assert__str__(tif)
10239
10240
10241def test_write_resolution_float():
10242    """Test write float Resolution tag."""
10243    data = random_data(numpy.uint8, (2, 219, 301))
10244    resolution = (92.0, 92.0)
10245    with TempFileName('resolution_float') as fname:
10246        imwrite(fname, data, resolution=resolution)
10247        assert_valid_tiff(fname)
10248        with TiffFile(fname) as tif:
10249            assert len(tif.pages) == 2
10250            assert tif.pages[0].tags['XResolution'].value == (92, 1)
10251            assert tif.pages[0].tags['YResolution'].value == (92, 1)
10252            assert tif.pages[1].tags['XResolution'].value == (92, 1)
10253            assert tif.pages[1].tags['YResolution'].value == (92, 1)
10254            assert__str__(tif)
10255
10256
10257def test_write_resolution_rational():
10258    """Test write rational Resolution tag."""
10259    data = random_data(numpy.uint8, (1, 219, 301))
10260    resolution = ((300, 1), (300, 1))
10261    with TempFileName('resolution_rational') as fname:
10262        imwrite(fname, data, resolution=resolution)
10263        assert_valid_tiff(fname)
10264        with TiffFile(fname) as tif:
10265            assert len(tif.pages) == 1
10266            assert tif.pages[0].tags['XResolution'].value == (300, 1)
10267            assert tif.pages[0].tags['YResolution'].value == (300, 1)
10268
10269
10270def test_write_resolution_unit():
10271    """Test write Resolution tag unit."""
10272    data = random_data(numpy.uint8, (219, 301))
10273    resolution = (92.0, (9200, 100), None)
10274    with TempFileName('resolution_unit') as fname:
10275        imwrite(fname, data, resolution=resolution)
10276        assert_valid_tiff(fname)
10277        with TiffFile(fname) as tif:
10278            assert len(tif.pages) == 1
10279            assert tif.pages[0].tags['XResolution'].value == (92, 1)
10280            assert tif.pages[0].tags['YResolution'].value == (92, 1)
10281            assert tif.pages[0].tags['ResolutionUnit'].value == 1
10282            assert__str__(tif)
10283
10284
10285@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
10286@pytest.mark.parametrize('bps', [1, 2, 7, 8])
10287@pytest.mark.parametrize('dtype', [numpy.uint8, numpy.uint16, numpy.uint32])
10288def test_write_bitspersample(bps, dtype):
10289    """Test write with packints."""
10290    dtype = numpy.dtype(dtype)
10291    bps += (dtype.itemsize // 2) * 8
10292    data = numpy.arange(256 * 256 * 3, dtype=dtype).reshape((256, 256, 3))
10293    with TempFileName(f'write_bitspersample_{dtype.char}{bps}') as fname:
10294        # TODO: enable all cases once imagecodecs.packints_encode works
10295        if bps == dtype.itemsize * 8:
10296            imwrite(fname, data, bitspersample=bps, photometric=RGB)
10297            assert_array_equal(imread(fname), data)
10298        else:
10299            with pytest.raises(NotImplementedError):
10300                imwrite(fname, data, bitspersample=bps, photometric=RGB)
10301                assert_array_equal(imread(fname), data)
10302
10303
10304def test_write_bitspersample_fail():
10305    """Test write with packints fails."""
10306    data = numpy.arange(32 * 32 * 3, dtype=numpy.uint32).reshape((32, 32, 3))
10307    with TempFileName('write_bitspersample_fail') as fname:
10308        with TiffWriter(fname) as tif:
10309            # not working with compression
10310            with pytest.raises(ValueError):
10311                tif.write(
10312                    data.astype(numpy.uint8),
10313                    bitspersample=4,
10314                    compression=ADOBE_DEFLATE,
10315                    photometric=RGB,
10316                )
10317            # dtype.itemsize != bitspersample
10318            for dtype in (
10319                numpy.int8,
10320                numpy.int16,
10321                numpy.float32,
10322                numpy.uint64,
10323            ):
10324                with pytest.raises(ValueError):
10325                    tif.write(
10326                        data.astype(dtype), bitspersample=4, photometric=RGB
10327                    )
10328            # bitspersample out of data range
10329            for bps in (0, 9, 16, 32):
10330                with pytest.raises(ValueError):
10331                    tif.write(
10332                        data.astype(numpy.uint8),
10333                        bitspersample=bps,
10334                        photometric=RGB,
10335                    )
10336            for bps in (1, 8, 17, 32):
10337                with pytest.raises(ValueError):
10338                    tif.write(
10339                        data.astype(numpy.uint16),
10340                        bitspersample=bps,
10341                        photometric=RGB,
10342                    )
10343            for bps in (1, 8, 16, 33, 64):
10344                with pytest.raises(ValueError):
10345                    tif.write(
10346                        data.astype(numpy.uint32),
10347                        bitspersample=bps,
10348                        photometric=RGB,
10349                    )
10350
10351
10352@pytest.mark.parametrize('kind', ['enum', 'int', 'lower', 'upper'])
10353def test_write_enum_parameters(kind):
10354    """Test imwrite using different kind of enum"""
10355    data = random_data(numpy.uint8, (2, 6, 219, 301))
10356    with TempFileName(f'enum_parameters_{kind}') as fname:
10357        if kind == 'enum':
10358            imwrite(
10359                fname,
10360                data,
10361                photometric=RGB,
10362                planarconfig=SEPARATE,
10363                extrasamples=(ASSOCALPHA, UNSPECIFIED, UNASSALPHA),
10364                compression=ADOBE_DEFLATE,
10365                predictor=HORIZONTAL,
10366            )
10367        elif kind == 'int':
10368            imwrite(
10369                fname,
10370                data,
10371                photometric=2,
10372                planarconfig=2,
10373                extrasamples=(1, 0, 2),
10374                compression=8,
10375                predictor=2,
10376            )
10377        elif kind == 'upper':
10378            imwrite(
10379                fname,
10380                data,
10381                photometric='RGB',
10382                planarconfig='SEPARATE',
10383                extrasamples=('ASSOCALPHA', 'UNSPECIFIED', 'UNASSALPHA'),
10384                compression='ADOBE_DEFLATE',
10385                predictor='HORIZONTAL',
10386            )
10387        elif kind == 'lower':
10388            imwrite(
10389                fname,
10390                data,
10391                photometric='rgb',
10392                planarconfig='separate',
10393                extrasamples=('assocalpha', 'unspecified', 'unassalpha'),
10394                compression='adobe_deflate',
10395                predictor='horizontal',
10396            )
10397        with TiffFile(fname) as tif:
10398            assert len(tif.pages) == 2
10399            page = tif.pages[0]
10400            assert page.imagewidth == 301
10401            assert page.imagelength == 219
10402            assert page.samplesperpixel == 6
10403            assert page.photometric == RGB
10404            assert page.planarconfig == SEPARATE
10405            assert page.extrasamples == (ASSOCALPHA, UNSPECIFIED, UNASSALPHA)
10406            assert page.compression == ADOBE_DEFLATE
10407            assert page.predictor == HORIZONTAL
10408            image = tif.asarray()
10409            assert_array_equal(data, image)
10410            assert_aszarr_method(tif, image)
10411            assert__str__(tif)
10412
10413
10414@pytest.mark.parametrize(
10415    'args',
10416    [
10417        (0, 0),
10418        (1, 1),
10419        (2, NONE),
10420        (3, ADOBE_DEFLATE),
10421        (4, 'zlib'),
10422        (5, 'zlib', 5),
10423        (6, 'zlib', 5, {'out': None}),
10424        (7, 'zlib', None, {'level': 5}),
10425    ],
10426)
10427def test_write_compression_args(args):
10428    """Test compression parameter."""
10429    i = args[0]
10430    compressionargs = args[1:]
10431    compressed = compressionargs[0] not in (0, 1, NONE)
10432    if len(compressionargs) == 1:
10433        compressionargs = compressionargs[0]
10434
10435    data = WRITE_DATA
10436    with TempFileName(f'compression_args_{i}') as fname:
10437        imwrite(fname, data, compression=compressionargs, photometric=RGB)
10438        assert_valid_tiff(fname)
10439        with TiffFile(fname) as tif:
10440            assert len(tif.pages) == 1
10441            page = tif.pages[0]
10442            assert page.compression == (ADOBE_DEFLATE if compressed else NONE)
10443            assert page.planarconfig == SEPARATE
10444            assert page.photometric == RGB
10445            assert page.imagewidth == 301
10446            assert page.imagelength == 219
10447            assert page.samplesperpixel == 3
10448            assert len(page.dataoffsets) == (9 if compressed else 3)
10449            image = tif.asarray()
10450            assert_array_equal(data, image)
10451            assert__str__(tif)
10452
10453
10454@pytest.mark.parametrize(
10455    'args', [(0, 0), (1, 5), (2, ADOBE_DEFLATE), (3, ADOBE_DEFLATE, 5)]
10456)
10457def test_write_compress_args(args):
10458    """Test deprecated compress parameter."""
10459    i = args[0]
10460    compressargs = args[1:]
10461    compressed = compressargs[0] != 0
10462    if len(compressargs) == 1:
10463        compressargs = compressargs[0]
10464
10465    data = WRITE_DATA
10466    with TempFileName(f'compression_args_{i}') as fname:
10467        with pytest.warns(DeprecationWarning):
10468            imwrite(fname, data, compress=compressargs, photometric=RGB)
10469        assert_valid_tiff(fname)
10470        with TiffFile(fname) as tif:
10471            assert len(tif.pages) == 1
10472            page = tif.pages[0]
10473            assert page.compression == (ADOBE_DEFLATE if compressed else NONE)
10474            assert page.planarconfig == SEPARATE
10475            assert page.photometric == RGB
10476            assert page.imagewidth == 301
10477            assert page.imagelength == 219
10478            assert page.samplesperpixel == 3
10479            assert len(page.dataoffsets) == (9 if compressed else 3)
10480            image = tif.asarray()
10481            assert_array_equal(data, image)
10482            assert__str__(tif)
10483
10484
10485def test_write_compression_none():
10486    """Test write compression=0."""
10487    data = WRITE_DATA
10488    with TempFileName('compression_none') as fname:
10489        imwrite(fname, data, compression=0, photometric=RGB)
10490        assert_valid_tiff(fname)
10491        with TiffFile(fname) as tif:
10492            assert len(tif.pages) == 1
10493            page = tif.pages[0]
10494            assert page.is_contiguous
10495            assert page.compression == NONE
10496            assert page.planarconfig == SEPARATE
10497            assert page.photometric == RGB
10498            assert page.imagewidth == 301
10499            assert page.imagelength == 219
10500            assert page.samplesperpixel == 3
10501            assert len(page.dataoffsets) == 3
10502            image = tif.asarray()
10503            assert_array_equal(data, image)
10504            assert_aszarr_method(tif, image)
10505            assert__str__(tif)
10506
10507
10508# @pytest.mark.parametrize('optimize', [None, False, True])
10509# @pytest.mark.parametrize('smoothing', [None, 10])
10510@pytest.mark.skipif(
10511    SKIP_PUBLIC or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
10512)
10513@pytest.mark.parametrize('subsampling', ['444', '422', '420', '411'])
10514@pytest.mark.parametrize('dtype', [numpy.uint8, numpy.uint16])
10515def test_write_compression_jpeg(dtype, subsampling):
10516    """Test write JPEG compression with subsampling."""
10517    dtype = numpy.dtype(dtype)
10518    filename = f'compression_jpeg_{dtype}_{subsampling}'
10519    subsampling, atol = {
10520        '444': [(1, 1), 5],
10521        '422': [(2, 1), 10],
10522        '420': [(2, 2), 20],
10523        '411': [(4, 1), 40],
10524    }[subsampling]
10525    data = numpy.load(public_file('tifffile/rgb.u1.npy')).astype(dtype)
10526    data = data[:32, :16].copy()  # make divisable by subsamples
10527    with TempFileName(filename) as fname:
10528        imwrite(
10529            fname,
10530            data,
10531            compression=(JPEG, 99),
10532            subsampling=subsampling,
10533            photometric=RGB,
10534        )
10535        assert_valid_tiff(fname)
10536        with TiffFile(fname) as tif:
10537            assert len(tif.pages) == 1
10538            page = tif.pages[0]
10539            assert not page.is_contiguous
10540            if subsampling[0] > 1:
10541                assert page.is_subsampled
10542                assert page.tags['YCbCrSubSampling'].value == subsampling
10543            assert page.compression == JPEG
10544            assert page.photometric == YCBCR
10545            assert page.imagewidth == data.shape[1]
10546            assert page.imagelength == data.shape[0]
10547            assert page.samplesperpixel == 3
10548            image = tif.asarray()
10549            assert_allclose(data, image, atol=atol)
10550            assert_aszarr_method(tif, image)
10551            assert__str__(tif)
10552
10553
10554def test_write_compression_deflate():
10555    """Test write ZLIB compression."""
10556    data = WRITE_DATA
10557    with TempFileName('compression_deflate') as fname:
10558        imwrite(fname, data, compression=(DEFLATE, 6), photometric=RGB)
10559        assert_valid_tiff(fname)
10560        with TiffFile(fname) as tif:
10561            assert len(tif.pages) == 1
10562            page = tif.pages[0]
10563            assert not page.is_contiguous
10564            assert page.compression == DEFLATE
10565            assert page.planarconfig == SEPARATE
10566            assert page.photometric == RGB
10567            assert page.imagewidth == 301
10568            assert page.imagelength == 219
10569            assert page.samplesperpixel == 3
10570            assert page.rowsperstrip == 108
10571            assert len(page.dataoffsets) == 9
10572            image = tif.asarray()
10573            assert_array_equal(data, image)
10574            assert_aszarr_method(tif, image)
10575            assert__str__(tif)
10576
10577
10578def test_write_compression_deflate_level():
10579    """Test write ZLIB compression with level."""
10580    data = WRITE_DATA
10581    with TempFileName('compression_deflate_level') as fname:
10582        imwrite(fname, data, compression=(ADOBE_DEFLATE, 9), photometric=RGB)
10583        assert_valid_tiff(fname)
10584        with TiffFile(fname) as tif:
10585            assert len(tif.pages) == 1
10586            page = tif.pages[0]
10587            assert not page.is_contiguous
10588            assert page.compression == ADOBE_DEFLATE
10589            assert page.planarconfig == SEPARATE
10590            assert page.photometric == RGB
10591            assert page.imagewidth == 301
10592            assert page.imagelength == 219
10593            assert page.samplesperpixel == 3
10594            image = tif.asarray()
10595            assert_array_equal(data, image)
10596            assert_aszarr_method(tif, image)
10597            assert__str__(tif)
10598
10599
10600@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
10601def test_write_compression_lzma():
10602    """Test write LZMA compression."""
10603    data = WRITE_DATA
10604    with TempFileName('compression_lzma') as fname:
10605        imwrite(fname, data, compression=LZMA, photometric=RGB)
10606        assert_valid_tiff(fname)
10607        with TiffFile(fname) as tif:
10608            assert len(tif.pages) == 1
10609            page = tif.pages[0]
10610            assert not page.is_contiguous
10611            assert page.compression == LZMA
10612            assert page.planarconfig == SEPARATE
10613            assert page.photometric == RGB
10614            assert page.imagewidth == 301
10615            assert page.imagelength == 219
10616            assert page.samplesperpixel == 3
10617            assert page.rowsperstrip == 108
10618            assert len(page.dataoffsets) == 9
10619            image = tif.asarray()
10620            assert_array_equal(data, image)
10621            assert_aszarr_method(tif, image)
10622            assert__str__(tif)
10623
10624
10625@pytest.mark.skipif(SKIP_CODECS or not imagecodecs.ZSTD, reason=REASON)
10626def test_write_compression_zstd():
10627    """Test write ZSTD compression."""
10628    data = WRITE_DATA
10629    with TempFileName('compression_zstd') as fname:
10630        imwrite(fname, data, compression=ZSTD, photometric=RGB)
10631        assert_valid_tiff(fname)
10632        with TiffFile(fname) as tif:
10633            assert len(tif.pages) == 1
10634            page = tif.pages[0]
10635            assert not page.is_contiguous
10636            assert page.compression == ZSTD
10637            assert page.planarconfig == SEPARATE
10638            assert page.photometric == RGB
10639            assert page.imagewidth == 301
10640            assert page.imagelength == 219
10641            assert page.samplesperpixel == 3
10642            assert page.rowsperstrip == 108
10643            assert len(page.dataoffsets) == 9
10644            image = tif.asarray()
10645            assert_array_equal(data, image)
10646            assert_aszarr_method(tif, image)
10647            assert__str__(tif)
10648
10649
10650@pytest.mark.skipif(SKIP_CODECS or not imagecodecs.WEBP, reason=REASON)
10651def test_write_compression_webp():
10652    """Test write WEBP compression."""
10653    data = WRITE_DATA.astype(numpy.uint8).reshape((219, 301, 3))
10654    with TempFileName('compression_webp') as fname:
10655        imwrite(fname, data, compression=(WEBP, -1), photometric=RGB)
10656        assert_valid_tiff(fname)
10657        with TiffFile(fname) as tif:
10658            assert len(tif.pages) == 1
10659            page = tif.pages[0]
10660            assert not page.is_contiguous
10661            assert page.compression == WEBP
10662            assert page.photometric == RGB
10663            assert page.imagewidth == 301
10664            assert page.imagelength == 219
10665            assert page.samplesperpixel == 3
10666            image = tif.asarray()
10667            assert_array_equal(data, image)
10668            assert_aszarr_method(tif, image)
10669            assert__str__(tif)
10670
10671
10672@pytest.mark.skipif(SKIP_CODECS or not imagecodecs.JPEGXL, reason=REASON)
10673def test_write_compression_jpegxl():
10674    """Test write JPEG XL compression."""
10675    data = WRITE_DATA.astype(numpy.uint8).reshape((219, 301, 3))
10676    with TempFileName('compression_jpegxl') as fname:
10677        imwrite(fname, data, compression=(JPEGXL, -1), photometric=RGB)
10678        assert_valid_tiff(fname)
10679        with TiffFile(fname) as tif:
10680            assert len(tif.pages) == 1
10681            page = tif.pages[0]
10682            assert not page.is_contiguous
10683            assert page.compression == JPEGXL
10684            assert page.photometric == RGB
10685            assert page.imagewidth == 301
10686            assert page.imagelength == 219
10687            assert page.samplesperpixel == 3
10688            image = tif.asarray()
10689            assert_array_equal(data, image)
10690            assert_aszarr_method(tif, image)
10691            assert__str__(tif)
10692
10693
10694@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
10695def test_write_compression_lerc():
10696    """Test write LERC compression."""
10697    if not hasattr(imagecodecs, 'LERC'):
10698        pytest.skip('LERC codec missing')
10699    data = WRITE_DATA.astype(numpy.uint16).reshape((219, 301, 3))
10700    with TempFileName('compression_lerc') as fname:
10701        imwrite(fname, data, compression=LERC, photometric=RGB)
10702        assert_valid_tiff(fname)
10703        with TiffFile(fname) as tif:
10704            assert len(tif.pages) == 1
10705            page = tif.pages[0]
10706            assert not page.is_contiguous
10707            assert page.compression == LERC
10708            assert page.photometric == RGB
10709            assert page.imagewidth == 301
10710            assert page.imagelength == 219
10711            assert page.samplesperpixel == 3
10712            image = tif.asarray()
10713            assert_array_equal(data, image)
10714            assert_aszarr_method(tif, image)
10715            assert__str__(tif)
10716
10717
10718@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
10719@pytest.mark.parametrize('dtype', [numpy.int8, numpy.uint8, numpy.bool8])
10720@pytest.mark.parametrize('tile', [None, (16, 16)])
10721def test_write_compression_packbits(dtype, tile):
10722    """Test write PackBits compression."""
10723    dtype = numpy.dtype(dtype)
10724    uncompressed = numpy.frombuffer(
10725        b'\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00'
10726        b'\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa',
10727        dtype=dtype,
10728    )
10729    shape = 2, 7, uncompressed.size
10730    data = numpy.empty(shape, dtype=dtype)
10731    data[..., :] = uncompressed
10732    with TempFileName(f'compression_packits_{dtype}') as fname:
10733        imwrite(fname, data, compression=PACKBITS, tile=tile)
10734        assert_valid_tiff(fname)
10735        with TiffFile(fname) as tif:
10736            assert len(tif.pages) == 2
10737            page = tif.pages[0]
10738            assert not page.is_contiguous
10739            assert page.compression == PACKBITS
10740            assert page.planarconfig == CONTIG
10741            assert page.imagewidth == uncompressed.size
10742            assert page.imagelength == 7
10743            assert page.samplesperpixel == 1
10744            image = tif.asarray()
10745            assert_array_equal(data, image)
10746            assert_aszarr_method(tif, image)
10747            assert__str__(tif)
10748
10749
10750def test_write_compression_rowsperstrip():
10751    """Test write rowsperstrip with compression."""
10752    data = WRITE_DATA
10753    with TempFileName('compression_rowsperstrip') as fname:
10754        imwrite(
10755            fname,
10756            data,
10757            compression=ADOBE_DEFLATE,
10758            rowsperstrip=32,
10759            photometric=RGB,
10760        )
10761        assert_valid_tiff(fname)
10762        with TiffFile(fname) as tif:
10763            assert len(tif.pages) == 1
10764            page = tif.pages[0]
10765            assert not page.is_contiguous
10766            assert page.compression == ADOBE_DEFLATE
10767            assert page.planarconfig == SEPARATE
10768            assert page.photometric == RGB
10769            assert page.imagewidth == 301
10770            assert page.imagelength == 219
10771            assert page.samplesperpixel == 3
10772            assert page.rowsperstrip == 32
10773            assert len(page.dataoffsets) == 21
10774            image = tif.asarray()
10775            assert_array_equal(data, image)
10776            assert_aszarr_method(tif, image)
10777            assert__str__(tif)
10778
10779
10780def test_write_compression_tiled():
10781    """Test write compressed tiles."""
10782    data = WRITE_DATA
10783    with TempFileName('compression_tiled') as fname:
10784        imwrite(
10785            fname,
10786            data,
10787            compression=ADOBE_DEFLATE,
10788            tile=(32, 32),
10789            photometric=RGB,
10790        )
10791        assert_valid_tiff(fname)
10792        with TiffFile(fname) as tif:
10793            assert len(tif.pages) == 1
10794            page = tif.pages[0]
10795            assert not page.is_contiguous
10796            assert page.is_tiled
10797            assert page.compression == ADOBE_DEFLATE
10798            assert page.planarconfig == SEPARATE
10799            assert page.photometric == RGB
10800            assert page.imagewidth == 301
10801            assert page.imagelength == 219
10802            assert page.samplesperpixel == 3
10803            assert len(page.dataoffsets) == 210
10804            image = tif.asarray()
10805            assert_array_equal(data, image)
10806            assert_aszarr_method(tif, image)
10807            assert__str__(tif)
10808
10809
10810def test_write_compression_predictor():
10811    """Test write horizontal differencing."""
10812    data = WRITE_DATA
10813    with TempFileName('compression_predictor') as fname:
10814        imwrite(
10815            fname,
10816            data,
10817            compression=ADOBE_DEFLATE,
10818            predictor=HORIZONTAL,
10819            photometric=RGB,
10820        )
10821        assert_valid_tiff(fname)
10822        with TiffFile(fname) as tif:
10823            assert len(tif.pages) == 1
10824            page = tif.pages[0]
10825            assert not page.is_contiguous
10826            assert page.compression == ADOBE_DEFLATE
10827            assert page.planarconfig == SEPARATE
10828            assert page.photometric == RGB
10829            assert page.predictor == HORIZONTAL
10830            assert page.imagewidth == 301
10831            assert page.imagelength == 219
10832            assert page.samplesperpixel == 3
10833            image = tif.asarray()
10834            assert_array_equal(data, image)
10835            assert_aszarr_method(tif, image)
10836            assert__str__(tif)
10837
10838
10839@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
10840@pytest.mark.parametrize('dtype', [numpy.uint16, numpy.float32])
10841def test_write_compression_predictor_tiled(dtype):
10842    """Test write horizontal differencing with tiles."""
10843    dtype = numpy.dtype(dtype)
10844    data = WRITE_DATA.astype(dtype)
10845    with TempFileName(f'compression_tiled_predictor_{dtype}') as fname:
10846        imwrite(
10847            fname,
10848            data,
10849            compression=ADOBE_DEFLATE,
10850            predictor=True,
10851            tile=(32, 32),
10852            photometric=RGB,
10853        )
10854        if dtype.kind != 'f':
10855            assert_valid_tiff(fname)
10856        with TiffFile(fname) as tif:
10857            assert len(tif.pages) == 1
10858            page = tif.pages[0]
10859            assert not page.is_contiguous
10860            assert page.is_tiled
10861            assert page.compression == ADOBE_DEFLATE
10862            assert page.planarconfig == SEPARATE
10863            assert page.photometric == RGB
10864            assert page.imagewidth == 301
10865            assert page.imagelength == 219
10866            assert page.samplesperpixel == 3
10867            assert page.predictor == 3 if dtype.kind == 'f' else 2
10868            image = tif.asarray()
10869            assert_array_equal(data, image)
10870            assert_aszarr_method(tif, image)
10871            assert__str__(tif)
10872
10873
10874def test_write_rowsperstrip():
10875    """Test write rowsperstrip without compression."""
10876    data = WRITE_DATA
10877    with TempFileName('rowsperstrip') as fname:
10878        imwrite(
10879            fname,
10880            data,
10881            rowsperstrip=32,
10882            contiguous=False,
10883            photometric=RGB,
10884            metadata=None,
10885        )
10886        assert_valid_tiff(fname)
10887        with TiffFile(fname) as tif:
10888            assert len(tif.pages) == 1
10889            page = tif.pages[0]
10890            assert page.is_contiguous
10891            assert page.planarconfig == SEPARATE
10892            assert page.photometric == RGB
10893            assert page.imagewidth == 301
10894            assert page.imagelength == 219
10895            assert page.samplesperpixel == 3
10896            assert page.rowsperstrip == 32
10897            assert len(page.dataoffsets) == 21
10898            stripbytecounts = page.tags['StripByteCounts'].value
10899            assert stripbytecounts[0] == 19264
10900            assert stripbytecounts[6] == 16254
10901            image = tif.asarray()
10902            assert_array_equal(data, image)
10903            assert_aszarr_method(tif, image)
10904            assert__str__(tif)
10905
10906
10907@pytest.mark.skipif(SKIP_BE, reason=REASON)
10908def test_write_write_bigendian():
10909    """Test write big endian file."""
10910    # also test memory mapping non-native byte order
10911    data = random_data(numpy.float32, (2, 3, 219, 301)).newbyteorder()
10912    data = numpy.nan_to_num(data, copy=False)
10913    with TempFileName('write_bigendian') as fname:
10914        imwrite(fname, data, planarconfig=SEPARATE, photometric=RGB)
10915        assert_valid_tiff(fname)
10916        with TiffFile(fname) as tif:
10917            assert len(tif.pages) == 2
10918            assert len(tif.series) == 1
10919            assert tif.byteorder == '>'
10920            # assert not tif.isnative
10921            assert tif.series[0].offset is not None
10922            page = tif.pages[0]
10923            assert page.is_contiguous
10924            assert page.planarconfig == SEPARATE
10925            assert page.photometric == RGB
10926            assert page.imagewidth == 301
10927            assert page.imagelength == 219
10928            assert page.samplesperpixel == 3
10929            # test reading data
10930            image = tif.asarray()
10931            assert_array_equal(data, image)
10932            assert_aszarr_method(tif, image)
10933            image = page.asarray()
10934            assert_array_equal(data[0], image)
10935            # test direct memory mapping; returns big endian array
10936            image = tif.asarray(out='memmap')
10937            assert isinstance(image, numpy.core.memmap)
10938            assert image.dtype == numpy.dtype('>f4')
10939            assert_array_equal(data, image)
10940            del image
10941            image = page.asarray(out='memmap')
10942            assert isinstance(image, numpy.core.memmap)
10943            assert image.dtype == numpy.dtype('>f4')
10944            assert_array_equal(data[0], image)
10945            del image
10946            # test indirect memory mapping; returns native endian array
10947            image = tif.asarray(out='memmap:')
10948            assert isinstance(image, numpy.core.memmap)
10949            assert image.dtype == numpy.dtype('=f4')
10950            assert_array_equal(data, image)
10951            del image
10952            image = page.asarray(out='memmap:')
10953            assert isinstance(image, numpy.core.memmap)
10954            assert image.dtype == numpy.dtype('=f4')
10955            assert_array_equal(data[0], image)
10956            del image
10957            # test 2nd page
10958            page = tif.pages[1]
10959            image = page.asarray(out='memmap')
10960            assert isinstance(image, numpy.core.memmap)
10961            assert image.dtype == numpy.dtype('>f4')
10962            assert_array_equal(data[1], image)
10963            del image
10964            image = page.asarray(out='memmap:')
10965            assert isinstance(image, numpy.core.memmap)
10966            assert image.dtype == numpy.dtype('=f4')
10967            assert_array_equal(data[1], image)
10968            del image
10969            assert__str__(tif)
10970
10971
10972def test_write_zero_size():
10973    """Test write zero size array no longer fails."""
10974    # with pytest.raises(ValueError):
10975    with pytest.warns(UserWarning):
10976        with TempFileName('empty') as fname:
10977            imwrite(fname, numpy.empty(0))
10978
10979
10980def test_write_pixel():
10981    """Test write single pixel."""
10982    data = numpy.zeros(1, dtype=numpy.uint8)
10983    with TempFileName('pixel') as fname:
10984        imwrite(fname, data)
10985        assert_valid_tiff(fname)
10986        with TiffFile(fname) as tif:
10987            assert len(tif.pages) == 1
10988            assert tif.series[0].axes == 'Y'
10989            page = tif.pages[0]
10990            assert page.is_contiguous
10991            assert page.planarconfig == CONTIG
10992            assert page.photometric != RGB
10993            assert page.imagewidth == 1
10994            assert page.imagelength == 1
10995            assert page.samplesperpixel == 1
10996            image = tif.asarray()
10997            assert_array_equal(data, image)
10998            assert_aszarr_method(tif, image)
10999            assert_aszarr_method(tif, image, chunkmode='page')
11000            assert__str__(tif)
11001
11002
11003def test_write_small():
11004    """Test write small image."""
11005    data = random_data(numpy.uint8, (1, 1))
11006    with TempFileName('small') as fname:
11007        imwrite(fname, data)
11008        assert_valid_tiff(fname)
11009        with TiffFile(fname) as tif:
11010            assert len(tif.pages) == 1
11011            page = tif.pages[0]
11012            assert page.is_contiguous
11013            assert page.planarconfig == CONTIG
11014            assert page.photometric != RGB
11015            assert page.imagewidth == 1
11016            assert page.imagelength == 1
11017            assert page.samplesperpixel == 1
11018            image = tif.asarray()
11019            assert_array_equal(data, image)
11020            assert_aszarr_method(tif, image)
11021            assert__str__(tif)
11022
11023
11024def test_write_2d_as_rgb():
11025    """Test write RGB color palette as RGB image."""
11026    # image length should be 1
11027    data = numpy.arange(3 * 256, dtype=numpy.uint16).reshape(256, 3) // 3
11028    with TempFileName('2d_as_rgb_contig') as fname:
11029        imwrite(fname, data, photometric=RGB)
11030        assert_valid_tiff(fname)
11031        with TiffFile(fname) as tif:
11032            assert len(tif.pages) == 1
11033            assert tif.series[0].axes == 'XS'
11034            page = tif.pages[0]
11035            assert page.is_contiguous
11036            assert page.planarconfig == CONTIG
11037            assert page.photometric == RGB
11038            assert page.imagewidth == 256
11039            assert page.imagelength == 1
11040            assert page.samplesperpixel == 3
11041            image = tif.asarray()
11042            assert_array_equal(data, image)
11043            assert_aszarr_method(tif, image)
11044            assert_aszarr_method(tif, image, chunkmode='page')
11045            assert__str__(tif)
11046
11047
11048def test_write_invalid_contig_rgb():
11049    """Test write planar RGB with 2 samplesperpixel."""
11050    data = random_data(numpy.uint8, (219, 301, 2))
11051    with pytest.raises(ValueError):
11052        with TempFileName('invalid_contig_rgb') as fname:
11053            imwrite(fname, data, photometric=RGB)
11054    # default to pages
11055    with TempFileName('invalid_contig_rgb_pages') as fname:
11056        imwrite(fname, data)
11057        assert_valid_tiff(fname)
11058        with TiffFile(fname) as tif:
11059            assert len(tif.pages) == 219
11060            assert tif.series[0].axes == 'QYX'
11061            page = tif.pages[0]
11062            assert page.is_contiguous
11063            assert page.planarconfig == CONTIG
11064            assert page.photometric != RGB
11065            assert page.imagewidth == 2
11066            assert page.imagelength == 301
11067            assert page.samplesperpixel == 1
11068            image = tif.asarray()
11069            assert_array_equal(data, image)
11070            assert_aszarr_method(tif, image)
11071            assert__str__(tif)
11072    # better save as contig samples
11073    with TempFileName('invalid_contig_rgb_samples') as fname:
11074        imwrite(fname, data, planarconfig=CONTIG)
11075        assert_valid_tiff(fname)
11076        with TiffFile(fname) as tif:
11077            assert len(tif.pages) == 1
11078            assert tif.series[0].axes == 'YXS'
11079            page = tif.pages[0]
11080            assert page.is_contiguous
11081            assert page.planarconfig == CONTIG
11082            assert page.photometric != RGB
11083            assert page.imagewidth == 301
11084            assert page.imagelength == 219
11085            assert page.samplesperpixel == 2
11086            image = tif.asarray()
11087            assert_array_equal(data, image)
11088            assert_aszarr_method(tif, image)
11089            assert__str__(tif)
11090
11091
11092def test_write_invalid_planar_rgb():
11093    """Test write planar RGB with 2 samplesperpixel."""
11094    data = random_data(numpy.uint8, (2, 219, 301))
11095    with pytest.raises(ValueError):
11096        with TempFileName('invalid_planar_rgb') as fname:
11097            imwrite(fname, data, photometric=RGB, planarconfig=SEPARATE)
11098    # default to pages
11099    with TempFileName('invalid_planar_rgb_pages') as fname:
11100        imwrite(fname, data)
11101        assert_valid_tiff(fname)
11102        with TiffFile(fname) as tif:
11103            assert len(tif.pages) == 2
11104            assert tif.series[0].axes == 'QYX'
11105            page = tif.pages[0]
11106            assert page.is_contiguous
11107            assert page.planarconfig == CONTIG
11108            assert page.photometric != RGB
11109            assert page.imagewidth == 301
11110            assert page.imagelength == 219
11111            assert page.samplesperpixel == 1
11112            image = tif.asarray()
11113            assert_array_equal(data, image)
11114            assert_aszarr_method(tif, image)
11115            assert__str__(tif)
11116    # or save as planar samples
11117    with TempFileName('invalid_planar_rgb_samples') as fname:
11118        imwrite(fname, data, planarconfig=SEPARATE)
11119        assert_valid_tiff(fname)
11120        with TiffFile(fname) as tif:
11121            assert len(tif.pages) == 1
11122            assert tif.series[0].axes == 'SYX'
11123            page = tif.pages[0]
11124            assert page.is_contiguous
11125            assert page.planarconfig == SEPARATE
11126            assert page.photometric != RGB
11127            assert page.imagewidth == 301
11128            assert page.imagelength == 219
11129            assert page.samplesperpixel == 2
11130            image = tif.asarray()
11131            assert_array_equal(data, image)
11132            assert_aszarr_method(tif, image)
11133            assert__str__(tif)
11134
11135
11136def test_write_extrasamples_gray():
11137    """Test write grayscale with extrasamples contig."""
11138    data = random_data(numpy.uint8, (301, 219, 2))
11139    with TempFileName('extrasamples_gray') as fname:
11140        imwrite(fname, data, extrasamples=UNASSALPHA)
11141        assert_valid_tiff(fname)
11142        with TiffFile(fname) as tif:
11143            assert len(tif.pages) == 1
11144            page = tif.pages[0]
11145            assert page.is_contiguous
11146            assert page.photometric == MINISBLACK
11147            assert page.planarconfig == CONTIG
11148            assert page.imagewidth == 219
11149            assert page.imagelength == 301
11150            assert page.samplesperpixel == 2
11151            assert page.extrasamples[0] == 2
11152            image = tif.asarray()
11153            assert_array_equal(data, image)
11154            assert_aszarr_method(tif, image)
11155            assert__str__(tif)
11156
11157
11158def test_write_extrasamples_gray_planar():
11159    """Test write planar grayscale with extrasamples."""
11160    data = random_data(numpy.uint8, (2, 301, 219))
11161    with TempFileName('extrasamples_gray_planar') as fname:
11162        imwrite(fname, data, planarconfig=SEPARATE, extrasamples=UNASSALPHA)
11163        assert_valid_tiff(fname)
11164        with TiffFile(fname) as tif:
11165            assert len(tif.pages) == 1
11166            page = tif.pages[0]
11167            assert page.is_contiguous
11168            assert page.photometric == MINISBLACK
11169            assert page.planarconfig == SEPARATE
11170            assert page.imagewidth == 219
11171            assert page.imagelength == 301
11172            assert page.samplesperpixel == 2
11173            assert page.extrasamples[0] == 2
11174            image = tif.asarray()
11175            assert_array_equal(data, image)
11176            assert_aszarr_method(tif, image)
11177            assert__str__(tif)
11178
11179
11180def test_write_extrasamples_gray_mix():
11181    """Test write grayscale with multiple extrasamples."""
11182    data = random_data(numpy.uint8, (301, 219, 4))
11183    with TempFileName('extrasamples_gray_mix') as fname:
11184        imwrite(
11185            fname,
11186            data,
11187            photometric=MINISBLACK,
11188            extrasamples=[ASSOCALPHA, UNASSALPHA, UNSPECIFIED],
11189        )
11190        assert_valid_tiff(fname)
11191        with TiffFile(fname) as tif:
11192            assert len(tif.pages) == 1
11193            page = tif.pages[0]
11194            assert page.is_contiguous
11195            assert page.photometric == MINISBLACK
11196            assert page.imagewidth == 219
11197            assert page.imagelength == 301
11198            assert page.samplesperpixel == 4
11199            assert page.extrasamples == (1, 2, 0)
11200            image = tif.asarray()
11201            assert_array_equal(data, image)
11202            assert_aszarr_method(tif, image)
11203            assert__str__(tif)
11204
11205
11206def test_write_extrasamples_unspecified():
11207    """Test write RGB with unspecified extrasamples by default."""
11208    data = random_data(numpy.uint8, (301, 219, 5))
11209    with TempFileName('extrasamples_unspecified') as fname:
11210        imwrite(fname, data, photometric=RGB)
11211        assert_valid_tiff(fname)
11212        with TiffFile(fname) as tif:
11213            assert len(tif.pages) == 1
11214            page = tif.pages[0]
11215            assert page.is_contiguous
11216            assert page.photometric == RGB
11217            assert page.imagewidth == 219
11218            assert page.imagelength == 301
11219            assert page.samplesperpixel == 5
11220            assert page.extrasamples == (0, 0)
11221            image = tif.asarray()
11222            assert_array_equal(data, image)
11223            assert_aszarr_method(tif, image)
11224            assert__str__(tif)
11225
11226
11227def test_write_extrasamples_assocalpha():
11228    """Test write RGB with assocalpha extrasample."""
11229    data = random_data(numpy.uint8, (219, 301, 4))
11230    with TempFileName('extrasamples_assocalpha') as fname:
11231        imwrite(fname, data, photometric=RGB, extrasamples=ASSOCALPHA)
11232        assert_valid_tiff(fname)
11233        with TiffFile(fname) as tif:
11234            assert len(tif.pages) == 1
11235            page = tif.pages[0]
11236            assert page.is_contiguous
11237            assert page.photometric == RGB
11238            assert page.imagewidth == 301
11239            assert page.imagelength == 219
11240            assert page.samplesperpixel == 4
11241            assert page.extrasamples[0] == 1
11242            image = tif.asarray()
11243            assert_array_equal(data, image)
11244            assert_aszarr_method(tif, image)
11245            assert__str__(tif)
11246
11247
11248def test_write_extrasamples_mix():
11249    """Test write RGB with mixture of extrasamples."""
11250    data = random_data(numpy.uint8, (219, 301, 6))
11251    with TempFileName('extrasamples_mix') as fname:
11252        imwrite(
11253            fname,
11254            data,
11255            photometric=RGB,
11256            extrasamples=[ASSOCALPHA, UNASSALPHA, UNSPECIFIED],
11257        )
11258        assert_valid_tiff(fname)
11259        with TiffFile(fname) as tif:
11260            assert len(tif.pages) == 1
11261            page = tif.pages[0]
11262            assert page.is_contiguous
11263            assert page.photometric == RGB
11264            assert page.imagewidth == 301
11265            assert page.imagelength == 219
11266            assert page.samplesperpixel == 6
11267            assert page.extrasamples == (1, 2, 0)
11268            image = tif.asarray()
11269            assert_array_equal(data, image)
11270            assert_aszarr_method(tif, image)
11271            assert__str__(tif)
11272
11273
11274def test_write_extrasamples_contig():
11275    """Test write contig grayscale with large number of extrasamples."""
11276    data = random_data(numpy.uint8, (3, 219, 301))
11277    with TempFileName('extrasamples_contig') as fname:
11278        imwrite(fname, data, planarconfig=CONTIG)
11279        assert_valid_tiff(fname)
11280        with TiffFile(fname) as tif:
11281            assert len(tif.pages) == 1
11282            page = tif.pages[0]
11283            assert page.is_contiguous
11284            assert page.planarconfig == CONTIG
11285            assert page.photometric != RGB
11286            assert page.imagewidth == 219
11287            assert page.imagelength == 3
11288            assert page.samplesperpixel == 301
11289            assert len(page.extrasamples) == 301 - 1
11290            image = tif.asarray()
11291            assert_array_equal(data, image)
11292            assert_aszarr_method(tif, image)
11293            assert__str__(tif)
11294    # better save as RGB planar
11295    with TempFileName('extrasamples_contig_planar') as fname:
11296        imwrite(fname, data, photometric=RGB, planarconfig=SEPARATE)
11297        assert_valid_tiff(fname)
11298        with TiffFile(fname) as tif:
11299            assert len(tif.pages) == 1
11300            page = tif.pages[0]
11301            assert page.is_contiguous
11302            assert page.planarconfig == SEPARATE
11303            assert page.photometric == RGB
11304            assert page.imagewidth == 301
11305            assert page.imagelength == 219
11306            assert page.samplesperpixel == 3
11307            image = tif.asarray()
11308            assert_array_equal(data, image)
11309            assert_aszarr_method(tif, image)
11310            assert__str__(tif)
11311
11312
11313def test_write_extrasamples_contig_rgb2():
11314    """Test write contig RGB with large number of extrasamples."""
11315    data = random_data(numpy.uint8, (3, 219, 301))
11316    with TempFileName('extrasamples_contig_rgb2') as fname:
11317        imwrite(fname, data, photometric=RGB, planarconfig=CONTIG)
11318        assert_valid_tiff(fname)
11319        with TiffFile(fname) as tif:
11320            assert len(tif.pages) == 1
11321            page = tif.pages[0]
11322            assert page.is_contiguous
11323            assert page.planarconfig == CONTIG
11324            assert page.photometric == RGB
11325            assert page.imagewidth == 219
11326            assert page.imagelength == 3
11327            assert page.samplesperpixel == 301
11328            assert len(page.extrasamples) == 301 - 3
11329            image = tif.asarray()
11330            assert_array_equal(data, image)
11331            assert_aszarr_method(tif, image)
11332            assert__str__(tif)
11333    # better save as planar
11334    with TempFileName('extrasamples_contig_rgb2_planar') as fname:
11335        imwrite(fname, data, photometric=RGB, planarconfig=SEPARATE)
11336        assert_valid_tiff(fname)
11337        with TiffFile(fname) as tif:
11338            assert len(tif.pages) == 1
11339            page = tif.pages[0]
11340            assert page.is_contiguous
11341            assert page.planarconfig == SEPARATE
11342            assert page.photometric == RGB
11343            assert page.imagewidth == 301
11344            assert page.imagelength == 219
11345            assert page.samplesperpixel == 3
11346            image = tif.asarray()
11347            assert_array_equal(data, image)
11348            assert_aszarr_method(tif, image)
11349            assert__str__(tif)
11350
11351
11352def test_write_extrasamples_planar():
11353    """Test write planar large number of extrasamples."""
11354    data = random_data(numpy.uint8, (219, 301, 3))
11355    with TempFileName('extrasamples_planar') as fname:
11356        imwrite(fname, data, planarconfig=SEPARATE)
11357        assert_valid_tiff(fname)
11358        with TiffFile(fname) as tif:
11359            assert len(tif.pages) == 1
11360            page = tif.pages[0]
11361            assert page.is_contiguous
11362            assert page.planarconfig == SEPARATE
11363            assert page.photometric != RGB
11364            assert page.imagewidth == 3
11365            assert page.imagelength == 301
11366            assert page.samplesperpixel == 219
11367            assert len(page.extrasamples) == 219 - 1
11368            image = tif.asarray()
11369            assert_array_equal(data, image)
11370            assert_aszarr_method(tif, image)
11371            assert__str__(tif)
11372
11373
11374def test_write_extrasamples_planar_rgb2():
11375    """Test write planar RGB with large number of extrasamples."""
11376    data = random_data(numpy.uint8, (219, 301, 3))
11377    with TempFileName('extrasamples_planar_rgb2') as fname:
11378        imwrite(fname, data, photometric=RGB, planarconfig=SEPARATE)
11379        assert_valid_tiff(fname)
11380        with TiffFile(fname) as tif:
11381            assert len(tif.pages) == 1
11382            page = tif.pages[0]
11383            assert page.is_contiguous
11384            assert page.planarconfig == SEPARATE
11385            assert page.photometric == RGB
11386            assert page.imagewidth == 3
11387            assert page.imagelength == 301
11388            assert page.samplesperpixel == 219
11389            assert len(page.extrasamples) == 219 - 3
11390            image = tif.asarray()
11391            assert_array_equal(data, image)
11392            assert_aszarr_method(tif, image)
11393            assert__str__(tif)
11394
11395
11396def test_write_minisblack_planar():
11397    """Test write planar minisblack."""
11398    data = random_data(numpy.uint8, (3, 219, 301))
11399    with TempFileName('minisblack_planar') as fname:
11400        imwrite(fname, data, photometric=MINISBLACK)
11401        assert_valid_tiff(fname)
11402        with TiffFile(fname) as tif:
11403            assert len(tif.pages) == 3
11404            page = tif.pages[0]
11405            assert page.is_contiguous
11406            assert page.planarconfig == CONTIG
11407            assert page.photometric != RGB
11408            assert page.imagewidth == 301
11409            assert page.imagelength == 219
11410            assert page.samplesperpixel == 1
11411            image = tif.asarray()
11412            assert_array_equal(data, image)
11413            assert_aszarr_method(tif, image)
11414            assert__str__(tif)
11415
11416
11417def test_write_minisblack_contig():
11418    """Test write contig minisblack."""
11419    data = random_data(numpy.uint8, (219, 301, 3))
11420    with TempFileName('minisblack_contig') as fname:
11421        imwrite(fname, data, photometric=MINISBLACK)
11422        assert_valid_tiff(fname)
11423        with TiffFile(fname) as tif:
11424            assert len(tif.pages) == 219
11425            page = tif.pages[0]
11426            assert page.is_contiguous
11427            assert page.planarconfig == CONTIG
11428            assert page.photometric != RGB
11429            assert page.imagewidth == 3
11430            assert page.imagelength == 301
11431            assert page.samplesperpixel == 1
11432            image = tif.asarray()
11433            assert_array_equal(data, image)
11434            assert_aszarr_method(tif, image)
11435            assert__str__(tif)
11436
11437
11438def test_write_scalar():
11439    """Test write 2D grayscale."""
11440    data = random_data(numpy.uint8, (219, 301))
11441    with TempFileName('scalar') as fname:
11442        imwrite(fname, data)
11443        assert_valid_tiff(fname)
11444        with TiffFile(fname) as tif:
11445            assert len(tif.pages) == 1
11446            page = tif.pages[0]
11447            assert page.is_contiguous
11448            assert page.planarconfig == CONTIG
11449            assert page.photometric != RGB
11450            assert page.imagewidth == 301
11451            assert page.imagelength == 219
11452            assert page.samplesperpixel == 1
11453            image = tif.asarray()
11454            assert_array_equal(data, image)
11455            assert_aszarr_method(tif, image)
11456            assert__str__(tif)
11457
11458
11459def test_write_scalar_3d():
11460    """Test write 3D grayscale."""
11461    data = random_data(numpy.uint8, (63, 219, 301))
11462    with TempFileName('scalar_3d') as fname:
11463        imwrite(fname, data)
11464        assert_valid_tiff(fname)
11465        with TiffFile(fname) as tif:
11466            assert len(tif.pages) == 63
11467            page = tif.pages[62]
11468            assert page.is_contiguous
11469            assert page.planarconfig == CONTIG
11470            assert page.photometric != RGB
11471            assert page.imagewidth == 301
11472            assert page.imagelength == 219
11473            assert page.samplesperpixel == 1
11474            image = tif.asarray()
11475            assert isinstance(image, numpy.ndarray)
11476            assert_array_equal(data, image)
11477            assert_aszarr_method(tif, image)
11478            assert__str__(tif)
11479
11480
11481def test_write_scalar_4d():
11482    """Test write 4D grayscale."""
11483    data = random_data(numpy.uint8, (3, 2, 219, 301))
11484    with TempFileName('scalar_4d') as fname:
11485        imwrite(fname, data)
11486        assert_valid_tiff(fname)
11487        with TiffFile(fname) as tif:
11488            assert len(tif.pages) == 6
11489            page = tif.pages[5]
11490            assert page.is_contiguous
11491            assert page.planarconfig == CONTIG
11492            assert page.photometric != RGB
11493            assert page.imagewidth == 301
11494            assert page.imagelength == 219
11495            assert page.samplesperpixel == 1
11496            image = tif.asarray()
11497            assert_array_equal(data, image)
11498            assert_aszarr_method(tif, image)
11499            assert__str__(tif)
11500
11501
11502def test_write_contig_extrasample():
11503    """Test write grayscale with contig extrasamples."""
11504    data = random_data(numpy.uint8, (219, 301, 2))
11505    with TempFileName('contig_extrasample') as fname:
11506        imwrite(fname, data, planarconfig=CONTIG)
11507        assert_valid_tiff(fname)
11508        with TiffFile(fname) as tif:
11509            assert len(tif.pages) == 1
11510            page = tif.pages[0]
11511            assert page.is_contiguous
11512            assert page.planarconfig == CONTIG
11513            assert page.photometric != RGB
11514            assert page.imagewidth == 301
11515            assert page.imagelength == 219
11516            assert page.samplesperpixel == 2
11517            image = tif.asarray()
11518            assert_array_equal(data, image)
11519            assert_aszarr_method(tif, image)
11520            assert__str__(tif)
11521
11522
11523def test_write_planar_extrasample():
11524    """Test write grayscale with planar extrasamples."""
11525    data = random_data(numpy.uint8, (2, 219, 301))
11526    with TempFileName('planar_extrasample') as fname:
11527        imwrite(fname, data, planarconfig=SEPARATE)
11528        assert_valid_tiff(fname)
11529        with TiffFile(fname) as tif:
11530            assert len(tif.pages) == 1
11531            page = tif.pages[0]
11532            assert page.is_contiguous
11533            assert page.planarconfig == SEPARATE
11534            assert page.photometric != RGB
11535            assert page.imagewidth == 301
11536            assert page.imagelength == 219
11537            assert page.samplesperpixel == 2
11538            image = tif.asarray()
11539            assert_array_equal(data, image)
11540            assert_aszarr_method(tif, image)
11541            assert__str__(tif)
11542
11543
11544def test_write_auto_rgb_contig():
11545    """Test write auto contig RGB."""
11546    data = random_data(numpy.uint8, (219, 301, 3))
11547    with TempFileName('auto_rgb_contig') as fname:
11548        imwrite(fname, data)  # photometric=RGB
11549        assert_valid_tiff(fname)
11550        with TiffFile(fname) as tif:
11551            assert len(tif.pages) == 1
11552            page = tif.pages[0]
11553            assert page.is_contiguous
11554            assert page.planarconfig == CONTIG
11555            assert page.photometric == RGB
11556            assert page.imagewidth == 301
11557            assert page.imagelength == 219
11558            assert page.samplesperpixel == 3
11559            image = tif.asarray()
11560            assert_array_equal(data, image)
11561            assert_aszarr_method(tif, image)
11562            assert__str__(tif)
11563
11564
11565def test_write_auto_rgb_planar():
11566    """Test write auto planar RGB."""
11567    data = random_data(numpy.uint8, (3, 219, 301))
11568    with TempFileName('auto_rgb_planar') as fname:
11569        with pytest.warns(DeprecationWarning):
11570            imwrite(fname, data)  # photometric=RGB, planarconfig=SEPARATE
11571        assert_valid_tiff(fname)
11572        with TiffFile(fname) as tif:
11573            assert len(tif.pages) == 1
11574            page = tif.pages[0]
11575            assert page.is_contiguous
11576            assert page.planarconfig == SEPARATE
11577            assert page.photometric == RGB
11578            assert page.imagewidth == 301
11579            assert page.imagelength == 219
11580            assert page.samplesperpixel == 3
11581            image = tif.asarray()
11582            assert_array_equal(data, image)
11583            assert_aszarr_method(tif, image)
11584            assert__str__(tif)
11585
11586
11587def test_write_auto_rgba_contig():
11588    """Test write auto contig RGBA."""
11589    data = random_data(numpy.uint8, (219, 301, 4))
11590    with TempFileName('auto_rgba_contig') as fname:
11591        imwrite(fname, data)  # photometric=RGB
11592        assert_valid_tiff(fname)
11593        with TiffFile(fname) as tif:
11594            assert len(tif.pages) == 1
11595            page = tif.pages[0]
11596            assert page.is_contiguous
11597            assert page.planarconfig == CONTIG
11598            assert page.photometric == RGB
11599            assert page.imagewidth == 301
11600            assert page.imagelength == 219
11601            assert page.samplesperpixel == 4
11602            assert page.extrasamples[0] == UNASSALPHA
11603            image = tif.asarray()
11604            assert_array_equal(data, image)
11605            assert_aszarr_method(tif, image)
11606            assert__str__(tif)
11607
11608
11609def test_write_auto_rgba_planar():
11610    """Test write auto planar RGBA."""
11611    data = random_data(numpy.uint8, (4, 219, 301))
11612    with TempFileName('auto_rgba_planar') as fname:
11613        with pytest.warns(DeprecationWarning):
11614            imwrite(fname, data)  # photometric=RGB, planarconfig=SEPARATE
11615        assert_valid_tiff(fname)
11616        with TiffFile(fname) as tif:
11617            assert len(tif.pages) == 1
11618            page = tif.pages[0]
11619            assert page.is_contiguous
11620            assert page.planarconfig == SEPARATE
11621            assert page.photometric == RGB
11622            assert page.imagewidth == 301
11623            assert page.imagelength == 219
11624            assert page.samplesperpixel == 4
11625            assert page.extrasamples[0] == UNASSALPHA
11626            image = tif.asarray()
11627            assert_array_equal(data, image)
11628            assert_aszarr_method(tif, image)
11629            assert__str__(tif)
11630
11631
11632def test_write_extrasamples_contig_rgb():
11633    """Test write contig RGB with extrasamples."""
11634    data = random_data(numpy.uint8, (219, 301, 8))
11635    with TempFileName('extrasamples_contig') as fname:
11636        imwrite(fname, data, photometric=RGB)
11637        assert_valid_tiff(fname)
11638        with TiffFile(fname) as tif:
11639            assert len(tif.pages) == 1
11640            page = tif.pages[0]
11641            assert page.is_contiguous
11642            assert page.planarconfig == CONTIG
11643            assert page.photometric == RGB
11644            assert page.imagewidth == 301
11645            assert page.imagelength == 219
11646            assert page.samplesperpixel == 8
11647            assert len(page.extrasamples) == 5
11648            assert page.extrasamples[0] == UNSPECIFIED
11649            image = tif.asarray()
11650            assert_array_equal(data, image)
11651            assert_aszarr_method(tif, image)
11652            assert__str__(tif)
11653
11654
11655def test_write_extrasamples_planar_rgb():
11656    """Test write planar RGB with extrasamples."""
11657    data = random_data(numpy.uint8, (8, 219, 301))
11658    with TempFileName('extrasamples_planar') as fname:
11659        imwrite(fname, data, photometric=RGB)
11660        assert_valid_tiff(fname)
11661        with TiffFile(fname) as tif:
11662            assert len(tif.pages) == 1
11663            page = tif.pages[0]
11664            assert page.is_contiguous
11665            assert page.planarconfig == SEPARATE
11666            assert page.photometric == RGB
11667            assert page.imagewidth == 301
11668            assert page.imagelength == 219
11669            assert page.samplesperpixel == 8
11670            assert len(page.extrasamples) == 5
11671            assert page.extrasamples[0] == UNSPECIFIED
11672            image = tif.asarray()
11673            assert_array_equal(data, image)
11674            assert_aszarr_method(tif, image)
11675            assert__str__(tif)
11676
11677
11678@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
11679def test_write_cfa():
11680    """Test write uncompressed CFA image."""
11681    # TODO: write a valid TIFF/EP file
11682    data = imread(
11683        private_file('DNG/cinemadng/M14-1451_000085_cDNG_uncompressed.dng')
11684    )
11685    extratags = [
11686        (271, 's', 4, 'Make', False),
11687        (272, 's', 5, 'Model', False),
11688        (33421, 'H', 2, (2, 2), False),  # CFARepeatPatternDim
11689        (33422, 'B', 4, b'\x00\x01\x01\x02', False),  # CFAPattern
11690        # (37398, 'B', 4, b'\x01\x00\x00\x00', False),  # TIFF/EPStandardID
11691        # (37399, 'H', 1, 0)  # SensingMethod Undefined
11692        # (50706, 'B', 4, b'\x01\x04\x00\x00', False),  # DNGVersion
11693    ]
11694    with TempFileName('write_cfa') as fname:
11695        imwrite(
11696            fname,
11697            data,
11698            photometric=CFA,
11699            software='Tifffile',
11700            datetime=True,
11701            extratags=extratags,
11702        )
11703        with TiffFile(fname) as tif:
11704            assert len(tif.pages) == 1
11705            page = tif.pages[0]
11706            assert page.compression == 1
11707            assert page.photometric == CFA
11708            assert page.imagewidth == 960
11709            assert page.imagelength == 540
11710            assert page.bitspersample == 16
11711            assert page.tags['CFARepeatPatternDim'].value == (2, 2)
11712            assert page.tags['CFAPattern'].value == b'\x00\x01\x01\x02'
11713            assert_array_equal(page.asarray(), data)
11714            assert_aszarr_method(page, data)
11715
11716
11717def test_write_tiled_compressed():
11718    """Test write compressed tiles."""
11719    data = random_data(numpy.uint8, (3, 219, 301))
11720    with TempFileName('tiled_compressed') as fname:
11721        imwrite(
11722            fname,
11723            data,
11724            photometric=RGB,
11725            planarconfig=SEPARATE,
11726            compression=(ADOBE_DEFLATE, 5),
11727            tile=(96, 64),
11728        )
11729        assert_valid_tiff(fname)
11730        with TiffFile(fname) as tif:
11731            assert len(tif.pages) == 1
11732            page = tif.pages[0]
11733            assert page.is_tiled
11734            assert not page.is_contiguous
11735            assert page.planarconfig == SEPARATE
11736            assert page.photometric == RGB
11737            assert page.imagewidth == 301
11738            assert page.imagelength == 219
11739            assert page.tilewidth == 64
11740            assert page.tilelength == 96
11741            assert page.samplesperpixel == 3
11742            image = tif.asarray()
11743            assert_array_equal(data, image)
11744            assert_aszarr_method(tif, image)
11745            assert__str__(tif)
11746
11747
11748def test_write_tiled():
11749    """Test write tiled."""
11750    data = random_data(numpy.uint16, (219, 301))
11751    with TempFileName('tiled') as fname:
11752        imwrite(fname, data, tile=(96, 64))
11753        assert_valid_tiff(fname)
11754        with TiffFile(fname) as tif:
11755            assert len(tif.pages) == 1
11756            page = tif.pages[0]
11757            assert page.is_tiled
11758            assert not page.is_contiguous
11759            assert page.planarconfig == CONTIG
11760            assert page.photometric != RGB
11761            assert page.imagewidth == 301
11762            assert page.imagelength == 219
11763            assert page.tilewidth == 64
11764            assert page.tilelength == 96
11765            assert page.samplesperpixel == 1
11766            image = tif.asarray()
11767            assert_array_equal(data, image)
11768            assert_aszarr_method(tif, image)
11769            assert__str__(tif)
11770
11771
11772def test_write_tiled_planar():
11773    """Test write planar tiles."""
11774    data = random_data(numpy.uint8, (4, 219, 301))
11775    with TempFileName('tiled_planar') as fname:
11776        imwrite(
11777            fname, data, tile=(96, 64), photometric=RGB, planarconfig=SEPARATE
11778        )
11779        assert_valid_tiff(fname)
11780        with TiffFile(fname) as tif:
11781            assert len(tif.pages) == 1
11782            page = tif.pages[0]
11783            assert page.is_tiled
11784            assert not page.is_contiguous
11785            assert not page.is_volumetric
11786            assert page.planarconfig == SEPARATE
11787            assert page.photometric == RGB
11788            assert page.imagewidth == 301
11789            assert page.imagelength == 219
11790            assert page.tilewidth == 64
11791            assert page.tilelength == 96
11792            assert page.samplesperpixel == 4
11793            image = tif.asarray()
11794            assert_array_equal(data, image)
11795            assert_aszarr_method(tif, image)
11796            assert__str__(tif)
11797
11798
11799def test_write_tiled_contig():
11800    """Test write contig tiles."""
11801    data = random_data(numpy.uint8, (219, 301, 3))
11802    with TempFileName('tiled_contig') as fname:
11803        imwrite(fname, data, tile=(96, 64), photometric=RGB)
11804        assert_valid_tiff(fname)
11805        with TiffFile(fname) as tif:
11806            assert len(tif.pages) == 1
11807            page = tif.pages[0]
11808            assert page.is_tiled
11809            assert not page.is_contiguous
11810            assert page.planarconfig == CONTIG
11811            assert page.photometric == RGB
11812            assert page.imagewidth == 301
11813            assert page.imagelength == 219
11814            assert page.tilewidth == 64
11815            assert page.tilelength == 96
11816            assert page.samplesperpixel == 3
11817            image = tif.asarray()
11818            assert_array_equal(data, image)
11819            assert_aszarr_method(tif, image)
11820            assert__str__(tif)
11821
11822
11823def test_write_tiled_pages():
11824    """Test write multiple tiled pages."""
11825    data = random_data(numpy.uint8, (5, 219, 301, 3))
11826    with TempFileName('tiled_pages') as fname:
11827        imwrite(fname, data, tile=(96, 64), photometric=RGB)
11828        assert_valid_tiff(fname)
11829        with TiffFile(fname) as tif:
11830            assert len(tif.pages) == 5
11831            page = tif.pages[0]
11832            assert page.is_tiled
11833            assert not page.is_contiguous
11834            assert page.planarconfig == CONTIG
11835            assert page.photometric == RGB
11836            assert not page.is_volumetric
11837            assert page.imagewidth == 301
11838            assert page.imagelength == 219
11839            assert page.tilewidth == 64
11840            assert page.tilelength == 96
11841            assert page.samplesperpixel == 3
11842            image = tif.asarray()
11843            assert_array_equal(data, image)
11844            assert_aszarr_method(tif, image)
11845            assert__str__(tif)
11846
11847
11848def test_write_tileiter():
11849    """Test write tiles from iterator."""
11850    data = numpy.arange(3 * 4 * 16 * 16, dtype=numpy.uint16).reshape(
11851        (3 * 4, 16, 16)
11852    )
11853
11854    def tiles():
11855        for i in range(data.shape[0]):
11856            yield data[i]
11857
11858    with TempFileName('write_tileiter') as fname:
11859
11860        with pytest.raises(StopIteration):
11861            # missing tiles
11862            imwrite(
11863                fname,
11864                tiles(),
11865                shape=(43, 81),
11866                tile=(16, 16),
11867                dtype=numpy.uint16,
11868            )
11869
11870        with pytest.raises(TypeError):
11871            # missing parameters
11872            imwrite(fname, tiles())
11873
11874        with pytest.raises(TypeError):
11875            # missing parameters
11876            imwrite(fname, tiles(), shape=(43, 81))
11877
11878        with pytest.raises(ValueError):
11879            # dtype mismatch
11880            imwrite(
11881                fname,
11882                tiles(),
11883                shape=(43, 61),
11884                tile=(16, 16),
11885                dtype=numpy.uint32,
11886            )
11887
11888        with pytest.raises(ValueError):
11889            # shape mismatch
11890            imwrite(
11891                fname, tiles(), shape=(43, 61), tile=(8, 8), dtype=numpy.uint16
11892            )
11893
11894        imwrite(
11895            fname, tiles(), shape=(43, 61), tile=(16, 16), dtype=numpy.uint16
11896        )
11897
11898        with TiffFile(fname) as tif:
11899            page = tif.pages[0]
11900            assert page.shape == (43, 61)
11901            assert page.tilelength == 16
11902            assert page.tilewidth == 16
11903            image = page.asarray()
11904            assert_array_equal(image[:16, :16], data[0])
11905            for i, segment in enumerate(page.segments()):
11906                assert_array_equal(numpy.squeeze(segment[0]), data[i])
11907
11908
11909def test_write_tileiter_separate():
11910    """Test write separate tiles from iterator."""
11911    data = numpy.arange(2 * 3 * 4 * 16 * 16, dtype=numpy.uint16)
11912    data = data.reshape((2 * 3 * 4, 16, 16))
11913
11914    def tiles():
11915        for i in range(data.shape[0]):
11916            yield data[i]
11917
11918    with TempFileName('write_tile_iter_separate') as fname:
11919
11920        imwrite(
11921            fname,
11922            tiles(),
11923            shape=(2, 43, 61),
11924            tile=(16, 16),
11925            dtype=numpy.uint16,
11926            planarconfig=SEPARATE,
11927            compression=ADOBE_DEFLATE,
11928        )
11929
11930        with TiffFile(fname) as tif:
11931            assert len(tif.pages) == 1
11932            page = tif.pages[0]
11933            assert page.shape == (2, 43, 61)
11934            assert page.tilelength == 16
11935            assert page.tilewidth == 16
11936            assert page.planarconfig == 2
11937            image = page.asarray()
11938            assert_array_equal(image[0, :16, :16], data[0])
11939            for i, segment in enumerate(page.segments()):
11940                assert_array_equal(numpy.squeeze(segment[0]), data[i])
11941
11942
11943def test_write_pyramids():
11944    """Test write two pyramids to shaped file."""
11945    data = random_data(numpy.uint8, (31, 64, 96, 3))
11946    with TempFileName('pyramids') as fname:
11947        with TiffWriter(fname) as tif:
11948            # use pages
11949            tif.write(data, tile=(16, 16), photometric=RGB)
11950            # interrupt pyramid, e.g. thumbnail
11951            tif.write(data[0, :, :, 0])
11952            # pyramid levels
11953            tif.write(
11954                data[:, ::2, ::2],
11955                tile=(16, 16),
11956                subfiletype=1,
11957                photometric=RGB,
11958            )
11959            tif.write(
11960                data[:, ::4, ::4],
11961                tile=(16, 16),
11962                subfiletype=1,
11963                photometric=RGB,
11964            )
11965            # second pyramid using volumetric with downsampling factor 3
11966            tif.write(data, tile=(16, 16, 16), photometric=RGB)
11967            tif.write(
11968                data[::3, ::3, ::3],
11969                tile=(16, 16, 16),
11970                subfiletype=1,
11971                photometric=RGB,
11972            )
11973
11974        assert_valid_tiff(fname)
11975
11976        with TiffFile(fname) as tif:
11977            assert len(tif.pages) == 3 * 31 + 2 + 1
11978            assert len(tif.series) == 3
11979
11980            series = tif.series[0]
11981            assert series.is_pyramidal
11982            assert len(series.levels) == 3
11983            assert len(series.levels[0].pages) == 31
11984            assert len(series.levels[1].pages) == 31
11985            assert len(series.levels[2].pages) == 31
11986            assert series.levels[0].shape == (31, 64, 96, 3)
11987            assert series.levels[1].shape == (31, 32, 48, 3)
11988            assert series.levels[2].shape == (31, 16, 24, 3)
11989
11990            series = tif.series[1]
11991            assert not series.is_pyramidal
11992            assert series.shape == (64, 96)
11993
11994            series = tif.series[2]
11995            assert series.is_pyramidal
11996            assert len(series.levels) == 2
11997            assert len(series.levels[0].pages) == 1
11998            assert len(series.levels[1].pages) == 1
11999            assert series.levels[0].keyframe.is_volumetric
12000            assert series.levels[1].keyframe.is_volumetric
12001            assert series.levels[0].shape == (31, 64, 96, 3)
12002            assert series.levels[1].shape == (11, 22, 32, 3)
12003
12004            assert_array_equal(tif.asarray(), data)
12005            assert_array_equal(tif.asarray(series=0, level=0), data)
12006            assert_aszarr_method(tif, data, series=0, level=0)
12007
12008            assert_array_equal(
12009                data[:, ::2, ::2], tif.asarray(series=0, level=1)
12010            )
12011            assert_aszarr_method(tif, data[:, ::2, ::2], series=0, level=1)
12012
12013            assert_array_equal(
12014                data[:, ::4, ::4], tif.asarray(series=0, level=2)
12015            )
12016            assert_aszarr_method(tif, data[:, ::4, ::4], series=0, level=2)
12017
12018            assert_array_equal(data[0, :, :, 0], tif.asarray(series=1))
12019            assert_aszarr_method(tif, data[0, :, :, 0], series=1)
12020
12021            assert_array_equal(data, tif.asarray(series=2, level=0))
12022            assert_aszarr_method(tif, data, series=2, level=0)
12023
12024            assert_array_equal(
12025                data[::3, ::3, ::3], tif.asarray(series=2, level=1)
12026            )
12027            assert_aszarr_method(tif, data[::3, ::3, ::3], series=2, level=1)
12028
12029            assert__str__(tif)
12030
12031
12032def test_write_volumetric_tiled():
12033    """Test write tiled volume."""
12034    data = random_data(numpy.uint8, (253, 64, 96))
12035    with TempFileName('volumetric_tiled') as fname:
12036        imwrite(fname, data, tile=(64, 64, 64))
12037        assert_valid_tiff(fname)
12038        with TiffFile(fname) as tif:
12039            assert len(tif.pages) == 1
12040            page = tif.pages[0]
12041            assert page.is_volumetric
12042            assert page.is_tiled
12043            assert not page.is_contiguous
12044            assert page.planarconfig == CONTIG
12045            assert page.photometric != RGB
12046            assert page.imagewidth == 96
12047            assert page.imagelength == 64
12048            assert page.imagedepth == 253
12049            assert page.tilewidth == 64
12050            assert page.tilelength == 64
12051            assert page.tiledepth == 64
12052            assert page.samplesperpixel == 1
12053            image = tif.asarray()
12054            assert_array_equal(data, image)
12055            assert_aszarr_method(tif, image)
12056            assert__str__(tif)
12057
12058
12059@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
12060def test_write_volumetric_tiled_png():
12061    """Test write tiled volume using an image compressor."""
12062    data = random_data(numpy.uint8, (16, 64, 96, 3))
12063    with TempFileName('volumetric_tiled_png') as fname:
12064        imwrite(
12065            fname, data, tile=(1, 64, 64), photometric=RGB, compression=PNG
12066        )
12067        assert_valid_tiff(fname)
12068        with TiffFile(fname) as tif:
12069            assert len(tif.pages) == 1
12070            page = tif.pages[0]
12071            assert page.is_volumetric
12072            assert page.is_tiled
12073            assert page.compression == PNG
12074            assert not page.is_contiguous
12075            assert page.planarconfig == CONTIG
12076            assert page.photometric == RGB
12077            assert page.imagewidth == 96
12078            assert page.imagelength == 64
12079            assert page.imagedepth == 16
12080            assert page.tilewidth == 64
12081            assert page.tilelength == 64
12082            assert page.tiledepth == 1
12083            assert page.samplesperpixel == 3
12084            image = tif.asarray()
12085            assert_array_equal(data, image)
12086            assert_aszarr_method(tif, image)
12087            assert__str__(tif)
12088
12089
12090def test_write_volumetric_tiled_planar_rgb():
12091    """Test write 5D array as grayscale volumes."""
12092    shape = (2, 3, 256, 64, 96)
12093    data = numpy.empty(shape, dtype=numpy.uint8)
12094    data[:] = numpy.arange(256, dtype=numpy.uint8).reshape(1, 1, -1, 1, 1)
12095    with TempFileName('volumetric_tiled_planar_rgb') as fname:
12096        imwrite(
12097            fname,
12098            data,
12099            tile=(256, 64, 96),
12100            photometric=RGB,
12101            planarconfig=SEPARATE,
12102        )
12103        assert_valid_tiff(fname)
12104        with TiffFile(fname) as tif:
12105            assert len(tif.pages) == 2
12106            page = tif.pages[0]
12107            assert page.is_volumetric
12108            assert page.is_tiled
12109            assert page.is_contiguous
12110            assert page.planarconfig == SEPARATE
12111            assert page.photometric == RGB
12112            assert page.imagewidth == 96
12113            assert page.imagelength == 64
12114            assert page.imagedepth == 256
12115            assert page.tilewidth == 96
12116            assert page.tilelength == 64
12117            assert page.tiledepth == 256
12118            assert page.samplesperpixel == 3
12119            series = tif.series[0]
12120            assert len(series._pages) == 1
12121            assert len(series.pages) == 2
12122            assert series.offset is not None
12123            assert series.shape == shape
12124            image = tif.asarray()
12125            assert_array_equal(data, image)
12126            assert_aszarr_method(tif, image)
12127            assert__str__(tif)
12128
12129
12130def test_write_volumetric_tiled_contig_rgb():
12131    """Test write 6D array as contig RGB volumes."""
12132    shape = (2, 3, 256, 64, 96, 3)
12133    data = numpy.empty(shape, dtype=numpy.uint8)
12134    data[:] = numpy.arange(256, dtype=numpy.uint8).reshape(1, 1, -1, 1, 1, 1)
12135    with TempFileName('volumetric_tiled_contig_rgb') as fname:
12136        imwrite(fname, data, tile=(256, 64, 96), photometric=RGB)
12137        assert_valid_tiff(fname)
12138        with TiffFile(fname) as tif:
12139            assert len(tif.pages) == 6
12140            page = tif.pages[0]
12141            assert page.is_volumetric
12142            assert page.is_tiled
12143            assert page.is_contiguous
12144            assert page.planarconfig == CONTIG
12145            assert page.photometric == RGB
12146            assert page.imagewidth == 96
12147            assert page.imagelength == 64
12148            assert page.imagedepth == 256
12149            assert page.tilewidth == 96
12150            assert page.tilelength == 64
12151            assert page.tiledepth == 256
12152            assert page.samplesperpixel == 3
12153            # self.assertEqual(page.tags['TileOffsets'].value, (352,))
12154            assert page.tags['TileByteCounts'].value == (4718592,)
12155            series = tif.series[0]
12156            assert len(series._pages) == 1
12157            assert len(series.pages) == 6
12158            assert series.offset is not None
12159            assert series.shape == shape
12160            image = tif.asarray()
12161            assert_array_equal(data, image)
12162            # assert iterating over series.pages
12163            data = data.reshape(6, 256, 64, 96, 3)
12164            for i, page in enumerate(series.pages):
12165                image = page.asarray()
12166                assert_array_equal(data[i], image)
12167                assert_aszarr_method(page, image)
12168            assert__str__(tif)
12169
12170
12171@pytest.mark.skipif(SKIP_LARGE, reason=REASON)
12172def test_write_volumetric_tiled_contig_rgb_empty():
12173    """Test write empty 6D array as contig RGB volumes."""
12174    shape = (2, 3, 256, 64, 96, 3)
12175    with TempFileName('volumetric_tiled_contig_rgb_empty') as fname:
12176        with TiffWriter(fname) as tif:
12177            tif.write(
12178                shape=shape,
12179                dtype=numpy.uint8,
12180                tile=(256, 64, 96),
12181                photometric=RGB,
12182            )
12183        assert_valid_tiff(fname)
12184        with TiffFile(fname) as tif:
12185            assert len(tif.pages) == 6
12186            page = tif.pages[0]
12187            assert page.is_volumetric
12188            assert page.is_tiled
12189            assert page.is_contiguous
12190            assert page.planarconfig == CONTIG
12191            assert page.photometric == RGB
12192            assert page.imagewidth == 96
12193            assert page.imagelength == 64
12194            assert page.imagedepth == 256
12195            assert page.tilewidth == 96
12196            assert page.tilelength == 64
12197            assert page.tiledepth == 256
12198            assert page.samplesperpixel == 3
12199            # self.assertEqual(page.tags['TileOffsets'].value, (352,))
12200            assert page.tags['TileByteCounts'].value == (4718592,)
12201            series = tif.series[0]
12202            assert len(series._pages) == 1
12203            assert len(series.pages) == 6
12204            assert series.offset is not None
12205            assert series.shape == shape
12206            image = tif.asarray()
12207            assert_array_equal(image.shape, shape)
12208            assert_aszarr_method(tif, image)
12209            assert__str__(tif)
12210
12211
12212def test_write_volumetric_striped():
12213    """Test write striped volume."""
12214    data = random_data(numpy.uint8, (15, 63, 95))
12215    with TempFileName('volumetric_striped') as fname:
12216        imwrite(fname, data, volumetric=True)
12217        assert_valid_tiff(fname)
12218        with TiffFile(fname) as tif:
12219            assert len(tif.pages) == 1
12220            page = tif.pages[0]
12221            assert page.is_volumetric
12222            assert not page.is_tiled
12223            assert page.is_contiguous
12224            assert page.planarconfig == CONTIG
12225            assert page.photometric != RGB
12226            assert page.imagewidth == 95
12227            assert page.imagelength == 63
12228            assert page.imagedepth == 15
12229            assert len(page.dataoffsets) == 15
12230            assert len(page.databytecounts) == 15
12231            assert page.samplesperpixel == 1
12232            image = tif.asarray()
12233            assert_array_equal(data, image)
12234            assert_aszarr_method(tif, image)
12235            assert__str__(tif)
12236
12237
12238@pytest.mark.skipif(SKIP_CODECS, reason=REASON)
12239def test_write_volumetric_striped_png():
12240    """Test write tiled volume using an image compressor."""
12241    data = random_data(numpy.uint8, (15, 63, 95, 3))
12242    with TempFileName('volumetric_striped_png') as fname:
12243        imwrite(
12244            fname,
12245            data,
12246            photometric=RGB,
12247            volumetric=True,
12248            rowsperstrip=32,
12249            compression=PNG,
12250        )
12251        assert_valid_tiff(fname)
12252        with TiffFile(fname) as tif:
12253            assert len(tif.pages) == 1
12254            page = tif.pages[0]
12255            assert page.is_volumetric
12256            assert not page.is_tiled
12257            assert page.compression == PNG
12258            assert not page.is_contiguous
12259            assert page.planarconfig == CONTIG
12260            assert page.photometric == RGB
12261            assert page.imagewidth == 95
12262            assert page.imagelength == 63
12263            assert page.imagedepth == 15
12264            assert page.samplesperpixel == 3
12265            assert len(page.dataoffsets) == 30
12266            assert len(page.databytecounts) == 30
12267            image = tif.asarray()
12268            assert_array_equal(data, image)
12269            assert_aszarr_method(tif, image)
12270            assert_aszarr_method(tif, image, chunkmode='page')
12271            assert__str__(tif)
12272
12273
12274def test_write_volumetric_striped_planar_rgb():
12275    """Test write 5D array as grayscale volumes."""
12276    shape = (2, 3, 15, 63, 96)
12277    data = numpy.empty(shape, dtype=numpy.uint8)
12278    data[:] = numpy.arange(15, dtype=numpy.uint8).reshape(1, 1, -1, 1, 1)
12279    with TempFileName('volumetric_striped_planar_rgb') as fname:
12280        imwrite(fname, data, volumetric=True, photometric=RGB)
12281        assert_valid_tiff(fname)
12282        with TiffFile(fname) as tif:
12283            assert len(tif.pages) == 2
12284            page = tif.pages[0]
12285            assert page.is_volumetric
12286            assert not page.is_tiled
12287            assert page.is_contiguous
12288            assert page.planarconfig == SEPARATE
12289            assert page.photometric == RGB
12290            assert page.imagewidth == 96
12291            assert page.imagelength == 63
12292            assert page.imagedepth == 15
12293            assert page.samplesperpixel == 3
12294            assert len(page.dataoffsets) == 15 * 3
12295            assert len(page.databytecounts) == 15 * 3
12296            series = tif.series[0]
12297            assert len(series._pages) == 1
12298            assert len(series.pages) == 2
12299            assert series.offset is not None
12300            assert series.shape == shape
12301            image = tif.asarray()
12302            assert_array_equal(data, image)
12303            assert_aszarr_method(tif, image)
12304            assert__str__(tif)
12305
12306
12307def test_write_volumetric_striped_contig_rgb():
12308    """Test write 6D array as contig RGB volumes."""
12309    shape = (2, 3, 15, 63, 95, 3)
12310    data = numpy.empty(shape, dtype=numpy.uint8)
12311    data[:] = numpy.arange(15, dtype=numpy.uint8).reshape(1, 1, -1, 1, 1, 1)
12312    with TempFileName('volumetric_striped_contig_rgb') as fname:
12313        imwrite(fname, data, volumetric=True, photometric=RGB)
12314        assert_valid_tiff(fname)
12315        with TiffFile(fname) as tif:
12316            assert len(tif.pages) == 6
12317            page = tif.pages[0]
12318            assert page.is_volumetric
12319            assert not page.is_tiled
12320            assert page.is_contiguous
12321            assert page.planarconfig == CONTIG
12322            assert page.photometric == RGB
12323            assert page.imagewidth == 95
12324            assert page.imagelength == 63
12325            assert page.imagedepth == 15
12326            assert page.samplesperpixel == 3
12327            assert len(page.dataoffsets) == 15
12328            assert len(page.databytecounts) == 15
12329            series = tif.series[0]
12330            assert len(series._pages) == 1
12331            assert len(series.pages) == 6
12332            assert series.offset is not None
12333            assert series.shape == shape
12334            image = tif.asarray()
12335            assert_array_equal(data, image)
12336            # assert iterating over series.pages
12337            data = data.reshape(6, 15, 63, 95, 3)
12338            for i, page in enumerate(series.pages):
12339                image = page.asarray()
12340                assert_array_equal(data[i], image)
12341                assert_aszarr_method(page, image)
12342            assert__str__(tif)
12343
12344
12345@pytest.mark.skipif(SKIP_LARGE, reason=REASON)
12346def test_write_volumetric_striped_contig_rgb_empty():
12347    """Test write empty 6D array as contig RGB volumes."""
12348    shape = (2, 3, 15, 63, 95, 3)
12349    with TempFileName('volumetric_striped_contig_rgb_empty') as fname:
12350        with TiffWriter(fname) as tif:
12351            tif.write(
12352                shape=shape,
12353                dtype=numpy.uint8,
12354                volumetric=True,
12355                photometric=RGB,
12356            )
12357        assert_valid_tiff(fname)
12358        with TiffFile(fname) as tif:
12359            assert len(tif.pages) == 6
12360            page = tif.pages[0]
12361            assert page.is_volumetric
12362            assert not page.is_tiled
12363            assert page.is_contiguous
12364            assert page.planarconfig == CONTIG
12365            assert page.photometric == RGB
12366            assert page.imagewidth == 95
12367            assert page.imagelength == 63
12368            assert page.imagedepth == 15
12369            assert page.samplesperpixel == 3
12370            assert len(page.dataoffsets) == 15
12371            assert len(page.databytecounts) == 15
12372            series = tif.series[0]
12373            assert len(series._pages) == 1
12374            assert len(series.pages) == 6
12375            assert series.offset is not None
12376            assert series.shape == shape
12377            image = tif.asarray()
12378            assert_array_equal(image.shape, shape)
12379            assert_aszarr_method(tif, image)
12380            assert__str__(tif)
12381
12382
12383def test_write_contiguous():
12384    """Test contiguous mode."""
12385    data = random_data(numpy.uint8, (5, 4, 219, 301, 3))
12386    with TempFileName('write_contiguous') as fname:
12387        with TiffWriter(fname, bigtiff=True) as tif:
12388            for i in range(data.shape[0]):
12389                tif.write(data[i], contiguous=True, photometric=RGB)
12390        # assert_jhove(fname)
12391        with TiffFile(fname) as tif:
12392            assert tif.is_bigtiff
12393            assert len(tif.pages) == 20
12394            # check metadata is updated in-place
12395            assert tif.pages[0].tags[270].valueoffset < tif.pages[1].offset
12396            for page in tif.pages:
12397                assert page.is_contiguous
12398                assert page.planarconfig == CONTIG
12399                assert page.photometric == RGB
12400                assert page.imagewidth == 301
12401                assert page.imagelength == 219
12402                assert page.samplesperpixel == 3
12403            image = tif.asarray()
12404            assert_array_equal(data, image)
12405            assert_aszarr_method(tif, image)
12406            assert__str__(tif)
12407
12408
12409@pytest.mark.skipif(SKIP_LARGE, reason=REASON)
12410def test_write_3gb():
12411    """Test write 3 GB no-BigTiff file."""
12412    # https://github.com/blink1073/tifffile/issues/47
12413    data = numpy.empty((4096 - 32, 1024, 1024), dtype=numpy.uint8)
12414    with TempFileName('3gb', remove=False) as fname:
12415        imwrite(fname, data)
12416        del data
12417        assert_valid_tiff(fname)
12418        # assert file
12419        with TiffFile(fname) as tif:
12420            assert not tif.is_bigtiff
12421
12422
12423@pytest.mark.skipif(SKIP_LARGE, reason=REASON)
12424def test_write_bigtiff():
12425    """Test write 5GB BigTiff file."""
12426    data = numpy.empty((640, 1024, 1024), dtype=numpy.float64)
12427    data[:] = numpy.arange(640, dtype=numpy.float64).reshape(-1, 1, 1)
12428    with TempFileName('bigtiff') as fname:
12429        # TiffWriter should fail without bigtiff parameter
12430        with pytest.raises(ValueError):
12431            with TiffWriter(fname) as tif:
12432                tif.write(data)
12433        # imwrite should use bigtiff for large data
12434        imwrite(fname, data)
12435        # assert_jhove(fname)
12436        # assert file
12437        with TiffFile(fname) as tif:
12438            assert tif.is_bigtiff
12439            assert len(tif.pages) == 640
12440            page = tif.pages[0]
12441            assert page.is_contiguous
12442            assert page.planarconfig == CONTIG
12443            assert page.photometric != RGB
12444            assert page.imagewidth == 1024
12445            assert page.imagelength == 1024
12446            assert page.samplesperpixel == 1
12447            image = tif.asarray(out='memmap')
12448            assert_array_equal(data, image)
12449            del image
12450            del data
12451            assert__str__(tif)
12452
12453
12454@pytest.mark.parametrize('compression', [0, 6])
12455@pytest.mark.parametrize('dtype', [numpy.uint8, numpy.uint16])
12456def test_write_palette(dtype, compression):
12457    """Test write palette images."""
12458    dtype = numpy.dtype(dtype)
12459    data = random_data(dtype, (3, 219, 301))
12460    cmap = random_data(numpy.uint16, (3, 2 ** (data.itemsize * 8)))
12461    with TempFileName(f'palette_{compression}{dtype}') as fname:
12462        imwrite(
12463            fname,
12464            data,
12465            colormap=cmap,
12466            compression=(ADOBE_DEFLATE, compression)
12467            if compression
12468            else compression,
12469        )
12470        assert_valid_tiff(fname)
12471        with TiffFile(fname) as tif:
12472            assert len(tif.pages) == 3
12473            page = tif.pages[0]
12474            assert page.is_contiguous != bool(compression)
12475            assert page.planarconfig == CONTIG
12476            assert page.photometric == PALETTE
12477            assert page.imagewidth == 301
12478            assert page.imagelength == 219
12479            assert page.samplesperpixel == 1
12480            for i, page in enumerate(tif.pages):
12481                assert_array_equal(apply_colormap(data[i], cmap), page.asrgb())
12482            assert__str__(tif)
12483
12484
12485@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
12486def test_write_palette_django():
12487    """Test write palette read from existing file."""
12488    fname = private_file('django.tiff')
12489    with TiffFile(fname) as tif:
12490        page = tif.pages[0]
12491        assert page.photometric == PALETTE
12492        assert page.imagewidth == 320
12493        assert page.imagelength == 480
12494        data = page.asarray()  # .squeeze()  # UserWarning ...
12495        cmap = page.colormap
12496        assert__str__(tif)
12497    with TempFileName('palette_django') as fname:
12498        imwrite(fname, data, colormap=cmap, compression=ADOBE_DEFLATE)
12499        assert_valid_tiff(fname)
12500        with TiffFile(fname) as tif:
12501            assert len(tif.pages) == 1
12502            page = tif.pages[0]
12503            assert not page.is_contiguous
12504            assert page.planarconfig == CONTIG
12505            assert page.photometric == PALETTE
12506            assert page.imagewidth == 320
12507            assert page.imagelength == 480
12508            assert page.samplesperpixel == 1
12509            image = page.asrgb(uint8=False)
12510            assert_array_equal(apply_colormap(data, cmap), image)
12511            assert__str__(tif)
12512
12513
12514@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
12515def test_write_multiple_series():
12516    """Test write multiple data into one file using various options."""
12517    data1 = imread(private_file('ome/multi-channel-4D-series.ome.tif'))
12518    image1 = imread(private_file('django.tiff'))
12519    image2 = imread(private_file('horse-16bit-col-littleendian.tif'))
12520    with TempFileName('multiple_series') as fname:
12521        with TiffWriter(fname, bigtiff=False) as tif:
12522            # series 0
12523            tif.write(
12524                image1, compression=(ADOBE_DEFLATE, 5), description='Django'
12525            )
12526            # series 1
12527            tif.write(image2, photometric=RGB)
12528            # series 2
12529            tif.write(data1[0], metadata=dict(axes='TCZYX'))
12530            for i in range(1, data1.shape[0]):
12531                tif.write(data1[i], contiguous=True)
12532            # series 3
12533            tif.write(data1[0], contiguous=False)
12534            # series 4
12535            tif.write(data1[0, 0, 0], tile=(64, 64))
12536            # series 5
12537            tif.write(image1, compression=ADOBE_DEFLATE, description='DEFLATE')
12538        assert_valid_tiff(fname)
12539        with TiffFile(fname) as tif:
12540            assert len(tif.pages) == 124
12541            assert len(tif.series) == 6
12542            serie = tif.series[0]
12543            assert not serie.offset
12544            assert serie.axes == 'YX'
12545            assert_array_equal(image1, serie.asarray())
12546            assert_aszarr_method(serie, image1)
12547            serie = tif.series[1]
12548            assert serie.offset
12549            assert serie.axes == 'YXS'
12550            assert_array_equal(image2, serie.asarray())
12551            assert_aszarr_method(serie, image2)
12552            serie = tif.series[2]
12553            assert serie.offset
12554            assert serie.pages[0].is_contiguous
12555            assert serie.axes == 'TCZYX'
12556            result = serie.asarray(out='memmap')
12557            assert_array_equal(data1, result)
12558            assert_aszarr_method(serie, data1)
12559            assert tif.filehandle.path == result.filename
12560            del result
12561            serie = tif.series[3]
12562            assert serie.offset
12563            assert serie.axes == 'QQYX'
12564            assert_array_equal(data1[0], serie.asarray())
12565            assert_aszarr_method(serie, data1[0])
12566            serie = tif.series[4]
12567            assert not serie.offset
12568            assert serie.axes == 'YX'
12569            assert_array_equal(data1[0, 0, 0], serie.asarray())
12570            assert_aszarr_method(serie, data1[0, 0, 0])
12571            serie = tif.series[5]
12572            assert not serie.offset
12573            assert serie.axes == 'YX'
12574            assert_array_equal(image1, serie.asarray())
12575            assert_aszarr_method(serie, image1)
12576            assert__str__(tif)
12577
12578            # test TiffFile.asarray key and series parameters
12579            assert_array_equal(image1, tif.asarray(key=0))
12580            assert_array_equal(image1, tif.asarray(key=-1))
12581
12582            assert_array_equal(image2, tif.asarray(key=[1]))
12583            assert_array_equal(image2, tif.asarray(key=0, series=1))
12584            assert_array_equal(
12585                image2, tif.asarray(key=0, series=tif.series[1])
12586            )
12587
12588            assert_array_equal(
12589                data1, tif.asarray(key=range(2, 107)).reshape(data1.shape)
12590            )
12591
12592            assert_array_equal(
12593                data1,
12594                tif.asarray(key=range(105), series=2).reshape(data1.shape),
12595            )
12596
12597            assert_array_equal(
12598                data1,
12599                tif.asarray(key=slice(None), series=2).reshape(data1.shape),
12600            )
12601
12602            assert_array_equal(
12603                data1[0],
12604                tif.asarray(key=slice(107, 122)).reshape(data1[0].shape),
12605            )
12606
12607            assert_array_equal(
12608                data1[0].reshape(-1, 167, 439)[::2],
12609                tif.asarray(key=slice(107, 122, 2)).reshape((-1, 167, 439)),
12610            )
12611
12612            with pytest.raises(RuntimeError):
12613                tif.asarray(key=[0, 1])
12614
12615            with pytest.raises(RuntimeError):
12616                tif.asarray(key=[-3, -2])
12617
12618        assert_array_equal(image1, imread(fname, key=0))
12619        assert_array_equal(image1, imread(fname, key=-1))
12620        assert_array_equal(image2, imread(fname, key=[1]))
12621        assert_array_equal(
12622            data1, imread(fname, key=range(2, 107)).reshape(data1.shape)
12623        )
12624        assert_array_equal(
12625            data1, imread(fname, key=range(105), series=2).reshape(data1.shape)
12626        )
12627        assert_array_equal(
12628            data1[0],
12629            imread(fname, key=slice(107, 122)).reshape(data1[0].shape),
12630        )
12631
12632
12633def assert_fsspec(url, data, target_protocol='http'):
12634    """Assert fsspec ReferenceFileSystem from local http server."""
12635    mapper = fsspec.get_mapper(
12636        'reference://', fo=url, target_protocol=target_protocol
12637    )
12638    zobj = zarr.open(mapper, mode='r')
12639    if isinstance(zobj, zarr.Group):
12640        assert_array_equal(zobj[0][:], data)
12641        assert_array_equal(zobj[1][:], data[:, ::2, ::2])
12642        assert_array_equal(zobj[2][:], data[:, ::4, ::4])
12643    else:
12644        assert_array_equal(zobj[:], data)
12645
12646
12647@pytest.mark.skipif(
12648    SKIP_HTTP or SKIP_ZARR or SKIP_CODECS or not imagecodecs.JPEG,
12649    reason=REASON,
12650)
12651@pytest.mark.parametrize('version', [0, 1])
12652def test_write_fsspec(version):
12653    """Test write fsspec for multi-series OME-TIFF."""
12654    data0 = random_data(numpy.uint8, (3, 252, 244))
12655    data1 = random_data(numpy.uint8, (219, 301, 3))
12656    data2 = random_data(numpy.uint16, (3, 219, 301))
12657
12658    with TempFileName('write_fsspec', ext='.ome.tif') as fname:
12659        filename = os.path.split(fname)[-1]
12660        with TiffWriter(fname, ome=True, byteorder='>') as tif:
12661            # series 0
12662            options = dict(
12663                tile=(64, 64), photometric=MINISBLACK, compression=DEFLATE
12664            )
12665            tif.write(data0, subifds=2, **options)
12666            tif.write(data0[:, ::2, ::2], subfiletype=1, **options)
12667            tif.write(data0[:, ::4, ::4], subfiletype=1, **options)
12668            # series 1
12669            tif.write(data1, photometric=RGB, rowsperstrip=data1.shape[0])
12670            # series 2
12671            tif.write(
12672                data2,
12673                rowsperstrip=data1.shape[1],
12674                photometric=RGB,
12675                planarconfig=SEPARATE,
12676            )
12677            # series 3
12678            tif.write(data1, photometric=RGB, rowsperstrip=5)
12679            # series 4
12680            tif.write(data1, photometric=RGB, tile=(32, 32), compression=JPEG)
12681
12682        with TiffFile(fname) as tif:
12683            assert tif.is_ome
12684            assert len(tif.series) == 5
12685
12686            with tif.series[0].aszarr() as store:
12687                assert store.is_multiscales
12688                store.write_fsspec(
12689                    fname + f'.v{version}.s0.json', URL, version=version
12690                )
12691                assert_fsspec(URL + filename + f'.v{version}.s0.json', data0)
12692
12693            with tif.series[1].aszarr() as store:
12694                assert not store.is_multiscales
12695                store.write_fsspec(
12696                    fname + f'.v{version}.s1.json', URL, version=version
12697                )
12698                assert_fsspec(URL + filename + f'.v{version}.s1.json', data1)
12699
12700            with tif.series[2].aszarr() as store:
12701                store.write_fsspec(
12702                    fname + f'.v{version}.s2.json', URL, version=version
12703                )
12704                assert_fsspec(URL + filename + f'.v{version}.s2.json', data2)
12705
12706            with tif.series[3].aszarr(chunkmode=2) as store:
12707                store.write_fsspec(
12708                    fname + f'.v{version}.s3.json', URL, version=version
12709                )
12710                assert_fsspec(URL + filename + f'.v{version}.s3.json', data1)
12711
12712            with tif.series[3].aszarr() as store:
12713                with pytest.raises(ValueError):
12714                    # imagelength % rowsperstrip != 0
12715                    store.write_fsspec(
12716                        fname + f'.v{version}.s3fail.json',
12717                        URL,
12718                        version=version,
12719                    )
12720
12721            with tif.series[4].aszarr() as store:
12722                store.write_fsspec(
12723                    fname + f'.v{version}.s4.json', URL, version=version
12724                )
12725                if version == 0:
12726                    with pytest.raises(ValueError):
12727                        # codec not available: 'imagecodecs_jpeg'
12728                        assert_fsspec(
12729                            URL + filename + f'.v{version}.s4.json', data1
12730                        )
12731                try:
12732                    from imagecodecs.numcodecs import register_codecs
12733                except ImportError:
12734                    pass
12735                else:
12736                    register_codecs('imagecodecs_jpeg')
12737                    assert_fsspec(
12738                        URL + filename + f'.v{version}.s4.json',
12739                        tif.series[4].asarray(),
12740                    )
12741
12742
12743@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE or SKIP_CODECS, reason=REASON)
12744@pytest.mark.parametrize('version', [1])  # 0,
12745def test_write_fsspec_sequence(version):
12746    """Test write fsspec for multi-file sequence."""
12747    # https://bbbc.broadinstitute.org/BBBC006
12748    ptrn = r'(?:_(z)_(\d+)).*_(?P<p>[a-z])(?P<a>\d+)(?:_(s)(\d))(?:_(w)(\d))'
12749    fnames = private_file('BBBC/BBBC006_v1_images_z_00/*.tif')
12750    fnames += private_file('BBBC/BBBC006_v1_images_z_01/*.tif')
12751    tifs = TiffSequence(
12752        fnames,
12753        imread=imagecodecs.imread,
12754        pattern=ptrn,
12755        axesorder=(1, 2, 0, 3, 4),
12756    )
12757    assert len(tifs) == 3072
12758    assert tifs.shape == (16, 24, 2, 2, 2)
12759    assert tifs.axes == 'PAZSW'
12760    data = tifs.asarray()
12761    with TempFileName(
12762        'write_fsspec_sequence', ext=f'.v{version}.json'
12763    ) as fname:
12764        with tifs.aszarr(codec=imagecodecs.tiff_decode) as store:
12765            store.write_fsspec(
12766                fname,
12767                'file:///' + store._commonpath.replace('\\', '/'),
12768                version=version,
12769            )
12770        mapper = fsspec.get_mapper(
12771            'reference://', fo=fname, target_protocol='file'
12772        )
12773
12774        from imagecodecs.numcodecs import register_codecs
12775
12776        register_codecs()
12777
12778        za = zarr.open(mapper, mode='r')
12779        assert_array_equal(za[:], data)
12780
12781
12782@pytest.mark.skipif(SKIP_ZARR, reason=REASON)
12783def test_write_numcodecs():
12784    """Test write zarr with numcodecs.Tiff."""
12785    from tifffile import numcodecs
12786
12787    data = numpy.arange(256 * 256 * 3, dtype=numpy.uint16).reshape(256, 256, 3)
12788    numcodecs.register_codec()
12789    compressor = numcodecs.Tiff(
12790        bigtiff=True,
12791        photometric=MINISBLACK,
12792        planarconfig=CONTIG,
12793        compression=(ADOBE_DEFLATE, 5),
12794        key=0,
12795    )
12796    with TempFileName('write_numcodecs', ext='.zarr') as fname:
12797        z = zarr.open(
12798            fname,
12799            mode='w',
12800            shape=(256, 256, 3),
12801            chunks=(100, 100, 3),
12802            dtype=numpy.uint16,
12803            compressor=compressor,
12804        )
12805        z[:] = data
12806        assert_array_equal(z[:], data)
12807
12808
12809###############################################################################
12810
12811# Test ImageJ writing
12812
12813
12814@pytest.mark.skipif(SKIP_EXTENDED, reason=REASON)
12815@pytest.mark.parametrize(
12816    'shape',
12817    [
12818        (219, 301, 1),
12819        (219, 301, 2),
12820        (219, 301, 3),
12821        (219, 301, 4),
12822        (219, 301, 5),
12823        (1, 219, 301),
12824        (2, 219, 301),
12825        (3, 219, 301),
12826        (4, 219, 301),
12827        (5, 219, 301),
12828        (4, 3, 219, 301),
12829        (4, 219, 301, 3),
12830        (3, 4, 219, 301),
12831        (1, 3, 1, 219, 301),
12832        (3, 1, 1, 219, 301),
12833        (1, 3, 4, 219, 301),
12834        (3, 1, 4, 219, 301),
12835        (3, 4, 1, 219, 301),
12836        (3, 4, 1, 219, 301, 3),
12837        (2, 3, 4, 219, 301),
12838        (4, 3, 2, 219, 301, 3),
12839    ],
12840)
12841@pytest.mark.parametrize(
12842    'dtype', [numpy.uint8, numpy.uint16, numpy.int16, numpy.float32]
12843)
12844@pytest.mark.parametrize('byteorder', ['>', '<'])
12845def test_write_imagej(byteorder, dtype, shape):
12846    """Test write ImageJ format."""
12847    # TODO: test compression and bigtiff ?
12848    dtype = numpy.dtype(dtype)
12849    if dtype != numpy.uint8 and shape[-1] in (3, 4):
12850        pytest.xfail('ImageJ only supports uint8 RGB')
12851    data = random_data(dtype, shape)
12852    fname = 'imagej_{}_{}_{}'.format(
12853        {'<': 'le', '>': 'be'}[byteorder], dtype, str(shape).replace(' ', '')
12854    )
12855    with TempFileName(fname) as fname:
12856        imwrite(fname, data, byteorder=byteorder, imagej=True)
12857        image = imread(fname)
12858        assert_array_equal(data.squeeze(), image.squeeze())
12859        # TODO: assert_aszarr_method
12860        assert_valid_tiff(fname)
12861
12862
12863def test_write_imagej_voxel_size():
12864    """Test write ImageJ with xyz voxel size 2.6755x2.6755x3.9474 µm^3."""
12865    data = numpy.zeros((4, 256, 256), dtype=numpy.float32)
12866    data.shape = 4, 1, 256, 256
12867    with TempFileName('imagej_voxel_size') as fname:
12868        imwrite(
12869            fname,
12870            data,
12871            imagej=True,
12872            resolution=(0.373759, 0.373759),
12873            metadata={'spacing': 3.947368, 'unit': 'um'},
12874        )
12875        with TiffFile(fname) as tif:
12876            assert tif.is_imagej
12877            assert 'unit' in tif.imagej_metadata
12878            assert tif.imagej_metadata['unit'] == 'um'
12879            series = tif.series[0]
12880            assert series.axes == 'ZYX'
12881            assert series.shape == (4, 256, 256)
12882            assert series.get_axes(False) == 'TZCYXS'
12883            assert series.get_shape(False) == (1, 4, 1, 256, 256, 1)
12884            assert__str__(tif)
12885        assert_valid_tiff(fname)
12886
12887
12888def test_write_imagej_metadata():
12889    """Test write additional ImageJ metadata."""
12890    data = numpy.empty((4, 256, 256), dtype=numpy.uint16)
12891    data[:] = numpy.arange(256 * 256, dtype=numpy.uint16).reshape(1, 256, 256)
12892    with TempFileName('imagej_metadata') as fname:
12893        imwrite(fname, data, imagej=True, metadata={'unit': 'um'})
12894        with TiffFile(fname) as tif:
12895            assert tif.is_imagej
12896            assert 'unit' in tif.imagej_metadata
12897            assert tif.imagej_metadata['unit'] == 'um'
12898            assert__str__(tif)
12899        assert_valid_tiff(fname)
12900
12901
12902@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
12903def test_write_imagej_ijmetadata_tag():
12904    """Test write and read IJMetadata tag."""
12905    fname = private_file('imagej/IJMetadata.tif')
12906    with TiffFile(fname) as tif:
12907        assert tif.is_imagej
12908        assert tif.byteorder == '>'
12909        assert len(tif.pages) == 3
12910        assert len(tif.series) == 1
12911        data = tif.asarray()
12912        ijmetadata = tif.pages[0].tags['IJMetadata'].value
12913
12914    assert ijmetadata['Info'][:21] == 'FluorescentCells.tif\n'
12915    assert ijmetadata['ROI'][:5] == b'Iout\x00'
12916    assert ijmetadata['Overlays'][1][:5] == b'Iout\x00'
12917    assert ijmetadata['Ranges'] == (0.0, 255.0, 0.0, 255.0, 0.0, 255.0)
12918    assert ijmetadata['Labels'] == ['Red', 'Green', 'Blue']
12919    assert ijmetadata['LUTs'][2][2, 255] == 255
12920    assert_valid_tiff(fname)
12921
12922    with TempFileName('imagej_ijmetadata') as fname:
12923        with pytest.warns(DeprecationWarning):
12924            imwrite(
12925                fname,
12926                data,
12927                byteorder='>',
12928                imagej=True,
12929                metadata={'mode': 'composite'},
12930                ijmetadata=ijmetadata,
12931            )
12932
12933        imwrite(
12934            fname,
12935            data,
12936            byteorder='>',
12937            imagej=True,
12938            metadata={**ijmetadata, 'mode': 'composite'},
12939        )
12940        with TiffFile(fname) as tif:
12941            assert tif.is_imagej
12942            assert tif.byteorder == '>'
12943            assert len(tif.pages) == 3
12944            assert len(tif.series) == 1
12945            imagej_metadata = tif.imagej_metadata
12946            data2 = tif.asarray()
12947            ijmetadata2 = tif.pages[0].tags['IJMetadata'].value
12948
12949            assert__str__(tif)
12950
12951    assert_array_equal(data, data2)
12952    assert imagej_metadata['mode'] == 'composite'
12953    assert imagej_metadata['Info'] == ijmetadata['Info']
12954    assert ijmetadata2['Info'] == ijmetadata['Info']
12955    assert ijmetadata2['ROI'] == ijmetadata['ROI']
12956    assert ijmetadata2['Overlays'] == ijmetadata['Overlays']
12957    assert ijmetadata2['Ranges'] == ijmetadata['Ranges']
12958    assert ijmetadata2['Labels'] == ijmetadata['Labels']
12959    assert_array_equal(ijmetadata2['LUTs'][2], ijmetadata['LUTs'][2])
12960    assert_valid_tiff(fname)
12961
12962
12963@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
12964def test_write_imagej_roundtrip():
12965    """Test ImageJ metadata survive read/write roundtrip."""
12966    fname = private_file('imagej/IJMetadata.tif')
12967    with TiffFile(fname) as tif:
12968        assert tif.is_imagej
12969        assert tif.byteorder == '>'
12970        assert len(tif.pages) == 3
12971        assert len(tif.series) == 1
12972        data = tif.asarray()
12973        ijmetadata = tif.imagej_metadata
12974
12975    assert ijmetadata['Info'][:21] == 'FluorescentCells.tif\n'
12976    assert ijmetadata['ROI'][:5] == b'Iout\x00'
12977    assert ijmetadata['Overlays'][1][:5] == b'Iout\x00'
12978    assert ijmetadata['Ranges'] == (0.0, 255.0, 0.0, 255.0, 0.0, 255.0)
12979    assert ijmetadata['Labels'] == ['Red', 'Green', 'Blue']
12980    assert ijmetadata['LUTs'][2][2, 255] == 255
12981    assert ijmetadata['mode'] == 'composite'
12982    assert not ijmetadata['loop']
12983    assert ijmetadata['ImageJ'] == '1.52b'
12984    assert_valid_tiff(fname)
12985
12986    with TempFileName('imagej_ijmetadata_roundtrip') as fname:
12987
12988        imwrite(fname, data, byteorder='>', imagej=True, metadata=ijmetadata)
12989
12990        with TiffFile(fname) as tif:
12991            assert tif.is_imagej
12992            assert tif.byteorder == '>'
12993            assert len(tif.pages) == 3
12994            assert len(tif.series) == 1
12995            ijmetadata2 = tif.imagej_metadata
12996            data2 = tif.asarray()
12997            assert__str__(tif)
12998
12999    assert_array_equal(data, data2)
13000    assert ijmetadata2['ImageJ'] == ijmetadata['ImageJ']
13001    assert ijmetadata2['mode'] == ijmetadata['mode']
13002    assert ijmetadata2['Info'] == ijmetadata['Info']
13003    assert ijmetadata2['ROI'] == ijmetadata['ROI']
13004    assert ijmetadata2['Overlays'] == ijmetadata['Overlays']
13005    assert ijmetadata2['Ranges'] == ijmetadata['Ranges']
13006    assert ijmetadata2['Labels'] == ijmetadata['Labels']
13007    assert_array_equal(ijmetadata2['LUTs'][2], ijmetadata['LUTs'][2])
13008    assert_valid_tiff(fname)
13009
13010
13011@pytest.mark.parametrize('mmap', [False, True])
13012@pytest.mark.parametrize('truncate', [False, True])
13013def test_write_imagej_hyperstack(truncate, mmap):
13014    """Test write ImageJ hyperstack."""
13015    shape = (5, 6, 7, 49, 61, 3)
13016    data = numpy.empty(shape, dtype=numpy.uint8)
13017    data[:] = numpy.arange(210, dtype=numpy.uint8).reshape(5, 6, 7, 1, 1, 1)
13018
13019    _truncate = ['', '_trunc'][truncate]
13020    _memmap = ['', '_memmap'][mmap]
13021    with TempFileName(f'imagej_hyperstack{_truncate}{_memmap}') as fname:
13022        if mmap:
13023            image = memmap(
13024                fname,
13025                shape=data.shape,
13026                dtype=data.dtype,
13027                imagej=True,
13028                truncate=truncate,
13029            )
13030            image[:] = data
13031            del image
13032        else:
13033            imwrite(fname, data, truncate=truncate, imagej=True)
13034        # assert file
13035        with TiffFile(fname) as tif:
13036            assert not tif.is_bigtiff
13037            assert not tif.is_shaped
13038            assert len(tif.pages) == 1 if truncate else 210
13039            page = tif.pages[0]
13040            assert page.is_contiguous
13041            assert page.planarconfig == CONTIG
13042            assert page.photometric == RGB
13043            assert page.imagewidth == 61
13044            assert page.imagelength == 49
13045            assert page.samplesperpixel == 3
13046            # assert series properties
13047            series = tif.series[0]
13048            assert series.shape == shape
13049            assert len(series._pages) == 1
13050            assert len(series.pages) == 1 if truncate else 210
13051            assert series.dtype == numpy.uint8
13052            assert series.axes == 'TZCYXS'
13053            assert series.get_axes(False) == 'TZCYXS'
13054            assert series.get_shape(False) == shape
13055            # assert data
13056            image = tif.asarray(out='memmap')
13057            assert_array_equal(data.squeeze(), image.squeeze())
13058            del image
13059            # assert iterating over series.pages
13060            data = data.reshape(210, 49, 61, 3)
13061            for i, page in enumerate(series.pages):
13062                image = page.asarray()
13063                assert_array_equal(data[i], image)
13064            del image
13065            assert__str__(tif)
13066        assert_valid_tiff(fname)
13067
13068
13069def test_write_imagej_append():
13070    """Test write ImageJ file consecutively."""
13071    data = numpy.empty((256, 1, 256, 256), dtype=numpy.uint8)
13072    data[:] = numpy.arange(256, dtype=numpy.uint8).reshape(-1, 1, 1, 1)
13073
13074    with TempFileName('imagej_append') as fname:
13075        with TiffWriter(fname, imagej=True) as tif:
13076            for image in data:
13077                tif.write(image, contiguous=True)
13078
13079        assert_valid_tiff(fname)
13080
13081        # assert file
13082        with TiffFile(fname) as tif:
13083            assert not tif.is_bigtiff
13084            assert not tif.is_shaped
13085            assert len(tif.pages) == 256
13086            page = tif.pages[0]
13087            assert page.is_contiguous
13088            assert page.planarconfig == CONTIG
13089            assert page.photometric != RGB
13090            assert page.imagewidth == 256
13091            assert page.imagelength == 256
13092            assert page.samplesperpixel == 1
13093            # assert series properties
13094            series = tif.series[0]
13095            assert series.shape == (256, 256, 256)
13096            assert series.dtype == numpy.uint8
13097            assert series.axes == 'ZYX'
13098            assert series.get_axes(False) == 'TZCYXS'
13099            assert series.get_shape(False) == (1, 256, 1, 256, 256, 1)
13100            # assert data
13101            image = tif.asarray(out='memmap')
13102            assert_array_equal(data.squeeze(), image)
13103            del image
13104            assert__str__(tif)
13105
13106
13107@pytest.mark.skipif(SKIP_LARGE, reason=REASON)
13108def test_write_imagej_raw():
13109    """Test write ImageJ 5 GB raw file."""
13110    data = numpy.empty((1280, 1, 1024, 1024), dtype=numpy.float32)
13111    data[:] = numpy.arange(1280, dtype=numpy.float32).reshape(-1, 1, 1, 1)
13112
13113    with TempFileName('imagej_big') as fname:
13114        with pytest.warns(UserWarning):
13115            # UserWarning: truncating ImageJ file
13116            imwrite(fname, data, imagej=True)
13117        assert_valid_tiff(fname)
13118        # assert file
13119        with TiffFile(fname) as tif:
13120            assert not tif.is_bigtiff
13121            assert not tif.is_shaped
13122            assert len(tif.pages) == 1
13123            page = tif.pages[0]
13124            assert page.is_contiguous
13125            assert page.planarconfig == CONTIG
13126            assert page.photometric != RGB
13127            assert page.imagewidth == 1024
13128            assert page.imagelength == 1024
13129            assert page.samplesperpixel == 1
13130            # assert series properties
13131            series = tif.series[0]
13132            assert len(series._pages) == 1
13133            assert len(series.pages) == 1
13134            assert series.shape == (1280, 1024, 1024)
13135            assert series.dtype == numpy.float32
13136            assert series.axes == 'ZYX'
13137            assert series.get_axes(False) == 'TZCYXS'
13138            assert series.get_shape(False) == (1, 1280, 1, 1024, 1024, 1)
13139            # assert data
13140            image = tif.asarray(out='memmap')
13141            assert_array_equal(data.squeeze(), image.squeeze())
13142            del image
13143            assert__str__(tif)
13144
13145
13146@pytest.mark.skipif(SKIP_EXTENDED, reason=REASON)
13147@pytest.mark.parametrize(
13148    'shape, axes',
13149    [
13150        ((219, 301, 1), None),
13151        ((219, 301, 2), None),
13152        ((219, 301, 3), None),
13153        ((219, 301, 4), None),
13154        ((219, 301, 5), None),
13155        ((1, 219, 301), None),
13156        ((2, 219, 301), None),
13157        ((3, 219, 301), None),
13158        ((4, 219, 301), None),
13159        ((5, 219, 301), None),
13160        ((4, 3, 219, 301), None),
13161        ((4, 219, 301, 3), None),
13162        ((3, 4, 219, 301), None),
13163        ((1, 3, 1, 219, 301), None),
13164        ((3, 1, 1, 219, 301), None),
13165        ((1, 3, 4, 219, 301), None),
13166        ((3, 1, 4, 219, 301), None),
13167        ((3, 4, 1, 219, 301), None),
13168        ((3, 4, 1, 219, 301, 3), None),
13169        ((2, 3, 4, 219, 301), None),
13170        ((4, 3, 2, 219, 301, 3), None),
13171        ((5, 1, 32, 32), 'CSYX'),
13172        ((5, 1, 32, 32), 'ZCYX'),
13173        ((2, 3, 4, 219, 301, 3), 'TCZYXS'),
13174        ((10, 5, 200, 200), 'EPYX'),
13175        ((2, 3, 4, 5, 6, 7, 32, 32, 3), 'TQCPZRYXS'),
13176    ],
13177)
13178def test_write_ome(shape, axes):
13179    """Test write OME-TIFF format."""
13180    photometric = None
13181    planarconfig = None
13182    if shape[-1] in (3, 4):
13183        photometric = RGB
13184        planarconfig = CONTIG
13185    elif shape[-3] in (3, 4):
13186        photometric = RGB
13187        planarconfig = SEPARATE
13188
13189    metadata = {'axes': axes} if axes is not None else {}
13190    data = random_data(numpy.uint8, shape)
13191    fname = 'write_ome_{}.ome'.format(str(shape).replace(' ', ''))
13192    with TempFileName(fname) as fname:
13193        imwrite(
13194            fname,
13195            data,
13196            metadata=metadata,
13197            photometric=photometric,
13198            planarconfig=planarconfig,
13199        )
13200        with TiffFile(fname) as tif:
13201            assert tif.is_ome
13202            assert not tif.is_shaped
13203            image = tif.asarray()
13204            omexml = tif.ome_metadata
13205            if axes:
13206                assert tif.series[0].axes == squeeze_axes(shape, axes)[-1]
13207            assert_array_equal(data.squeeze(), image.squeeze())
13208            assert_aszarr_method(tif, image)
13209            assert_valid_omexml(omexml)
13210        assert_valid_tiff(fname)
13211
13212
13213def test_write_ome_enable():
13214    """Test OME-TIFF enabling."""
13215    data = numpy.zeros((32, 32), dtype=numpy.uint8)
13216    with TempFileName('write_ome_enable.ome') as fname:
13217        imwrite(fname, data)
13218        with TiffFile(fname) as tif:
13219            assert tif.is_ome
13220        imwrite(fname, data, description='not OME')
13221        with TiffFile(fname) as tif:
13222            assert not tif.is_ome
13223        with pytest.warns(UserWarning):
13224            imwrite(fname, data, description='not OME', ome=True)
13225        with TiffFile(fname) as tif:
13226            assert tif.is_ome
13227        imwrite(fname, data, imagej=True)
13228        with TiffFile(fname) as tif:
13229            assert not tif.is_ome
13230            assert tif.is_imagej
13231        imwrite(fname, data, imagej=True, ome=True)
13232        with TiffFile(fname) as tif:
13233            assert tif.is_ome
13234            assert not tif.is_imagej
13235
13236    with TempFileName('write_ome_auto.tif') as fname:
13237        imwrite(fname, data)
13238        with TiffFile(fname) as tif:
13239            assert not tif.is_ome
13240        imwrite(fname, data, ome=True)
13241        with TiffFile(fname) as tif:
13242            assert tif.is_ome
13243
13244
13245@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13246@pytest.mark.parametrize(
13247    'method', ['manual', 'copy', 'iter', 'compression', 'xml']
13248)
13249def test_write_ome_methods(method):
13250    """Test re-write OME-TIFF."""
13251    # 4D (7 time points, 5 focal planes)
13252    fname = public_file('OME/bioformats-artificial/4D-series.ome.tiff')
13253    with TiffFile(fname) as tif:
13254        series = tif.series[0]
13255        data = series.asarray()
13256        dtype = data.dtype
13257        shape = data.shape
13258        axes = series.axes
13259        omexml = tif.ome_metadata
13260
13261    def pages():
13262        for image in data.reshape(-1, *data.shape[-2:]):
13263            yield image
13264
13265    with TempFileName(f'write_ome_{method}.ome') as fname:
13266
13267        if method == 'xml':
13268            # use original XML metadata
13269            metadata = xml2dict(omexml)
13270            metadata['axes'] = axes
13271            imwrite(
13272                fname,
13273                data,
13274                byteorder='>',
13275                photometric=MINISBLACK,
13276                metadata=metadata,
13277            )
13278
13279        elif method == 'manual':
13280            # manually write omexml to first page and data to individual pages
13281            # process OME-XML
13282            omexml = omexml.replace(
13283                '4D-series.ome.tiff', os.path.split(fname)[-1]
13284            )
13285            # omexml = omexml.replace('BigEndian="true"', 'BigEndian="false"')
13286            data = data.newbyteorder('>')
13287            # save image planes in the order referenced in the OME-XML
13288            # make sure storage options (compression, byteorder, photometric)
13289            #   match OME-XML
13290            # write OME-XML to first page only
13291            with TiffWriter(fname, byteorder='>') as tif:
13292                for i, image in enumerate(pages()):
13293                    description = omexml if i == 0 else None
13294                    tif.write(
13295                        image,
13296                        description=description,
13297                        photometric=MINISBLACK,
13298                        metadata=None,
13299                        contiguous=False,
13300                    )
13301
13302        elif method == 'iter':
13303            # use iterator over individual pages
13304            imwrite(
13305                fname,
13306                pages(),
13307                shape=shape,
13308                dtype=dtype,
13309                byteorder='>',
13310                photometric=MINISBLACK,
13311                metadata={'axes': axes},
13312            )
13313
13314        elif method == 'compression':
13315            # use iterator with compression
13316            imwrite(
13317                fname,
13318                pages(),
13319                shape=shape,
13320                dtype=dtype,
13321                compression=ADOBE_DEFLATE,
13322                byteorder='>',
13323                photometric=MINISBLACK,
13324                metadata={'axes': axes},
13325            )
13326
13327        elif method == 'copy':
13328            # use one numpy array
13329            imwrite(
13330                fname,
13331                data,
13332                byteorder='>',
13333                photometric=MINISBLACK,
13334                metadata={'axes': axes},
13335            )
13336
13337        with TiffFile(fname) as tif:
13338            assert tif.is_ome
13339            assert tif.byteorder == '>'
13340            assert len(tif.pages) == 35
13341            assert len(tif.series) == 1
13342            # assert page properties
13343            page = tif.pages[0]
13344            if method != 'compression':
13345                assert page.is_contiguous
13346                assert page.compression == NONE
13347            assert page.imagewidth == 439
13348            assert page.imagelength == 167
13349            assert page.bitspersample == 8
13350            assert page.samplesperpixel == 1
13351            # assert series properties
13352            series = tif.series[0]
13353            assert series.shape == (7, 5, 167, 439)
13354            assert series.dtype == numpy.int8
13355            assert series.axes == 'TZYX'
13356            # assert data
13357            assert_array_equal(data, tif.asarray())
13358            assert_valid_omexml(tif.ome_metadata)
13359            assert__str__(tif)
13360
13361        assert_valid_tiff(fname)
13362
13363
13364@pytest.mark.parametrize('contiguous', [True, False])
13365def test_write_ome_manual(contiguous):
13366    """Test writing OME-TIFF manually."""
13367    data = numpy.random.randint(0, 255, (19, 31, 21), numpy.uint8)
13368
13369    with TempFileName(f'write_ome__manual{int(contiguous)}.ome') as fname:
13370
13371        with TiffWriter(fname) as tif:
13372            # sucessively write image data to TIFF pages
13373            # disable tifffile from writing any metadata
13374            # add empty ImageDescription tag to first page
13375            for i, frame in enumerate(data):
13376                tif.write(
13377                    frame,
13378                    contiguous=contiguous,
13379                    metadata=None,
13380                    description=None if i else b'',
13381                )
13382            # update ImageDescription tag with custom OME-XML
13383            xml = OmeXml()
13384            xml.addimage(
13385                numpy.uint8, (16, 31, 21), (16, 1, 1, 31, 21, 1), axes='ZYX'
13386            )
13387            xml.addimage(
13388                numpy.uint8, (3, 31, 21), (3, 1, 1, 31, 21, 1), axes='CYX'
13389            )
13390            tif.overwrite_description(xml.tostring())
13391
13392        with TiffFile(fname) as tif:
13393            assert tif.is_ome
13394            assert len(tif.pages) == 19
13395            assert len(tif.series) == 2
13396            # assert series properties
13397            series = tif.series[0]
13398            assert series.axes == 'ZYX'
13399            assert bool(series.offset) == contiguous
13400            assert_array_equal(data[:16], series.asarray())
13401            series = tif.series[1]
13402            assert series.axes == 'CYX'
13403            assert bool(series.offset) == contiguous
13404            assert_array_equal(data[16:], series.asarray())
13405            #
13406            assert_valid_omexml(tif.ome_metadata)
13407            assert__str__(tif)
13408
13409        assert_valid_tiff(fname)
13410
13411
13412@pytest.mark.skipif(
13413    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG or SKIP_LARGE,
13414    reason=REASON,
13415)
13416def test_write_ome_copy():
13417    """Test write pyramidal OME-TIFF by copying compressed tiles from SVS."""
13418
13419    def tiles(page):
13420        # return iterator over compressed tiles in page
13421        assert page.is_tiled
13422        fh = page.parent.filehandle
13423        for offset, bytecount in zip(page.dataoffsets, page.databytecounts):
13424            fh.seek(offset)
13425            yield fh.read(bytecount)
13426
13427    with TiffFile(private_file('AperioSVS/CMU-1.svs')) as svs:
13428        assert svs.is_svs
13429        levels = svs.series[0].levels
13430
13431        with TempFileName('_write_ome_copy', ext='.ome.tif') as fname:
13432
13433            with TiffWriter(fname, ome=True, bigtiff=True) as tif:
13434                level = levels[0]
13435                assert len(level.pages) == 1
13436                page = level.pages[0]
13437                if page.compression == 7:
13438                    # override default that RGB will be compressed as YCBCR
13439                    compressionargs = {'outcolorspace': page.photometric}
13440                else:
13441                    compressionargs = {}
13442                extratags = (
13443                    # copy some extra tags
13444                    page.tags.get('ImageDepth')._astuple(),
13445                    page.tags.get('InterColorProfile')._astuple(),
13446                )
13447                tif.write(
13448                    tiles(page),
13449                    shape=page.shape,
13450                    dtype=page.dtype,
13451                    tile=(page.tilelength, page.tilewidth),
13452                    photometric=page.photometric,
13453                    planarconfig=page.planarconfig,
13454                    compression=(page.compression, None, compressionargs),
13455                    jpegtables=page.jpegtables,
13456                    subsampling=page.subsampling,
13457                    subifds=len(levels) - 1,
13458                    extratags=extratags,
13459                )
13460                for level in levels[1:]:
13461                    assert len(level.pages) == 1
13462                    page = level.pages[0]
13463                    if page.compression == 7:
13464                        compressionargs = {'outcolorspace': page.photometric}
13465                    else:
13466                        compressionargs = {}
13467                    tif.write(
13468                        tiles(page),
13469                        shape=page.shape,
13470                        dtype=page.dtype,
13471                        tile=(page.tilelength, page.tilewidth),
13472                        photometric=page.photometric,
13473                        planarconfig=page.planarconfig,
13474                        compression=(page.compression, None, compressionargs),
13475                        jpegtables=page.jpegtables,
13476                        subsampling=page.subsampling,
13477                        subfiletype=1,
13478                    )
13479
13480            with TiffFile(fname) as tif:
13481                assert tif.is_ome
13482                assert len(tif.pages) == 1
13483                assert len(tif.pages[0].pages) == 2
13484                assert 'InterColorProfile' in tif.pages[0].tags
13485                assert tif.pages[0].tags['ImageDepth'].value == 1
13486                levels_ = tif.series[0].levels
13487                assert len(levels_) == len(levels)
13488                for level, level_ in zip(levels[1:], levels_[1:]):
13489                    assert level.shape == level_.shape
13490                    assert level.dtype == level_.dtype
13491                    assert_array_equal(level.asarray(), level_.asarray())
13492
13493
13494@pytest.mark.skipif(
13495    SKIP_PRIVATE or SKIP_CODECS or not imagecodecs.JPEG, reason=REASON
13496)
13497@pytest.mark.xfail  # TODO: should pass once strip generators are supported
13498def test_write_geotiff_copy():
13499    """Test write a copy of striped, compressed GeoTIFF."""
13500
13501    def strips(page):
13502        # return iterator over compressed tiles in page
13503        assert not page.is_tiled
13504        fh = page.parent.filehandle
13505        for offset, bytecount in zip(page.dataoffsets, page.databytecounts):
13506            fh.seek(offset)
13507            yield fh.read(bytecount)
13508
13509    with TiffFile(private_file('GeoTIFF/ML_30m.tif')) as geotiff:
13510        assert geotiff.is_geotiff
13511        assert len(geotiff.pages) == 1
13512
13513        with TempFileName('_write_geotiff_copy') as fname:
13514
13515            with TiffWriter(
13516                fname, byteorder=geotiff.byteorder, bigtiff=geotiff.is_bigtiff
13517            ) as tif:
13518                page = geotiff.pages[0]
13519                tags = page.tags
13520                extratags = (
13521                    tags.get('ModelPixelScaleTag')._astuple(),
13522                    tags.get('ModelTiepointTag')._astuple(),
13523                    tags.get('GeoKeyDirectoryTag')._astuple(),
13524                    tags.get('GeoAsciiParamsTag')._astuple(),
13525                    tags.get('GDAL_NODATA')._astuple(),
13526                )
13527                tif.write(
13528                    strips(page),
13529                    shape=page.shape,
13530                    dtype=page.dtype,
13531                    rowsperstrip=page.rowsperstrip,
13532                    photometric=page.photometric,
13533                    planarconfig=page.planarconfig,
13534                    compression=page.compression,
13535                    predictor=page.predictor,
13536                    jpegtables=page.jpegtables,
13537                    subsampling=page.subsampling,
13538                    extratags=extratags,
13539                )
13540
13541            with TiffFile(fname) as tif:
13542                assert tif.is_geotiff
13543                assert len(tif.pages) == 1
13544                assert tif.nodata == -32767
13545                assert tif.pages[0].tags['ModelPixelScaleTag'].value == (
13546                    30.0,
13547                    30.0,
13548                    0.0,
13549                )
13550                assert tif.pages[0].tags['ModelTiepointTag'].value == (
13551                    0.0,
13552                    0.0,
13553                    0.0,
13554                    1769487.0,
13555                    5439473.0,
13556                    0.0,
13557                )
13558                assert tif.geotiff_metadata['GeogAngularUnitsGeoKey'] == 9102
13559                assert_array_equal(tif.asarray(), geotiff.asarray())
13560
13561
13562###############################################################################
13563
13564# Test embedded TIFF files
13565
13566EMBED_NAME = public_file('tifffile/test_FileHandle.bin')
13567EMBED_OFFSET = 7077
13568EMBED_SIZE = 5744
13569EMBED_OFFSET1 = 13820
13570EMBED_SIZE1 = 7936382
13571
13572
13573def assert_embed_tif(tif):
13574    """Assert embedded TIFF file."""
13575    # 4 series in 6 pages
13576    assert tif.byteorder == '<'
13577    assert len(tif.pages) == 6
13578    assert len(tif.series) == 4
13579    # assert series 0 properties
13580    series = tif.series[0]
13581    assert series.shape == (3, 20, 20)
13582    assert series.dtype == numpy.uint8
13583    assert series.axes == 'IYX'
13584    page = series.pages[0]
13585    assert page.compression == LZW
13586    assert page.imagewidth == 20
13587    assert page.imagelength == 20
13588    assert page.bitspersample == 8
13589    assert page.samplesperpixel == 1
13590    data = tif.asarray(series=0)
13591    assert isinstance(data, numpy.ndarray)
13592    assert data.shape == (3, 20, 20)
13593    assert data.dtype == numpy.uint8
13594    assert tuple(data[:, 9, 9]) == (19, 90, 206)
13595    # assert series 1 properties
13596    series = tif.series[1]
13597    assert series.shape == (10, 10, 3)
13598    assert series.dtype == numpy.float32
13599    assert series.axes == 'YXS'
13600    page = series.pages[0]
13601    assert page.photometric == RGB
13602    assert page.compression == LZW
13603    assert page.imagewidth == 10
13604    assert page.imagelength == 10
13605    assert page.bitspersample == 32
13606    assert page.samplesperpixel == 3
13607    data = tif.asarray(series=1)
13608    assert isinstance(data, numpy.ndarray)
13609    assert data.shape == (10, 10, 3)
13610    assert data.dtype == numpy.float32
13611    assert round(abs(data[9, 9, 1] - 214.5733642578125), 7) == 0
13612    # assert series 2 properties
13613    series = tif.series[2]
13614    assert series.shape == (20, 20, 3)
13615    assert series.dtype == numpy.uint8
13616    assert series.axes == 'YXS'
13617    page = series.pages[0]
13618    assert page.photometric == RGB
13619    assert page.compression == LZW
13620    assert page.imagewidth == 20
13621    assert page.imagelength == 20
13622    assert page.bitspersample == 8
13623    assert page.samplesperpixel == 3
13624    data = tif.asarray(series=2)
13625    assert isinstance(data, numpy.ndarray)
13626    assert data.shape == (20, 20, 3)
13627    assert data.dtype == numpy.uint8
13628    assert tuple(data[9, 9, :]) == (19, 90, 206)
13629    # assert series 3 properties
13630    series = tif.series[3]
13631    assert series.shape == (10, 10)
13632    assert series.dtype == numpy.float32
13633    assert series.axes == 'YX'
13634    page = series.pages[0]
13635    assert page.compression == LZW
13636    assert page.imagewidth == 10
13637    assert page.imagelength == 10
13638    assert page.bitspersample == 32
13639    assert page.samplesperpixel == 1
13640    data = tif.asarray(series=3)
13641    assert isinstance(data, numpy.ndarray)
13642    assert data.shape == (10, 10)
13643    assert data.dtype == numpy.float32
13644    assert round(abs(data[9, 9] - 223.1648712158203), 7) == 0
13645    assert__str__(tif)
13646
13647
13648def assert_embed_micromanager(tif):
13649    """Assert embedded MicroManager TIFF file."""
13650    assert tif.is_ome
13651    assert tif.is_imagej
13652    assert tif.is_micromanager
13653    assert tif.byteorder == '<'
13654    assert len(tif.pages) == 15
13655    assert len(tif.series) == 1
13656    # assert non-tiff micromanager_metadata
13657    tags = tif.micromanager_metadata['Summary']
13658    assert tags['MicroManagerVersion'] == '1.4.x dev'
13659    assert tags['UserName'] == 'trurl'
13660    # assert page properties
13661    page = tif.pages[0]
13662    assert page.is_contiguous
13663    assert page.compression == NONE
13664    assert page.imagewidth == 512
13665    assert page.imagelength == 512
13666    assert page.bitspersample == 16
13667    assert page.samplesperpixel == 1
13668    # two description tags
13669    assert page.description.startswith('<?xml')
13670    assert page.description1.startswith('ImageJ')
13671    # assert some metadata
13672    tags = tif.imagej_metadata
13673    assert tags['frames'] == 5
13674    assert tags['slices'] == 3
13675    assert tags['Ranges'] == (706.0, 5846.0)
13676    tags = tif.pages[0].tags[51123].value
13677    assert tags['FileName'] == 'Untitled_1_MMStack.ome.tif'
13678    assert tags['PixelType'] == 'GRAY16'
13679    # assert series properties
13680    series = tif.series[0]
13681    assert series.shape == (5, 3, 512, 512)
13682    assert series.dtype == numpy.uint16
13683    assert series.axes == 'TZYX'
13684    # assert data
13685    data = tif.asarray()
13686    assert data.shape == (5, 3, 512, 512)
13687    assert data.dtype == numpy.uint16
13688    assert data[4, 2, 511, 511] == 1602
13689    # assert memmap
13690    data = tif.asarray(out='memmap')
13691    assert isinstance(data, numpy.core.memmap)
13692    assert data.shape == (5, 3, 512, 512)
13693    assert data.dtype == numpy.dtype('<u2')
13694    assert data[4, 2, 511, 511] == 1602
13695    del data
13696    assert__str__(tif)
13697
13698
13699@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
13700def test_embed_tif_filename():
13701    """Test embedded TIFF from filename."""
13702    with TiffFile(EMBED_NAME, offset=EMBED_OFFSET, size=EMBED_SIZE) as tif:
13703        assert_embed_tif(tif)
13704
13705
13706@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
13707def test_embed_tif_openfile():
13708    """Test embedded TIFF from file handle."""
13709    with open(EMBED_NAME, 'rb') as fh:
13710        with TiffFile(fh, offset=EMBED_OFFSET, size=EMBED_SIZE) as tif:
13711            assert_embed_tif(tif)
13712
13713
13714@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
13715def test_embed_tif_openfile_seek():
13716    """Test embedded TIFF from seeked file handle."""
13717    with open(EMBED_NAME, 'rb') as fh:
13718        fh.seek(EMBED_OFFSET)
13719        with TiffFile(fh, size=EMBED_SIZE) as tif:
13720            assert_embed_tif(tif)
13721
13722
13723@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
13724def test_embed_tif_filehandle():
13725    """Test embedded TIFF from FileHandle."""
13726    with FileHandle(EMBED_NAME, offset=EMBED_OFFSET, size=EMBED_SIZE) as fh:
13727        with TiffFile(fh) as tif:
13728            assert_embed_tif(tif)
13729
13730
13731@pytest.mark.skipif(SKIP_PUBLIC or SKIP_CODECS, reason=REASON)
13732def test_embed_tif_bytesio():
13733    """Test embedded TIFF from BytesIO."""
13734    with open(EMBED_NAME, 'rb') as fh:
13735        fh2 = BytesIO(fh.read())
13736    with TiffFile(fh2, offset=EMBED_OFFSET, size=EMBED_SIZE) as tif:
13737        assert_embed_tif(tif)
13738
13739
13740@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13741def test_embed_mm_filename():
13742    """Test embedded MicroManager TIFF from file name."""
13743    with TiffFile(EMBED_NAME, offset=EMBED_OFFSET1, size=EMBED_SIZE1) as tif:
13744        assert_embed_micromanager(tif)
13745
13746
13747@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13748def test_embed_mm_openfile():
13749    """Test embedded MicroManager TIFF from file handle."""
13750    with open(EMBED_NAME, 'rb') as fh:
13751        with TiffFile(fh, offset=EMBED_OFFSET1, size=EMBED_SIZE1) as tif:
13752            assert_embed_micromanager(tif)
13753
13754
13755@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13756def test_embed_mm_openfile_seek():
13757    """Test embedded MicroManager TIFF from seeked file handle."""
13758    with open(EMBED_NAME, 'rb') as fh:
13759        fh.seek(EMBED_OFFSET1)
13760        with TiffFile(fh, size=EMBED_SIZE1) as tif:
13761            assert_embed_micromanager(tif)
13762
13763
13764@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13765def test_embed_mm_filehandle():
13766    """Test embedded MicroManager TIFF from FileHandle."""
13767    with FileHandle(EMBED_NAME, offset=EMBED_OFFSET1, size=EMBED_SIZE1) as fh:
13768        with TiffFile(fh) as tif:
13769            assert_embed_micromanager(tif)
13770
13771
13772@pytest.mark.skipif(SKIP_PUBLIC, reason=REASON)
13773def test_embed_mm_bytesio():
13774    """Test embedded MicroManager TIFF from BytesIO."""
13775    with open(EMBED_NAME, 'rb') as fh:
13776        fh2 = BytesIO(fh.read())
13777    with TiffFile(fh2, offset=EMBED_OFFSET1, size=EMBED_SIZE1) as tif:
13778        assert_embed_micromanager(tif)
13779
13780
13781###############################################################################
13782
13783# Test sequence of image files
13784
13785
13786def test_sequence_stream_list():
13787    """Test TiffSequence with list of ByteIO streams raises TypeError."""
13788    data = numpy.random.rand(7, 9)
13789    files = [BytesIO(), BytesIO()]
13790    for buffer in files:
13791        imwrite(buffer, data)
13792    with pytest.raises(TypeError):
13793        imread(files)
13794
13795
13796@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
13797def test_sequence_glob_pattern():
13798    """Test TiffSequence with glob pattern without axes pattern."""
13799    fname = private_file('TiffSequence/*.tif')
13800    tifs = TiffSequence(fname, pattern=None)
13801    assert len(tifs) == 10
13802    assert tifs.shape == (10,)
13803    assert tifs.axes == 'I'
13804    data = tifs.asarray()
13805    assert isinstance(data, numpy.ndarray)
13806    assert data.flags['C_CONTIGUOUS']
13807    assert data.shape == (10, 480, 640)
13808    assert data.dtype == numpy.uint8
13809    assert data[9, 256, 256] == 135
13810    if not SKIP_ZARR:
13811        with tifs.aszarr() as store:
13812            assert_array_equal(data, zarr.open(store, mode='r'))
13813
13814
13815@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
13816def test_sequence_name_list():
13817    """Test TiffSequence with list of file names without pattern."""
13818    fname = [
13819        private_file('TiffSequence/AT3_1m4_01.tif'),
13820        private_file('TiffSequence/AT3_1m4_10.tif'),
13821    ]
13822    tifs = TiffSequence(fname, pattern=None)
13823    assert len(tifs) == 2
13824    assert tifs.shape == (2,)
13825    assert tifs.axes == 'I'
13826    data = tifs.asarray()
13827    assert isinstance(data, numpy.ndarray)
13828    assert data.flags['C_CONTIGUOUS']
13829    assert data.shape == (2, 480, 640)
13830    assert data.dtype == numpy.uint8
13831    assert data[1, 256, 256] == 135
13832    if not SKIP_ZARR:
13833        with tifs.aszarr() as store:
13834            assert_array_equal(data, zarr.open(store, mode='r'))
13835
13836
13837@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
13838def test_sequence_oif_series():
13839    """Test TiffSequence with files from Olympus OIF, memory mapped."""
13840    fname = private_file(
13841        'oif/MB231cell1_paxgfp_PDMSgasket_PMMAflat_30nm_378sli.oif.files/*.tif'
13842    )
13843    tifs = TiffSequence(fname, pattern='axes')
13844    assert len(tifs) == 756
13845    assert tifs.shape == (2, 378)
13846    assert tifs.axes == 'CZ'
13847    # memory map
13848    data = tifs.asarray(out='memmap', ioworkers=None)
13849    assert isinstance(data, numpy.core.memmap)
13850    assert data.flags['C_CONTIGUOUS']
13851    assert data.shape == (2, 378, 256, 256)
13852    assert data.dtype == numpy.dtype('<u2')
13853    assert data[1, 377, 70, 146] == 29
13854    if not SKIP_ZARR:
13855        with tifs.aszarr() as store:
13856            assert_array_equal(data, zarr.open(store, mode='r'))
13857    del data
13858
13859
13860@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
13861def test_sequence_leica_series():
13862    """Test TiffSequence with Leica TIFF series, memory mapped."""
13863    fname = private_file('leicaseries/Series019_*.tif')
13864    tifs = TiffSequence(fname, pattern='axes')
13865    assert len(tifs) == 46
13866    assert tifs.shape == (46,)
13867    assert tifs.axes == 'Y'
13868    # memory map
13869    data = tifs.asarray(out='memmap')
13870    assert isinstance(data, numpy.core.memmap)
13871    assert data.flags['C_CONTIGUOUS']
13872    assert data.shape == (46, 512, 512, 3)
13873    assert data.dtype == numpy.uint8
13874    assert tuple(data[45, 256, 256]) == (93, 56, 56)
13875    if not SKIP_ZARR:
13876        with tifs.aszarr() as store:
13877            assert_array_equal(data, zarr.open(store, mode='r'))
13878    del data
13879
13880
13881@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
13882def test_sequence_zip_container():
13883    """Test TiffSequence with glob pattern without axes pattern."""
13884    fname = private_file('TiffSequence.zip')
13885    with TiffSequence('*.tif', container=fname, pattern=None) as tifs:
13886        assert len(tifs) == 10
13887        assert tifs.shape == (10,)
13888        assert tifs.axes == 'I'
13889        data = tifs.asarray()
13890        assert isinstance(data, numpy.ndarray)
13891        assert data.flags['C_CONTIGUOUS']
13892        assert data.shape == (10, 480, 640)
13893        assert data.dtype == numpy.uint8
13894        assert data[9, 256, 256] == 135
13895    assert_array_equal(data, imread(container=fname))
13896
13897
13898@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE or SKIP_CODECS, reason=REASON)
13899def test_sequence_wells_axesorder():
13900    """Test FileSequence with well plates and axes reorder."""
13901    # https://bbbc.broadinstitute.org/BBBC006
13902    ptrn = r'(?:_(z)_(\d+)).*_(?P<p>[a-z])(?P<a>\d+)(?:_(s)(\d))(?:_(w)(\d))'
13903    fnames = private_file('BBBC/BBBC006_v1_images_z_00/*.tif')
13904    fnames += private_file('BBBC/BBBC006_v1_images_z_01/*.tif')
13905    tifs = TiffSequence(fnames, pattern=ptrn, axesorder=(1, 2, 0, 3, 4))
13906    assert len(tifs) == 3072
13907    assert tifs.shape == (16, 24, 2, 2, 2)
13908    assert tifs.axes == 'PAZSW'
13909    data = tifs.asarray()
13910    assert isinstance(data, numpy.ndarray)
13911    assert data.flags['C_CONTIGUOUS']
13912    assert data.shape == (16, 24, 2, 2, 2, 520, 696)
13913    assert data.dtype == numpy.uint16
13914    assert data[8, 12, 1, 0, 1, 256, 519] == 1579
13915    if not SKIP_ZARR:
13916        with tifs.aszarr() as store:
13917            assert_array_equal(data, zarr.open(store, mode='r'))
13918
13919
13920@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
13921def test_sequence_tiled():
13922    """Test FileSequence with tiled OME-TIFFs."""
13923    # Dataset from https://github.com/tlambert03/tifffolder/issues/2
13924    ptrn = re.compile(
13925        r'\[(?P<U>\d+) x (?P<V>\d+)\].*(C)(\d+).*(Z)(\d+)', re.IGNORECASE
13926    )
13927    fnames = private_file('TiffSequenceTiled/*.tif', expand=False)
13928    tifs = TiffSequence(fnames, pattern=ptrn)
13929    assert len(tifs) == 60
13930    assert tifs.shape == (2, 3, 2, 5)
13931    assert tifs.axes == 'UVCZ'
13932    data = tifs.asarray(is_ome=False)
13933    assert isinstance(data, numpy.ndarray)
13934    assert data.flags['C_CONTIGUOUS']
13935    assert data.shape == (2, 3, 2, 5, 2560, 2160)
13936    assert data.dtype == numpy.uint16
13937    assert data[1, 2, 1, 3, 1024, 1024] == 596
13938    if not SKIP_ZARR:
13939        with tifs.aszarr(is_ome=False) as store:
13940            assert_array_equal(
13941                data[1, 2, 1, 3:5], zarr.open(store, mode='r')[1, 2, 1, 3:5]
13942            )
13943
13944
13945@pytest.mark.skipif(SKIP_PRIVATE or SKIP_CODECS, reason=REASON)
13946def test_sequence_imread():
13947    """Test TiffSequence with imagecodecs.imread."""
13948    fname = private_file('PNG/*.png')
13949    pngs = TiffSequence(fname, imread=imagecodecs.imread)
13950    assert len(pngs) == 4
13951    assert pngs.shape == (4,)
13952    assert pngs.axes == 'I'
13953    data = pngs.asarray(codec=imagecodecs.png_decode)
13954    assert data.flags['C_CONTIGUOUS']
13955    assert data.shape == (4, 200, 200)
13956    assert data.dtype == numpy.uint16
13957    if not SKIP_ZARR:
13958        with pngs.aszarr(codec=imagecodecs.png_decode) as store:
13959            assert_array_equal(data, zarr.open(store, mode='r'))
13960    del data
13961
13962
13963###############################################################################
13964
13965# Test packages depending on tifffile
13966
13967
13968@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
13969def test_depend_roifile():
13970    """Test roifile.ImagejRoi class."""
13971    from roifile import ImagejRoi  # noqa
13972
13973    for roi in ImagejRoi.fromfile(private_file('imagej/IJMetadata.tif')):
13974        assert roi == ImagejRoi.frombytes(roi.tobytes())
13975        roi.coordinates()
13976        roi.__str__()
13977
13978
13979@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
13980def test_depend_lfdfiles():
13981    """Test lfdfiles conversion to TIFF."""
13982    from lfdfiles import SimfcsZ64  # noqa
13983
13984    filename = private_file('SimFCS/simfcs.Z64')
13985    with TempFileName('simfcsz_z64', ext='.tif') as outfile:
13986        with SimfcsZ64(filename) as z64:
13987            data = z64.asarray()
13988            z64.totiff(outfile)
13989        with TiffFile(outfile) as tif:
13990            assert len(tif.pages) == 256
13991            assert len(tif.series) == 1
13992            assert tif.series[0].shape == (256, 256, 256)
13993            assert tif.series[0].dtype == numpy.float32
13994            assert_array_equal(data, tif.asarray())
13995
13996
13997@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
13998def test_depend_cmapfile():
13999    """Test cmapfile.lsm2cmap."""
14000    from cmapfile import CmapFile, lsm2cmap  # noqa
14001
14002    filename = private_file('LSM/3d_zfish_onephoton_zoom.lsm')
14003    data = imread(filename)
14004    with TempFileName('cmapfile', ext='.cmap') as cmapfile:
14005        lsm2cmap(filename, cmapfile, step=(1.0, 1.0, 20.0))
14006        fname = os.path.join(
14007            os.path.split(cmapfile)[0], 'test_cmapfile.ch0000.cmap'
14008        )
14009        with CmapFile(fname, mode='r') as cmap:
14010            assert_array_equal(
14011                cmap['map00000']['data00000'], data.squeeze()[:, 0, :, :]
14012            )
14013
14014
14015@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
14016def test_depend_czifile():
14017    """Test czifile.CziFile."""
14018    # TODO: test LZW compressed czi file
14019    from czifile import CziFile
14020
14021    fname = private_file('czi/pollen.czi')
14022    with CziFile(fname) as czi:
14023        assert czi.shape == (1, 1, 104, 365, 364, 1)
14024        assert czi.axes == 'TCZYX0'
14025        # verify data
14026        data = czi.asarray()
14027        assert data.flags['C_CONTIGUOUS']
14028        assert data.shape == (1, 1, 104, 365, 364, 1)
14029        assert data.dtype == numpy.uint8
14030        assert data[0, 0, 52, 182, 182, 0] == 10
14031
14032
14033@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
14034def test_depend_czi2tif():
14035    """Test czifile.czi2tif."""
14036    from czifile.czifile import CziFile, czi2tif
14037
14038    fname = private_file('CZI/pollen.czi')
14039    with CziFile(fname) as czi:
14040        metadata = czi.metadata()
14041        data = czi.asarray().squeeze()
14042    with TempFileName('czi2tif') as tif:
14043        czi2tif(fname, tif, bigtiff=False)
14044        with TiffFile(tif) as t:
14045            im = t.asarray()
14046            assert t.pages[0].description == metadata
14047
14048        assert_array_equal(im, data)
14049        del im
14050        del data
14051        assert_valid_tiff(tif)
14052
14053
14054@pytest.mark.skipif(SKIP_PRIVATE or SKIP_LARGE, reason=REASON)
14055def test_depend_czi2tif_airy():
14056    """Test czifile.czi2tif with AiryScan."""
14057    from czifile.czifile import czi2tif
14058
14059    fname = private_file('CZI/AiryscanSRChannel.czi')
14060    with TempFileName('czi2tif_airy') as tif:
14061        czi2tif(fname, tif, verbose=True, truncate=True, bigtiff=False)
14062        im = memmap(tif)
14063        assert im.shape == (32, 6, 1680, 1680)
14064        assert tuple(im[17, :, 1500, 1000]) == (95, 109, 3597, 0, 0, 0)
14065        del im
14066        assert_valid_tiff(tif)
14067
14068
14069@pytest.mark.skipif(SKIP_PRIVATE, reason=REASON)
14070def test_depend_oiffile():
14071    """Test oiffile.OifFile."""
14072    from oiffile import OifFile
14073
14074    fname = private_file(
14075        'oib/MB231cell1_paxgfp_PDMSgasket_PMMAflat_30nm_378sli.oib'
14076    )
14077    with OifFile(fname) as oib:
14078        assert oib.is_oib
14079        tifs = oib.series[0]
14080        assert len(tifs) == 756
14081        assert tifs.shape == (2, 378)
14082        assert tifs.axes == 'CZ'
14083        # verify data
14084        data = tifs.asarray(out='memmap')
14085        assert data.flags['C_CONTIGUOUS']
14086        assert data.shape == (2, 378, 256, 256)
14087        assert data.dtype == numpy.dtype('<u2')
14088        assert data[1, 377, 70, 146] == 29
14089        del data
14090
14091
14092###############################################################################
14093
14094if __name__ == '__main__':
14095    import warnings
14096
14097    # warnings.simplefilter('always')  # noqa
14098    warnings.filterwarnings('ignore', category=ImportWarning)  # noqa
14099    argv = sys.argv
14100    argv.append('--cov=tifffile')
14101    argv.append('--verbose')
14102    sys.exit(pytest.main(argv))
14103