view scripts/io/Tiff.m @ 31185:a1145ac2ce9b

Tiff: populated TagID from the C++ map to avoid having two copies * __tiff__.cc (F__tiff_make_tagid__): implemented internal function as initializer for TagID. * Tiff.m: changed the initialization for TagID to use the internal function.
author magedrifaat <magedrifaat@gmail.com>
date Thu, 18 Aug 2022 17:23:43 +0200
parents f294b800f002
children 90eccc78d958
line wrap: on
line source

## PKG_ADD: __tiff_set_errors_enabled__ (false);

classdef Tiff
  properties (Constant = true)
    TagID = __tiff_make_tagid__ ();

    Compression = struct (
      "None", 1,
      "CCITTRLE", 2,
      "CCITTFax3", 3,
      "CCITTFax4", 4,
      "LZW", 5,
      "OJPEG", 6,
      "JPEG", 7,
      "AdobeDeflate", 8,
      "Next", 32766,
      "CCITTRLEW", 32771,
      "PackBits", 32773,
      "Thunderscan", 32809,
      "IT8CTPad", 32895,
      "IT8LW", 32896,
      "IT8MP", 32897,
      "IT8BL", 32898,
      "PixarFilm", 32908,
      "PixarLog", 32909,
      "Deflate", 32946,
      "DCS", 32947,
      "JBIG", 34661,
      "SGILog", 34676,
      "SGILog24", 34677,
      "JPEG2000", 34712,
      # Not defined in LibTIFF, only in matlab
      # TODO(maged): test these compression methods
      "JPEG2000_SVS_YCbCr", 33003,
      "JPEG2000_SVS_RGB", 33005
    );

    ExtraSamples = struct (
      "Unspecified", 0,
      "AssociatedAlpha", 1,
      "UnassociatedAlpha", 2
    );

    Group3Options = struct (
      "Encoding2D", 1,
      "Uncompressed", 2,
      "FillBits", 4
    );

    InkSet = struct (
      "CMYK", 1,
      "MultiInk", 2
    );

    JPEGColorMode = struct (
      "Raw", 0,
      "RGB", 1
    );

    Orientation = struct (
      "TopLeft", 1,
      "TopRight", 2,
      "BottomRight", 3,
      "BottomLeft", 4,
      "LeftTop", 5,
      "RightTop", 6,
      "RightBottom", 7,
      "LeftBottom", 8
    );

    Photometric = struct (
      "MinIsWhite", 0,
      "MinIsBlack", 1,
      "RGB", 2,
      "Palette", 3,
      "Mask", 4,
      "Separated", 5,
      "YCbCr", 6,
      "CIELab", 8,
      "ICCLab", 9,
      "ITULab", 10,
      "LogL", 32844,
      "LogLUV", 32845,
      "CFA", 32803,
      "LinearRaw", 34892
    );

    PlanarConfiguration = struct (
      "Chunky", 1,
      "Separate", 2
    );

    ResolutionUnit = struct (
      "None", 1,
      "Inch", 2,
      "Centimeter", 3
    );

    SampleFormat = struct (
      "UInt", 1,
      "Int", 2,
      "IEEEFP", 3
    );

    SGILogDataFmt = struct (
      "Float", 0,
      "Bits8", 3
    );

    SubFileType = struct (
      "Default", 0,
      "ReducedImage", 1,
      "Page", 2,
      "Mask", 4
    );

    Thresholding = struct (
      "BiLevel", 1,
      "HalfTone", 2,
      "ErrorDiffuse", 3
    );

    YCbCrPositioning = struct (
      "Centered", 1,
      "Cosited", 2
    );
  endproperties

  properties (Access = private)
    tiff_handle;
  endproperties

  methods
    function t = Tiff (filename, mode="r")
      if (nargin == 0 || nargin > 2)
        % print_usage();
        error("Usage: Tiff(filename[, mode])");
      endif

      t.tiff_handle = __open_tiff__ (filename, mode);
    endfunction

    function close (t)
      __close_tiff__ (t.tiff_handle);
    endfunction

    function tag = getTag (t, tag_name)
      tag = __tiff_get_tag__ (t.tiff_handle, tag_name);
    endfunction

    function setTag (t, varargin)
      __tiff_set_tag__ (t.tiff_handle, varargin{:});
    endfunction

    function argout = read (t)
      argout = __tiff_read__ (t.tiff_handle);
    endfunction

    function stripData = readEncodedStrip (t, stripNumber)
      stripData = __tiff_read_encoded_strip__ (t.tiff_handle, stripNumber);
    endfunction

    function tileData = readEncodedTile (t, tileNumber)
      tileData = __tiff_read_encoded_tile__ (t.tiff_handle, tileNumber);
    endfunction

    function [RGB, alpha] = readRGBAImage (t)
      [RGB, alpha] = __tiff_read_rgba_image__ (t.tiff_handle);
    endfunction

    function [RGB, alpha] = readRGBAStrip (t, row)
      [RGB, alpha] = __tiff_read_rgba_strip__ (t.tiff_handle, row);
    endfunction

    function [RGB, alpha] = readRGBATile (t, row, col)
      [RGB, alpha] = __tiff_read_rgba_tile__ (t.tiff_handle, row, col);
    endfunction

    function write (t, imageData)
      __tiff_write__ (t.tiff_handle, imageData);
    endfunction

    function writeEncodedStrip (t, stripNumber, imageData)
      __tiff_write_encoded_strip__ (t.tiff_handle, stripNumber, imageData);
    endfunction

    function writeEncodedTile (t, tileNumber, imageData)
      __tiff_write_encoded_tile__ (t.tiff_handle, tileNumber, imageData);
    endfunction

    function tf = isTiled (t)
      tf = __tiff_is_tiled__ (t.tiff_handle);
    endfunction

    function numStrips = numberOfStrips (t)
      numStrips = __tiff_number_of_strips__ (t.tiff_handle);
    endfunction

    function numTiles = numberOfTiles (t)
      numTiles = __tiff_number_of_tiles__ (t.tiff_handle);
    endfunction

    function stripNumber = computeStrip (t, varargin)
      stripNumber = __tiff_compute_strip__ (t.tiff_handle, varargin{:});
    endfunction

    function tileNumber = computeTile (t, varargin)
      tileNumber = __tiff_compute_tile__ (t.tiff_handle, varargin{:});
    endfunction

    function dirNum = currentDirectory (t)
      dirNum = __tiff_current_directory__ (t.tiff_handle);
    endfunction

    function isLast = lastDirectory (t)
      isLast = __tiff_last_directory__ (t.tiff_handle);
    endfunction

    function nextDirectory (t)
      __tiff_next_directory__ (t.tiff_handle);
    endfunction

    function setDirectory (t, dirNum)
      __tiff_set_directory__ (t.tiff_handle, dirNum);
    endfunction

    function writeDirectory (t)
      __tiff_write_directory__ (t.tiff_handle);
    endfunction

    function rewriteDirectory (t)
      __tiff_rewrite_directory__ (t.tiff_handle);
    endfunction

    function setSubDirectory (t, offset)
      __tiff_set_sub_directory__ (t.tiff_handle, offset);
    endfunction

    % TODO(maged): add documentation and make print_usage work
  endmethods

  methods (Static = true)
    function versionString = getVersion()
      versionString = __tiff_version__ ();
    endfunction

    function tagNames = getTagNames ()
      tagNames = fieldnames (Tiff.TagID);
    endfunction

    function setLibTIFFErrorsEnabled(state)
      __tiff_set_errors_enabled__ (state);
    endfunction
  endmethods
