changeset 31147:7af78a63d3c3

Tiff.m: added test for writing and reading tiled images.
author magedrifaat <magedrifaat@gmail.com>
date Sun, 31 Jul 2022 20:41:02 +0200
parents 50402b8dfb4a
children 4bc9a1938f9a
files libinterp/dldfcn/__tiff__.cc scripts/io/Tiff.m
diffstat 2 files changed, 225 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Sun Jul 31 18:34:59 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Sun Jul 31 20:41:02 2022 +0200
@@ -52,6 +52,8 @@
                                    &bits_per_sample))
         error ("Failed to read the BitsPerSample tag");
       
+      // TODO(maged): this doesn't really work for writing as LibTIFF will
+      // refuse to write unless the tag is set
       if (! TIFFGetField (tif, TIFFTAG_PLANARCONFIG,
                           &planar_configuration))
         // LibTIFF has a bug where it incorrectly returns 0 as a default
--- a/scripts/io/Tiff.m	Sun Jul 31 18:34:59 2022 +0200
+++ b/scripts/io/Tiff.m	Sun Jul 31 20:41:02 2022 +0200
@@ -207,7 +207,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 1,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 8));
 %!    data = uint8 (randi (intmax ("uint8"), 1, 1));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -230,7 +230,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 10,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 8));
 %!    data = uint8 (reshape (1:10, [1, 10]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -243,7 +243,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 10,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "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.");
@@ -257,7 +257,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 8));
 %!    data = uint8 (reshape (1:100, [10, 10]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -270,7 +270,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 10, "ImageWidth", 10,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "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.");
@@ -327,12 +327,24 @@
 %!  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, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 16));
 %!    data = uint16 (reshape (1:400, [20, 20]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -345,7 +357,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 32, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 32));
 %!    data = uint32 (reshape (1:400, [20, 20]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -388,23 +400,50 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 24, "SamplesPerPixel", 1));
+%!                         "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, "SamplesPerPixel", 1,
-%!                         "RowsPerStrip", 2));
+%!                         "BitsPerSample", 16, "RowsPerStrip", 2));
 %!    data = uint16 (reshape (1:400, [20, 20]));
-%!    for row = 1:2:20
-%!      writeEncodedStrip (img, row / 2, data(row: row + 1, :));
+%!    for strip = 1:10
+%!      writeEncodedStrip (img, strip, data(strip * 2 - 1: strip * 2, :));
 %!    endfor
 %!    img.close ();
 %!    verify_data (filename, data, [20, 20]);
@@ -420,8 +459,8 @@
 %!                         "RowsPerStrip", 2, "PlanarConfiguration", 1,
 %!                         "PhotometricInterpretation", 2));
 %!    data = uint16 (reshape (1:1200, [20, 20, 3]));
-%!    for row = 1:2:20
-%!      writeEncodedStrip (img, row / 2, data(row: row + 1, :, :));
+%!    for strip = 1:10
+%!      writeEncodedStrip (img, strip, data(strip * 2 - 1: strip * 2, :, :));
 %!    endfor
 %!    img.close ();
 %!    verify_data (filename, data, [20, 20, 3]);
@@ -454,8 +493,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 32, "SamplesPerPixel", 1,
-%!                         "SampleFormat", 3));
+%!                         "BitsPerSample", 32, "SampleFormat", 3));
 %!    data = single (reshape (1:400, [20, 20]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -468,8 +506,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 64, "SamplesPerPixel", 1,
-%!                         "SampleFormat", 3));
+%!                         "BitsPerSample", 64, "SampleFormat", 3));
 %!    data = double (reshape (1:400, [20, 20]));
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close ();
@@ -482,8 +519,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 16, "SamplesPerPixel", 1,
-%!                         "SampleFormat", 3));
+%!                         "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");
@@ -510,7 +546,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 1, "ImageWidth", 1,
-%!                         "BitsPerSample", 8, "SamplesPerPixel", 1));
+%!                         "BitsPerSample", 8));
 %!    data = uint8 (1);
 %!    writeEncodedStrip (img, 1, data);
 %!    img.close();
@@ -525,8 +561,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 16, "SamplesPerPixel", 1,
-%!                         "SampleFormat", 5));
+%!                         "BitsPerSample", 16, "SampleFormat", 5));
 %!    data = double (reshape (1:400, [20, 20]));
 %!    fail ("writeEncodedStrip (img, 1, data)", "Unsupported sample format");
 %!    img.close ();
@@ -538,8 +573,7 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 16, "SamplesPerPixel", 1,
-%!                         "RowsPerStrip", 5));
+%!                         "BitsPerSample", 16, "RowsPerStrip", 5));
 %!    strip_data = uint16 (reshape (1:100, [5, 20]));
 %!    fail ("writeEncodedStrip (img, 5, strip_data)",
 %!          "Strip number out of range");
@@ -552,11 +586,172 @@
 %!  function test_fn (filename)
 %!    img = Tiff (filename, "w");
 %!    setTag (img, struct ("ImageLength", 20, "ImageWidth", 20,
-%!                         "BitsPerSample", 16, "SamplesPerPixel", 1,
-%!                         "TileLength", 16, "TileWidth", 16));
+%!                         "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);
\ No newline at end of file
+%!  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);