classdef Tiff < handle
  properties (Constant = true)
    TagID = struct(
        "SubFileType", 254,
        "ImageWidth", 256,
        "ImageLength", 257,
        "BitsPerSample", 258,
        "Compression", 259,
        "Photometric", 262,
        "Thresholding", 263,
        "FillOrder", 266,
        "DocumentName", 269,
        "ImageDescription", 270,
        "Make", 271,
        "Model", 272,
        "StripOffsets", 273,
        "Orientation", 274,
        "SamplesPerPixel", 277,
        "RowsPerStrip", 278,
        "StripByteCounts", 279,
        "MinSampleValue", 280,
        "MaxSampleValue", 281,
        "XResolution", 282,
        "YResolution", 283,
        "PlanarConfiguration", 284,
        "PageName", 285,
        "XPosition", 286,
        "YPosition", 287,
        "GrayResponseUnit", 290,
        'GrayResponseCurve', 291,
        "Group3Options", 292,
        "Group4Options", 293,
        "ResolutionUnit", 296,
        "PageNumber", 297,
        "TransferFunction", 301,
        "Software", 305,
        "DateTime", 306,
        "Artist", 315,
        "HostComputer", 316,
        "WhitePoint", 318,
        "PrimaryChromaticities", 319,
        "ColorMap", 320,
        "HalfToneHints", 321,
        "TileWidth", 322,
        "TileLength", 323,
        "TileOffsets", 324,
        "TileByteCounts", 325,
        "SubIFD", 330,
        "InkSet", 332,
        "InkNames", 333,
        "NumberOfInks", 334,
        "DotRange", 336,
        "TargetPrinter", 337,
        "ExtraSamples", 338,
        "SampleFormat", 339,
        "SMinSampleValue", 340,
        "SMaxSampleValue", 341,
        "YCbCrCoefficients", 529,
        "YCbCrSubSampling", 530,
        "YCbCrPositioning", 531,
        "ReferenceBlackWhite", 532,
        "XMP", 700,
        "ImageDepth", 32997,
        "Copyright", 33432,
        "RichTIFFIPTC", 33723,
        "Photoshop", 34377,
        "ICCProfile", 34675,
        "SToNits", 37439,
        "JPEGQuality", 65537,
        "JPEGColorMode", 65538,
        "ZipQuality", 65557,
        "SGILogDataFmt", 65560
    )
  endproperties

  properties (Access = private)
    tiff_handle;
    closed=false;
  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)
      if (! t.closed)
        __close_tiff__ (t.tiff_handle);
        t.closed = true;
      endif
    endfunction

    function tag = getTag (t, tag_name)
      if (t.closed)
        error ("Image file was closed");
      endif
      tag = __tiff_get_tag__ (t.tiff_handle, tag_name);
    endfunction

    function setTag (t, varargin)
      if (t.closed)
        error ("Image file was closed");
      endif
      __tiff_set_tag__ (t.tiff_handle, varargin{:});
    endfunction

    function argout = read (t)
      if (t.closed)
        error ("Image file was closed");
      endif
      argout = __tiff_read__ (t.tiff_handle);
    endfunction

    function stripData = readEncodedStrip (t, stripNumber)
      if (t.closed)
        error ("Image file was closed");
      endif
      stripData = __tiff_read_encoded_strip__ (t.tiff_handle, stripNumber);
    endfunction

    function tileData = readEncodedTile (t, tileNumber)
      if (t.closed)
        error ("Image file was closed");
      endif
      tileData = __tiff_read_encoded_tile__ (t.tiff_handle, tileNumber);
    endfunction

    function write (t, imageData)
      if (t.closed)
        error ("Image file was closed");
      endif
      __tiff_write__ (t.tiff_handle, imageData);
    endfunction

    function writeEncodedStrip (t, stripNumber, imageData)
      if (t.closed)
        error ("Image file was closed");
      endif
      __tiff_write_encoded_strip__ (t.tiff_handle, stripNumber, imageData);
    endfunction

    function writeEncodedTile (t, tileNumber, imageData)
      if (t.closed)
        error ("Image file was closed");
      endif
      __tiff_write_encoded_tile__ (t.tiff_handle, tileNumber, imageData);
    endfunction

    function tf = isTiled (t)
      if (t.closed)
        error ("Image file was closed");
      endif
      tf = __tiff_is_tiled__ (t.tiff_handle);
    endfunction

    function numStrips = numberOfStrips (t)
      if (t.closed)
        error ("Image file was closed");
      endif
      numStrips = __tiff_number_of_strips__ (t.tiff_handle);
    endfunction

    function numTiles = numberOfTiles (t)
      if (t.closed)
        error ("Image file was closed");
      endif
      numTiles = __tiff_number_of_tiles__ (t.tiff_handle);
    endfunction

    function stripNumber = computeStrip (t, varargin)
      if (t.closed)
        error ("Image file was closed");
      endif
      stripNumber = __tiff_compute_strip__ (t.tiff_handle, varargin{:});
    endfunction

    function tileNumber = computeTile (t, varargin)
      if (t.closed)
        error ("Image file was closed");
      endif
      tileNumber = __tiff_compute_tile__ (t.tiff_handle, varargin{:});
    endfunction

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

  methods (Static = true)
    function versionString = getVersion()
      versionString = __tiff_version__ ();
    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 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 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)",
%!          "Floating point images are only supported for bit depths of 32 and 64");
%!    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 ("test.tif", "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 ("test.tif", "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 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);