endclassdef

%!function file_wrapper (fn)
%!  filename = [tempname() ".tif"];
%!  unwind_protect
%!    fn (filename);
%!  unwind_protect_cleanup
%!    unlink (filename);
%!  end_unwind_protect
%!endfunction

%!function verify_data (filename, data, ex_size)
%!    img = Tiff (filename, "r");
%!    data2 = img.read ();
%!    assert (size (data2), ex_size);
%!    assert (data2, resize (data, size (data2)));
%!    img.close ();
%!endfunction

## test setTag and getTag for scalar tags
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, "ImageWidth", 2);
%!    val = getTag (img, "ImageWidth");
%!    assert (val, 2);
%!    assert (class (val), "double");
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure setTag and getTag unknown tag
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    fail ("getTag (img, \"ImageWidt\")", "Tiff tag not found");
%!    fail ("getTag (img, 999999)", "Tiff tag not found");
%!    fail ("setTag (img, \"ImageWidt\", 2)", "Tiff tag not found");
%!    fail ("setTag (img, 999999, 2)", "Tiff tag not found");
%!  endfunction
%!  file_wrapper (@test_fn);

## test setTag structure input
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 2, "ImageWidth", 2));
%!    assert (getTag (img, "ImageLength"), 2);
%!    assert (getTag (img, "ImageWidth"), 2);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure setTag structure unknown tag
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, "ImageLength", 1);
%!    setTag (img, "ImageWidth", 1);
%!    fail ("setTag (img, struct (\"ImageLength\", 2, \"a\", 1, \"ImageWidth\", 2))",
%!          "Tag a not found");
%!    assert (getTag (img, "ImageLength"), 2);
%!    assert (getTag (img, "ImageWidth"), 1);
%!  endfunction
%!  file_wrapper (@test_fn);

