From 85ece697e88fb6a32a740fc8aadddb1259fdc55c Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Tue, 7 Jan 2025 11:17:51 -0800 Subject: [PATCH] testing: better testing coverage of null image reader/writer (#4578) This improves the mediocre testing line coverage in nullimageio.cpp from 50% to 95%. * Test writing * Test reading of tiled and MIP-mapped null images * Test setting and reading of attributes * Simplify some code * Along the way, identified and fixed a nullimage bug -- it was answering that it supported "rectangles" but had no write_rectangle method. Testing works! Signed-off-by: Larry Gritz --- src/null.imageio/nullimageio.cpp | 29 +++++++++++++---------------- testsuite/null/ref/out.txt | 29 +++++++++++++++++++++++++++-- testsuite/null/run.py | 8 +++++++- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/null.imageio/nullimageio.cpp b/src/null.imageio/nullimageio.cpp index 0454a0483d..89afc9c0c6 100644 --- a/src/null.imageio/nullimageio.cpp +++ b/src/null.imageio/nullimageio.cpp @@ -24,7 +24,10 @@ class NullOutput final : public ImageOutput { NullOutput() {} ~NullOutput() override {} const char* format_name(void) const override { return "null"; } - int supports(string_view /*feature*/) const override { return true; } + int supports(string_view feature) const override + { + return feature != "rectangles"; + } bool open(const std::string& /*name*/, const ImageSpec& spec, OpenMode /*mode*/) override { @@ -316,10 +319,10 @@ NullInput::open(const std::string& name, ImageSpec& newspec, } } + m_value.resize(m_topspec.pixel_bytes()); // default fills with 0's if (fvalue.size()) { // Convert float to the native type fvalue.resize(m_topspec.nchannels, 0.0f); - m_value.resize(m_topspec.pixel_bytes()); convert_pixel_values(TypeFloat, fvalue.data(), m_topspec.format, m_value.data(), m_topspec.nchannels); } @@ -365,13 +368,10 @@ bool NullInput::read_native_scanline(int /*subimage*/, int /*miplevel*/, int /*y*/, int /*z*/, void* data) { - if (m_value.size()) { - size_t s = m_spec.pixel_bytes(); - for (int x = 0; x < m_spec.width; ++x) - memcpy((char*)data + s * x, m_value.data(), s); - } else { - memset(data, 0, m_spec.scanline_bytes()); - } + size_t s = m_spec.pixel_bytes(); + OIIO_DASSERT(m_value.size() == s); + for (int x = 0; x < m_spec.width; ++x) + memcpy((char*)data + s * x, m_value.data(), s); return true; } @@ -381,13 +381,10 @@ bool NullInput::read_native_tile(int /*subimage*/, int /*miplevel*/, int /*x*/, int /*y*/, int /*z*/, void* data) { - if (m_value.size()) { - size_t s = m_spec.pixel_bytes(); - for (size_t x = 0, e = m_spec.tile_pixels(); x < e; ++x) - memcpy((char*)data + s * x, m_value.data(), s); - } else { - memset(data, 0, m_spec.tile_bytes()); - } + size_t s = m_spec.pixel_bytes(); + OIIO_DASSERT(m_value.size() == s); + for (size_t x = 0, e = m_spec.tile_pixels(); x < e; ++x) + memcpy((char*)data + s * x, m_value.data(), s); return true; } diff --git a/testsuite/null/ref/out.txt b/testsuite/null/ref/out.txt index ae32451d2b..f5ddf23f87 100644 --- a/testsuite/null/ref/out.txt +++ b/testsuite/null/ref/out.txt @@ -1,6 +1,12 @@ -Reading foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1 -foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1 : 640 x 480, 3 channel, uint8 null +Reading foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1&a=1&b=2.5&c=foo&string d=bar&e=float 3&f="baz" +foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1&a=1&b=2.5&c=foo&string d=bar&e=float 3&f="baz" : 640 x 480, 3 channel, uint8 null channel list: R, G, B + a: 1 + b: 2.5 + c: "foo" + d: "bar" + e: 3 + f: "baz" Stats Min: 64 128 255 (of 255) Stats Max: 64 128 255 (of 255) Stats Avg: 64.00 128.00 255.00 (of 255) @@ -11,3 +17,22 @@ foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1 : 640 x 480, 3 cha Constant: Yes Constant Color: 64.00 128.00 255.00 (of 255) Monochrome: No +Writing out.null +Reading bar.null?RES=128x128&CHANNELS=3&TILE=64x64&TEX=1&TYPE=uint16&PIXEL=0.25,0.5,1 +bar.null?RES=128x128&CHANNELS=3&TILE=64x64&TEX=1&TYPE=uint16&PIXEL=0.25,0.5,1 : 128 x 128, 3 channel, uint16 null + MIP-map levels: 128x128 64x64 32x32 16x16 8x8 4x4 2x2 1x1 + channel list: R, G, B + tile size: 64 x 64 + textureformat: "Plain Texture" + wrapmodes: "black,black" + Stats Min: 16384 32768 65535 (of 65535) + Stats Max: 16384 32768 65535 (of 65535) + Stats Avg: 16384.00 32768.00 65535.00 (of 65535) + Stats StdDev: 0.00 0.00 0.00 (of 65535) + Stats NanCount: 0 0 0 + Stats InfCount: 0 0 0 + Stats FiniteCount: 16384 16384 16384 + Constant: Yes + Constant Color: 16384.00 32768.00 65535.00 (of 65535) + Monochrome: No +Writing outtile.null diff --git a/testsuite/null/run.py b/testsuite/null/run.py index 24f135d099..9eb0cf1de6 100755 --- a/testsuite/null/run.py +++ b/testsuite/null/run.py @@ -5,4 +5,10 @@ # https://github.com/AcademySoftwareFoundation/OpenImageIO -command += oiiotool ('-v -info -stats "foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1"') +# Read and write null scanline and a tiled mipmap image +command += oiiotool ('-v -info -stats ' + + '"foo.null?RES=640x480&CHANNELS=3&TYPE=uint8&PIXEL=0.25,0.5,1&a=1&b=2.5&c=foo&string d=bar&e=float 3&f=\\\"baz\\\"" ' + + '-o out.null ' + + '"bar.null?RES=128x128&CHANNELS=3&TILE=64x64&TEX=1&TYPE=uint16&PIXEL=0.25,0.5,1" ' + + '-o:tile=64x64 outtile.null' + )