## test setTag array field
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, "YCbCrCoefficients", [1.5, 2.5, 3.5]);
%!    data = getTag (img, "YCbCrCoefficients");
%!    assert (data, [1.5, 2.5, 3.5]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test setTag special field
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, "BitsPerSample", 8);
%!    cmap = reshape (1:768, [256, 3]) / 1024.0;
%!    setTag (img, "ColorMap", cmap);
%!    assert (getTag (img, "ColorMap"), cmap, 1e-5);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure invalid open mode/ invalid filename
%!testif HAVE_TIFF
%!  fail ("Tiff (\"test.tif\", \"rh\")",
%!        "Invalid mode for openning Tiff file: rh");
%!  fail ("Tiff ([tempname() \".tif\"], \"r\")", "Failed to open Tiff file");

## test r+ mode modifies exisitng images
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct (
%!      "ImageLength", 1, "ImageWidth", 1,
%!      "BitsPerSample", 8
%!    ));
%!    write (img, uint8 ([210]));
%!    img.close ();
%!    img = Tiff (filename, "r+");
%!    setTag (img, "Make", "test_tag");
%!    img.rewriteDirectory ();
%!    img.close ();
%!    img = Tiff (filename);
%!    assert (img.read(), uint8 ([210]));
%!    assert (getTag (img, "Make"), "test_tag");
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn)

## test one-pixel grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 1,
%!                         "BitsPerSample", 8));
%!    data = uint8 (randi (intmax ("uint8"), 1, 1));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [1, 1]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure to write to image without dimensions
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    data = uint8 (randi (intmax ("uint8"), 1, 1));
%!    fail ("writeEncodedStrip (img, 1, data)", "Failed to read image width");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test one row grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 10,
%!                         "BitsPerSample", 8));
%!    data = uint8 (reshape (1:10, [1, 10]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [1, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test wrong size of row
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 10,
%!                         "BitsPerSample", 8));
%!    data = uint8 (reshape (1:13, [1, 13]));
%!    fail ("writeEncodedStrip (img, 1, data)", "warning",
%!          "The image width is 10 but the input has 13 columns.");
%!    img.close ();
%!    verify_data (filename, data, [1, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test one strip grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "BitsPerSample", 8));
%!    data = uint8 (reshape (1:100, [10, 10]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test wrong height of strip
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "BitsPerSample", 8));
%!    data = uint8 (reshape (1:110, [11, 10]));
%!    fail ("writeEncodedStrip (img, 1, data)", "warning",
%!          "The strip is composed of 10 rows but the input has 11 rows.");
%!    img.close ();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test one strip RGB image chunky planes (RGBRGBRGB)
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "BitsPerSample", 8, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test wrong number of channels
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "BitsPerSample", 8, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:400, [10, 10, 4]));
%!    fail ("writeEncodedStrip (img, 1, data)", "warning",
%!          "The strip is composed of 3 channels but the input has 4 channels.");
%!    img.close ();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test one strip RGB image separate planes (RRRGGGBBB)
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "BitsPerSample", 8, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 2,
%!                         "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    for i = 1:3
%!      writeEncodedStrip (img, i, data(:,:,i));
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test 1-bit BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test 16-bit grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16));
%!    data = uint16 (reshape (1:400, [20, 20]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test 32-bit grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 32));
%!    data = uint32 (reshape (1:400, [20, 20]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test 16-bit RGB image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1200, [20, 20, 3]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test 32-bit RGB image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 32, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint32 (reshape (1:1200, [20, 20, 3]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure unsupported bit-depth
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 24));
%!    data = uint16 (reshape (1:400, [20, 20]));
%!    fail ("writeEncodedStrip (img, 1, data)", "Unsupported bit depth");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure unsupported BiLevel number of channels
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "SamplesPerPixel", 3));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    fail ("writeEncodedStrip (img, 1, data)",
%!          "Bi-Level images must have one channel only");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test multi-strip BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                         "RowsPerStrip", 2));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    for strip = 1:5
%!      writeEncodedStrip (img, strip, data(strip * 2 - 1: strip * 2, :));
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test multi-strip grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "RowsPerStrip", 3));
%!    data = uint16 (reshape (1:400, [20, 20]));
%!    for strip = 1:7
%!      writeEncodedStrip (img, strip, data(strip * 3 - 2: min(strip * 3, 20), :));
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test multi-strip RGB image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "RowsPerStrip", 2, "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1200, [20, 20, 3]));
%!    for strip = 1:10
%!      writeEncodedStrip (img, strip, data(strip * 2 - 1: strip * 2, :, :));
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test multi-strip RGB separate planes image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "RowsPerStrip", 3, "PlanarConfiguration", 2,
%!                         "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1200, [20, 20, 3]));
%!    strip = 1;
%!    for sample = 1:3
%!      for row = 1:3:20
%!        writeEncodedStrip (img, strip, data(row: min(row + 2, 20), :, sample));
%!        strip = strip + 1;
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test single-precision image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 32, "SampleFormat", 3));
%!    data = single (reshape (1:400, [20, 20]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test double-precision image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 64, "SampleFormat", 3));
%!    data = double (reshape (1:400, [20, 20]));
%!    writeEncodedStrip (img, 1, data);
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure unsupported floating-point bit depth
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SampleFormat", 3));
%!    data = double (reshape (1:400, [20, 20]));
%!    fail ("writeEncodedStrip (img, 1, data)",
%!          "Unsupported bit depth for floating-point images");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure data-type and bit-depth mismatch
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1,
%!                         "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:1200, [20, 20, 3]));
%!    fail ("writeEncodedStrip (img, 1, data)", "Only uint16 data is allowed for uint images with bit depth of 16");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure writing to img read-only file
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 1,
%!                         "BitsPerSample", 8));
%!    data = uint8 (1);
%!    writeEncodedStrip (img, 1, data);
%!    img.close();
%!    img = Tiff (filename, "r");
%!    fail ("writeEncodedStrip(img, 1, [1])",
%!          "Can't write data to a file opened in read-only mode");
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure unsupported sample format
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SampleFormat", 5));
%!    data = double (reshape (1:400, [20, 20]));
%!    fail ("writeEncodedStrip (img, 1, data)", "Unsupported sample format");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure wrong strip number
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "RowsPerStrip", 5));
%!    strip_data = uint16 (reshape (1:100, [5, 20]));
%!    fail ("writeEncodedStrip (img, 5, strip_data)",
%!          "Strip number out of range");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure writing strips to tiled image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "TileLength", 16,
%!                         "TileWidth", 16));
%!    data = uint8 (reshape (1:400, [20, 20]));
%!    fail ("writeEncodedStrip (img, 1, data)",
%!          "Can't write strips to a tiled image");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 32, "ImageWidth", 32,
%!                         "TileLength", 16, "TileWidth", 16));
%!    data = logical (repmat ([1,0,0,1,0,1,1,0], [32, 4]));
%!    tile = 1;
%!    for row = 1:16:32
%!      for col = 1:16:32
%!        writeEncodedTile (img, tile, data(row:row+15, col:col+15));
%!        tile = tile + 1;
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [32, 32]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 32, "ImageWidth", 32,
%!                         "BitsPerSample", 16, "TileLength", 16,
%!                         "TileWidth", 16));
%!    data = uint16 (reshape (1:1024, [32, 32]));
%!    tile = 1;
%!    for row = 1:16:32
%!      for col = 1:16:32
%!        writeEncodedTile (img, tile, data(row:row+15, col:col+15));
%!        tile = tile + 1;
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [32, 32]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled grayscale image with padding
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "TileLength", 16,
%!                         "TileWidth", 16));
%!    data = uint16 (reshape (1:400, [20, 20]));
%!    tile = 1;
%!    for row = 1:16:32
%!      for col = 1:16:32
%!        writeEncodedTile (img, tile, data(row:min(row+15, 20),
%!                                          col:min(col+15, 20)));
%!        tile = tile + 1;
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled RGB image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1, "TileLength", 16,
%!                         "TileWidth", 16, "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1200, [20, 20, 3]));
%!    tile = 1;
%!    for row = 1:16:32
%!      for col = 1:16:32
%!        writeEncodedTile (img, tile, data(row:min(row+15,20),
%!                                          col:min(col+15,20), :));
%!        tile = tile + 1;
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled RGB image separate planes
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 2, "TileLength", 16,
%!                         "TileWidth", 16, "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1200, [20, 20, 3]));
%!    tile = 1;
%!    for channel=1:3
%!      for row = 1:16:32
%!        for col = 1:16:32
%!          writeEncodedTile (img, tile, data(row:min(row+15,20),
%!                                            col:min(col+15,20), channel));
%!          tile = tile + 1;
%!        endfor
%!      endfor
%!    endfor
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure writing tiles to stripped image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16));
%!    data = uint8 (reshape (1:400, [20, 20]));
%!    fail ("writeEncodedTile (img, 1, data)",
%!          "Can't write tiles to a stripped image");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test tiled image wrong tile dimensions
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                         "PlanarConfiguration", 1, "TileLength", 16,
%!                         "TileWidth", 16, "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:1600, [20, 20, 4]));
%!    tile = 1;
%!    for row = 1:16:32
%!      for col = 1:16:32
%!        writeEncodedTile (img, tile, data(row:min(row+15,20),
%!                                          col:min(col+15,20), 1:3));
%!        tile = tile + 1;
%!      endfor
%!    endfor
%!    fail ("writeEncodedTile (img, 1, data(1:18,1:16,1:3))", "warning",
%!          "The tile is composed of 16 rows but input has 18 rows");
%!    fail ("writeEncodedTile (img, 1, data(1:16,1:20,1:3))", "warning",
%!          "The tile is composed of 16 columns but input has 20 columns");
%!    fail ("writeEncodedTile (img, 1, data(1:16,1:16,:))", "warning",
%!          "The tile is composed of 3 channels but input has 4 channels");
%!    img.close ();
%!    verify_data (filename, data, [20, 20, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test failure wrong tile number
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
%!                         "BitsPerSample", 16, "TileWidth", 16,
%!                         "TileLength", 16));
%!    tile_data = uint16 (reshape (1:256, [16, 16]));
%!    fail ("writeEncodedTile (img, 5, tile_data)",
%!          "Tile number out of range");
%!    img.close ();
%!  endfunction
%!  file_wrapper (@test_fn);

## test isTiled returns the correct value
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    assert (isTiled (img), logical (0));
%!    setTag (img, "TileLength", 16);
%!    setTag (img, "TileWidth", 16);
%!    assert (isTiled (img), logical (1));
%!  endfunction
%!  file_wrapper (@test_fn);

## test numberOfStrips returns the correct value
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageWidth", 10, "ImageLength", 10));
%!    assert (numberOfStrips (img), 1);
%!    setTag (img, "RowsPerStrip", 2);
%!    assert (numberOfStrips (img), 5);
%!    setTag (img, "RowsPerStrip", 4);
%!    assert (numberOfStrips (img), 3);
%!    setTag (img, "TileLength", 16);
%!    setTag (img, "TileWidth", 16);
%!    fail ("numberOfStrips (img)", "The image is tiled not stripped");
%!  endfunction
%!  file_wrapper (@test_fn);

## test numberOfTiles returns the correct value
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageWidth", 20, "ImageLength", 20,
%!                         "TileLength", 16, "TileWidth", 16));
%!    assert (numberOfTiles (img), 4);
%!    setTag (img, "TileLength", 32);
%!    assert (numberOfTiles (img), 2);
%!    setTag (img, "TileWidth", 32);
%!    assert (numberOfTiles (img), 1);
%!    img = Tiff (filename, "w");
%!    fail ("numberOfTiles (img)", "The image is stripped not tiled");
%!  endfunction
%!  file_wrapper (@test_fn);

## test computeStrip returns the correct value
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageWidth", 10, "ImageLength", 10,
%!                         "RowsPerStrip", 2, "BitsPerSample", 8,
%!                         "SamplesPerPixel", 3, "PlanarConfiguration", 1));
%!    assert (computeStrip (img, 1), 1);
%!    assert (computeStrip (img, 2), 1);
%!    assert (computeStrip (img, 0), 1);
%!    assert (computeStrip (img, 10), 5);
%!    assert (computeStrip (img, 11), 5);
%!    setTag (img, "PlanarConfiguration", 2);
%!    ## This is need for the tag to take effect, should be
%!    ## replaced by rewriteDirectory
%!    writeEncodedStrip (img, 1, uint8 (reshape (1:20, [2, 10])));
%!    assert (computeStrip (img, 1, 2), 6);
%!    assert (computeStrip (img, 100, 1), 5);
%!    img = Tiff (filename, "w");
%!    setTag (img, "TileWidth", 16);
%!    setTag (img, "TileLength", 16);
%!    fail ("computeStrip (img, 1, 1)", "The image is tiled not stripped");
%!  endfunction
%!  file_wrapper (@test_fn);

## test computeTile returns the correct value
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct ("ImageWidth", 20, "ImageLength", 20,
%!                         "BitsPerSample", 8, "SamplesPerPixel", 3,
%!                         "TileLength", 16, "TileWidth", 16,
%!                         "PlanarConfiguration", 1));
%!    assert (computeTile (img, [1, 1]), 1);
%!    assert (computeTile (img, [2, 2]), 1);
%!    assert (computeTile (img, [0, 0]), 1);
%!    assert (computeTile (img, [8, 17]), 2);
%!    assert (computeTile (img, [19, 10]), 3);
%!    assert (computeTile (img, [17, 17]), 4);
%!    assert (computeTile (img, [100, 100]), 4);
%!    setTag (img, "PlanarConfiguration", 2);
%!    ## This is need for the tag to take effect, should be
%!    ## replaced by rewriteDirectory
%!    writeEncodedTile (img, 1, uint8 (reshape (1:256, [16, 16])));
%!    assert (computeTile (img, [1, 1], 2), 5);
%!    assert (computeTile (img, [100, 100], 1), 4);
%!    img = Tiff (filename, "w");
%!    fail ("computeTile (img, 1, 1)", "The image is stripped not tiled");
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method one pixel bilevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 1, "ImageWidth", 1));
%!    write (img, logical ([1]));
%!    img.close();
%!    verify_data (filename, logical ([1]), [1, 1]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method one strip bilevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method multi-strip bilevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "RowsPerStrip", 3));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method one pixel grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 1, "ImageWidth", 1,
%!                        "BitsPerSample", 8));
%!    write (img, uint8 ([255]));
%!    img.close();
%!    verify_data (filename, uint8 ([255]), [1, 1]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method one strip grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 8));
%!    data = uint8 (reshape (1:100, [10, 10]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method multi-strip grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 8, "RowsPerStrip", 3));
%!    data = uint8 (reshape (1:100, [10, 10]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method multi-strip RGB image chunky
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 8, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 1,
%!                        "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method multi-strip RGB image separate
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 8, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 2,
%!                        "PhotometricInterpretation", 2));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method 16-bit multi-strip image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 16, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 1,
%!                        "PhotometricInterpretation", 2));
%!    data = uint16 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method 32-bit multi-strip image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 32, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 1,
%!                        "PhotometricInterpretation", 2));
%!    data = uint32 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method single-precision image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 32, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 1,
%!                        "PhotometricInterpretation", 2, "SampleFormat", 3));
%!    data = single (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method single-precision image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 64, "RowsPerStrip", 3,
%!                        "SamplesPerPixel", 3, "PlanarConfiguration", 1,
%!                        "PhotometricInterpretation", 2, "SampleFormat", 3));
%!    data = double (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write signed integer image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag (img, struct (
%!      "ImageLength", 10, "ImageWidth", 10, "SamplesPerPixel", 3,
%!      "BitsPerSample", 16, "SampleFormat", Tiff.SampleFormat.Int,
%!      "PhotometricInterpretation", Tiff.Photometric.RGB,
%!      "PlanarConfiguration", Tiff.PlanarConfiguration.Chunky));
%!    data = int16 (reshape (-150:149, [10, 10, 3]));
%!    write (img, data);
%!    img.close ();
%!    verify_data (filename, data, [10, 10, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method tiled BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [40, 4]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method tiled grayscale image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 16));
%!    data = uint16 (reshape (1:1600, [40, 40]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method tiled RGB image chunky
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 1));
%!    data = uint16 (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method tiled RGB image separate
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 2));
%!    data = uint16 (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method 32-bit tiled image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 32, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 1));
%!    data = uint32 (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method single-precision tiled image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 32, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 1, "SampleFormat", 3));
%!    data = single (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test write method double-precision tiled image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 64, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 1, "SampleFormat", 3));
%!    data = double (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    img.close();
%!    verify_data (filename, data, [40, 40, 3]);
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedStrip BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "RowsPerStrip", 6));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [10, 1]));
%!    write (img, data);
%!    s1 = readEncodedStrip (img, 1);
%!    s2 = readEncodedStrip (img, 2);
%!    assert ([s1;s2], data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedStrip RGB Chunky
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2, "RowsPerStrip", 6,
%!                        "PlanarConfiguration", 1));
%!    data = uint16 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    s1 = readEncodedStrip (img, 1);
%!    s2 = readEncodedStrip (img, 2);
%!    assert ([s1;s2], data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedStrip RGB Separated
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 10, "ImageWidth", 10,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2, "RowsPerStrip", 6,
%!                        "PlanarConfiguration", 2));
%!    data = uint16 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    s = cell (6, 1);
%!    for i=1:6
%!      s{i} = readEncodedStrip (img, i);
%!    endfor
%!    data2 = cat (3, [s{1}; s{2}], [s{3}; s{4}], [s{5}; s{6}]);
%!    assert (data2, data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedTile BiLevel image
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16));
%!    data = logical (repmat ([1,0,0,0,1,0,1,1,1,0], [40, 4]));
%!    write (img, data);
%!    t = cell (9, 1);
%!    for i=1:9
%!      t{i} = readEncodedTile (img, i);
%!    endfor
%!    data2 = cat(1, cat (2, t{1}, t{2}, t{3}), cat (2, t{4}, t{5}, t{6}),
%!                cat (2, t{7}, t{8}, t{9}));
%!    assert (data2, data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedTile RGB Chunky
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 1));
%!    data = uint16 (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    t = cell (9, 1);
%!    for i=1:9
%!      t{i} = readEncodedTile (img, i);
%!    endfor
%!    data2 = cat(1, cat (2, t{1}, t{2}, t{3}), cat (2, t{4}, t{5}, t{6}),
%!                cat (2, t{7}, t{8}, t{9}));
%!    assert (data2, data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readEncodedTile RGB Separated
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct ("ImageLength", 40, "ImageWidth", 40,
%!                        "TileWidth", 16, "TileLength", 16,
%!                        "BitsPerSample", 16, "SamplesPerPixel", 3,
%!                        "PhotometricInterpretation", 2,
%!                        "PlanarConfiguration", 2));
%!    data = uint16 (reshape (1:4800, [40, 40, 3]));
%!    write (img, data);
%!    data2 = uint16 (zeros (40, 40, 3));
%!    tile = 1;
%!    for sample=1:3
%!      for row=1:16:40
%!        for col=1:16:40
%!          data2(row: min(40, row + 15), col: min(40, col + 15), sample)...
%!            = readEncodedTile(img, tile);
%!          tile += 1;
%!        endfor
%!      endfor
%!    endfor
%!    assert (data2, data);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAImage
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1
%!    ));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAImage (img);
%!    assert (rgb, data);
%!    assert (alpha, uint8 (repmat ([255], [10, 10])));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAImage with orientation
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "Orientation", Tiff.Orientation.BottomRight
%!    ));
%!    data = uint8 (reshape (1:300, [10, 10, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAImage (img);
%!    assert (rgb, data(end:-1:1, end:-1:1, :));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAImage with alpha
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 4,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "ExtraSamples", 1
%!    ));
%!    data = uint8 (randi ([0,255], [10, 10, 4]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAImage (img);
%!    assert (rgb, data(:,:,1:3));
%!    assert (alpha, data(:,:,4));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAStrip
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "RowsPerStrip", 3
%!    ));
%!    data = uint8 (randi ([0,255], [10, 10, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAStrip (img, 1);
%!    assert (rgb, data(1:3,:,:));
%!    assert (alpha, uint8 (repmat ([255], [3, 10])));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAStrip with orientation
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "RowsPerStrip", 3,
%!      "Orientation", Tiff.Orientation.BottomRight
%!    ));
%!    data = uint8 (randi ([0,255], [10, 10, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAStrip (img, 1);
%!    assert (rgb, data(3:-1:1,end:-1:1,:));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAStrip boundary strip
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "RowsPerStrip", 3
%!    ));
%!    data = uint8 (randi ([0,255], [10, 10, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAStrip (img, 10);
%!    assert (rgb, data(10,:,:));
%!    assert (alpha, uint8 (repmat ([255], [1, 10])));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBAStrip with alpha
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SamplesPerPixel", 4,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "RowsPerStrip", 3,
%!      "ExtraSamples", 1
%!    ));
%!    data = uint8 (randi ([0,255], [10, 10, 4]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBAStrip (img, 1);
%!    assert (rgb, data(1:3,:, 1:3));
%!    assert (alpha, data (1:3, :, 4));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBATile
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 40, "ImageWidth", 40,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "TileLength", 16, "TileWidth", 32
%!    ));
%!    data = uint8 (randi ([0,255], [40, 40, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBATile (img, 1, 1);
%!    assert (rgb, data(1:16,1:32,:));
%!    assert (alpha, uint8 (repmat ([255], [16, 32])));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBATile ith orientation
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 40, "ImageWidth", 40,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "TileLength", 16, "TileWidth", 32,
%!      "Orientation", Tiff.Orientation.BottomRight
%!    ));
%!    data = uint8 (randi ([0,255], [40, 40, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBATile (img, 1, 1);
%!    assert (rgb, data(16:-1:1,32:-1:1,:));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBATile boundary tile
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 40, "ImageWidth", 40,
%!      "BitsPerSample", 8, "SamplesPerPixel", 3,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "TileLength", 16, "TileWidth", 32
%!    ));
%!    data = uint8 (randi ([0,255], [40, 40, 3]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBATile (img, 40, 40);
%!    assert (rgb, data(33:end,33:end,:));
%!    assert (alpha, uint8 (repmat ([255], [8, 8])));
%!  endfunction
%!  file_wrapper (@test_fn);

## test readRGBATile ith alpha
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct (
%!      "ImageLength", 40, "ImageWidth", 40,
%!      "BitsPerSample", 8, "SamplesPerPixel", 4,
%!      "PhotometricInterpretation", 2,
%!      "PlanarConfiguration", 1,
%!      "TileLength", 16, "TileWidth", 32,
%!      "ExtraSamples", 1
%!    ));
%!    data = uint8 (randi ([0,255], [40, 40, 4]));
%!    write (img, data);
%!    [rgb, alpha] = readRGBATile (img, 1, 1);
%!    assert (rgb, data(1:16,1:32,1:3));
%!    assert (alpha, data(1:16,1:32,4));
%!  endfunction
%!  file_wrapper (@test_fn);

## test directory manipulation
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    tags = struct (
%!      "ImageLength", 10, "ImageWidth", 10, "BitsPerSample", 8
%!    );
%!    setTag (img, tags);
%!    data = uint8 (reshape (1:100, [10, 10]));
%!    write(img, data);
%!    img.writeDirectory ();
%!    setTag (img, tags);
%!    write(img, data);
%!    img.close();
%!    img = Tiff (filename);
%!    assert (img.currentDirectory, 1);
%!    assert (img.lastDirectory, logical (0));
%!    img.nextDirectory ();
%!    assert (img.currentDirectory, 2);
%!    assert (img.lastDirectory, logical (1));
%!    img.setDirectory (1);
%!    assert (img.currentDirectory, 1);
%!  endfunction
%!  file_wrapper (@test_fn)

## test creating and reading subdirectories
%!testif HAVE_TIFF
%!  function test_fn (filename)
%!    img = Tiff (filename, "w");
%!    setTag(img, struct(
%!      "ImageLength", 10, "ImageWidth", 10,
%!      "BitsPerSample", 8, "SubIFD", 1
%!    ));
%!    data = uint8 (reshape (1:100, [10, 10]));
%!    write (img, data);
%!    img.writeDirectory ();
%!    setTag(img, struct(
%!      "ImageLength", 15, "ImageWidth", 15,
%!      "BitsPerSample", 8
%!    ));
%!    data_subdir = uint8 (reshape (1:225, [15, 15]));
%!    write (img, data_subdir);
%!    img.close();
%!    img = Tiff (filename);
%!    assert (img.read(), data);
%!    offsets = getTag (img, "SubIFD");
%!    img.setSubDirectory (offsets (1));
%!    assert (img.read(), data_subdir);
%!    img.close();
%!  endfunction
%!  file_wrapper (@test_fn)