Skip to content

Commit 78aaf34

Browse files
authored
oiiotool testing and minor subimage/miplevel fixes (#3649)
* Add casual tests of oiiotool with no args (print brief usage message) and when an unknown command. * Also changed the meaning of -q (quiet mode) to be more quiet -- in particular, not to print the full help message for errors when quiet mode is used, only print the error. * oiiotool test sequence errors. * Test (and fix) --selectmip and --subimage with out of range indices
1 parent f099e19 commit 78aaf34

File tree

11 files changed

+160
-13
lines changed

11 files changed

+160
-13
lines changed

src/build-scripts/ci-test.bash

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,26 @@ set -ex
77
: ${CTEST_EXCLUSIONS:="broken"}
88
: ${CTEST_TEST_TIMEOUT:=180}
99

10-
$OpenImageIO_ROOT/bin/oiiotool --version --help || /bin/true
11-
12-
# Catch-all of some unit tests and args that aren't used elsewhere
10+
#
11+
# Try a few command line options to test them and also get some important
12+
# debugging info in the CI logs.
13+
#
14+
echo ; echo "Results of oiiotool --version:"
15+
$OpenImageIO_ROOT/bin/oiiotool --version || true
16+
echo ; echo "Results of oiiotool --help:"
17+
$OpenImageIO_ROOT/bin/oiiotool --help || true
18+
echo ; echo "Results of oiiotool with no args (should get short help message):"
19+
$OpenImageIO_ROOT/bin/oiiotool || true
20+
echo ; echo "Run unit tests and simple stats:"
1321
$OpenImageIO_ROOT/bin/oiiotool --unittest --list-formats --threads 0 \
14-
--cache 1000 --autotile --autopremult --runstats || /bin/true
22+
--cache 1000 --autotile --autopremult --runstats || true
23+
echo ; echo "Try unknown command:"
24+
$OpenImageIO_ROOT/bin/oiiotool -q --unknown || true
25+
1526

27+
#
28+
# Full test suite
29+
#
1630
echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
1731
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
1832
echo "Test exclusions '${CTEST_EXCLUSIONS}'"

src/oiiotool/imagerec.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,24 @@ ImageRec::ImageRec(ImageRec& img, int subimage_to_copy, int miplevel_to_copy,
6060
, m_imagecache(img.m_imagecache)
6161
{
6262
img.read();
63-
int first_subimage = std::max(0, subimage_to_copy);
63+
if (subimage_to_copy >= img.subimages()) {
64+
errorfmt("Selecting subimage {}, but there are only {} subimages",
65+
subimage_to_copy, img.subimages());
66+
subimage_to_copy = img.subimages() - 1;
67+
}
68+
int first_subimage = clamp(subimage_to_copy, 0, img.subimages() - 1);
6469
int subimages = (subimage_to_copy < 0) ? img.subimages() : 1;
6570
m_subimages.resize(subimages);
6671
for (int s = 0; s < subimages; ++s) {
67-
int srcsub = s + first_subimage;
68-
int first_miplevel = std::max(0, miplevel_to_copy);
72+
int srcsub = s + first_subimage;
73+
if (miplevel_to_copy >= img.miplevels(srcsub)) {
74+
errorfmt(
75+
"Selecting MIP level {} of subimage {}, which has only {} MIP levels",
76+
miplevel_to_copy, srcsub, img.miplevels(srcsub));
77+
miplevel_to_copy = img.miplevels(srcsub) - 1;
78+
}
79+
int first_miplevel = clamp(miplevel_to_copy, 0,
80+
img.miplevels(srcsub) - 1);
6981
int miplevels = (miplevel_to_copy < 0) ? img.miplevels(srcsub) : 1;
7082
m_subimages[s].m_miplevels.resize(miplevels);
7183
m_subimages[s].m_specs.resize(miplevels);

src/oiiotool/oiiotool.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ void
121121
Oiiotool::clear_options()
122122
{
123123
verbose = false;
124+
quiet = false;
124125
debug = false;
125126
dryrun = false;
126127
runstats = false;
@@ -3158,6 +3159,10 @@ action_selectmip(int argc, const char* argv[])
31583159
}
31593160

31603161
ImageRecRef newimg(new ImageRec(*ot.curimg, -1, miplevel, true, true));
3162+
if (newimg->has_error()) {
3163+
ot.error(command, newimg->geterror());
3164+
return 0;
3165+
}
31613166
ot.curimg = newimg;
31623167
return 0;
31633168
}
@@ -5777,7 +5782,7 @@ output_file(int /*argc*/, const char* argv[])
57775782
double optime = timer();
57785783
ot.num_outputs += 1;
57795784

5780-
if (ot.debug)
5785+
if (ot.debug && ot.runstats)
57815786
Strutil::print(" output took {} (total time {}, mem {})\n",
57825787
Strutil::timeintervalformat(optime, 2),
57835788
Strutil::timeintervalformat(ot.total_runtime(), 2),
@@ -6213,8 +6218,9 @@ Oiiotool::getargs(int argc, char* argv[])
62136218
});
62146219
ap.arg("-v", &ot.verbose)
62156220
.help("Verbose status messages");
6216-
ap.arg("-q %!", &ot.verbose)
6217-
.help("Quiet mode (turn verbose off)");
6221+
ap.arg("-q")
6222+
.help("Quiet mode (turn verbose off and reduce printed output)")
6223+
.action([](cspan<const char*>){ ot.verbose = false; ot.quiet = true; });
62186224
ap.arg("-n", &ot.dryrun)
62196225
.help("No saved output (dry run)");
62206226
ap.arg("--no-error-exit", ot.noerrexit)
@@ -6826,7 +6832,8 @@ Oiiotool::getargs(int argc, char* argv[])
68266832
if (ap.parse_args(argc, (const char**)argv) < 0) {
68276833
auto& errstream(ot.nostderr ? std::cout : std::cerr);
68286834
errstream << ap.geterror() << std::endl;
6829-
print_help(ap);
6835+
if (!ot.quiet)
6836+
print_help(ap);
68306837
// Repeat the command line, so if oiiotool is being called from a
68316838
// script, it's easy to debug how the command was mangled.
68326839
errstream << "\nFull command line was:\n> " << ot.full_command_line
@@ -6841,8 +6848,10 @@ Oiiotool::getargs(int argc, char* argv[])
68416848
// exit(EXIT_SUCCESS);
68426849
}
68436850
if (argc <= 1) {
6844-
ap.briefusage();
6845-
std::cout << "\nFor detailed help: oiiotool --help\n";
6851+
if (!ot.quiet) {
6852+
ap.briefusage();
6853+
std::cout << "\nFor detailed help: oiiotool --help\n";
6854+
}
68466855
ap.abort();
68476856
// exit(EXIT_SUCCESS);
68486857
}

src/oiiotool/oiiotool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Oiiotool {
7474
public:
7575
// General options
7676
bool verbose;
77+
bool quiet;
7778
bool debug;
7879
bool dryrun;
7980
bool runstats;

testsuite/oiiotool-control/ref/out.txt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,76 @@ Testing for i 5,10,2,8 (bad range):
118118
oiiotool ERROR: --for : Invalid range "5,10,2,8"
119119
Full command line was:
120120
> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio -echo "Testing for i 5,10,2,8 (bad range):" --for i 5,10,2,8 --echo " i = {i}" --endfor -echo " "
121+
SEQUENCE 0
122+
copyA.#.jpg -> ./copyA.0001.jpg
123+
copyB.#.jpg -> copyB.0001.jpg
124+
Reading ./copyA.0001.jpg
125+
Output: copyB.0001.jpg
126+
Writing copyB.0001.jpg
127+
128+
SEQUENCE 1
129+
copyA.#.jpg -> ./copyA.0002.jpg
130+
copyB.#.jpg -> copyB.0002.jpg
131+
Reading ./copyA.0002.jpg
132+
Output: copyB.0002.jpg
133+
Writing copyB.0002.jpg
134+
135+
SEQUENCE 2
136+
copyA.#.jpg -> ./copyA.0003.jpg
137+
copyB.#.jpg -> copyB.0003.jpg
138+
Reading ./copyA.0003.jpg
139+
Output: copyB.0003.jpg
140+
Writing copyB.0003.jpg
141+
142+
SEQUENCE 3
143+
copyA.#.jpg -> ./copyA.0004.jpg
144+
copyB.#.jpg -> copyB.0004.jpg
145+
Reading ./copyA.0004.jpg
146+
Output: copyB.0004.jpg
147+
Writing copyB.0004.jpg
148+
149+
SEQUENCE 4
150+
copyA.#.jpg -> ./copyA.0005.jpg
151+
copyB.#.jpg -> copyB.0005.jpg
152+
Reading ./copyA.0005.jpg
153+
Output: copyB.0005.jpg
154+
Writing copyB.0005.jpg
155+
156+
SEQUENCE 5
157+
copyA.#.jpg -> ./copyA.0006.jpg
158+
copyB.#.jpg -> copyB.0006.jpg
159+
Reading ./copyA.0006.jpg
160+
Output: copyB.0006.jpg
161+
Writing copyB.0006.jpg
162+
163+
SEQUENCE 6
164+
copyA.#.jpg -> ./copyA.0007.jpg
165+
copyB.#.jpg -> copyB.0007.jpg
166+
Reading ./copyA.0007.jpg
167+
Output: copyB.0007.jpg
168+
Writing copyB.0007.jpg
169+
170+
SEQUENCE 7
171+
copyA.#.jpg -> ./copyA.0008.jpg
172+
copyB.#.jpg -> copyB.0008.jpg
173+
Reading ./copyA.0008.jpg
174+
Output: copyB.0008.jpg
175+
Writing copyB.0008.jpg
176+
177+
SEQUENCE 8
178+
copyA.#.jpg -> ./copyA.0009.jpg
179+
copyB.#.jpg -> copyB.0009.jpg
180+
Reading ./copyA.0009.jpg
181+
Output: copyB.0009.jpg
182+
Writing copyB.0009.jpg
183+
184+
SEQUENCE 9
185+
copyA.#.jpg -> ./copyA.0010.jpg
186+
copyB.#.jpg -> copyB.0010.jpg
187+
Reading ./copyA.0010.jpg
188+
Output: copyB.0010.jpg
189+
Writing copyB.0010.jpg
190+
121191
copyA.0001.jpg : 128 x 96, 3 channel, uint8 jpeg
122192
copyA.0002.jpg : 128 x 96, 3 channel, uint8 jpeg
123193
copyA.0003.jpg : 128 x 96, 3 channel, uint8 jpeg
@@ -148,6 +218,10 @@ Sequence -5--2: -5
148218
Sequence -5--2: -4
149219
Sequence -5--2: -3
150220
Sequence -5--2: -2
221+
oiiotool WARNING : oiiotool produced no output. Did you forget -o?
222+
oiiotool ERROR : Not all sequence specifications matched: copyA.#.jpg (10 frames) vs. copyC.1-5#.jpg (5 frames)
223+
Full command line was:
224+
>
151225

152226
Brief: 128 x 96, 3 channel, float tiff
153227

testsuite/oiiotool-control/run.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,18 @@
108108

109109
# test sequences
110110
command += oiiotool ("../common/tahoe-tiny.tif -o copyA.1-10#.jpg")
111+
command += oiiotool ("--debug copyA.#.jpg -o copyB.#.jpg")
111112
command += oiiotool (" --info " + " ".join(["copyA.{0:04}.jpg".format(x) for x in range(1,11)]))
112113
command += oiiotool ("--frames 1-5 --echo \"Sequence 1-5: {FRAME_NUMBER}\"")
113114
command += oiiotool ("--frames -5-5 --echo \"Sequence -5-5: {FRAME_NUMBER}\"")
114115
command += oiiotool ("--frames -5--2 --echo \"Sequence -5--2: {FRAME_NUMBER}\"")
115116

117+
# Sequence errors:
118+
# No matching files found
119+
command += oiiotool ("notfound.#.jpg -o alsonotfound.#.jpg")
120+
# Ranges don't match
121+
command += oiiotool ("copyA.#.jpg -o copyC.1-5#.jpg")
122+
116123
# Test stats and metadata expression substitution
117124
command += oiiotool ("../common/tahoe-tiny.tif"
118125
+ " --echo \"\\nBrief: {TOP.METABRIEF}\""

testsuite/oiiotool-copy/ref/out.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ metamerge.exr : 64 x 64, 6 channel, float openexr
7474
screenWindowWidth: 1
7575
oiio:ColorSpace: "Linear"
7676
oiio:subimages: 1
77+
Testing -o with no image
78+
oiiotool WARNING: -o : out.tif did not have any current image to output.
7779
Comparing "rgonly.exr" and "ref/rgonly.exr"
7880
PASS
7981
Comparing "ch-err.exr" and "ref/ch-err.exr"

testsuite/oiiotool-copy/run.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@
9393
"--chappend:n=3 -d half -o chappend-3images.exr")
9494

9595

96+
# Interesting error cases
97+
command += oiiotool ("-echo \"Testing -o with no image\" -o out.tif")
98+
9699

97100
# Outputs to check against references
98101
outputs = [

testsuite/oiiotool-subimage/ref/out-oldfreetype.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ mip4.tif : 64 x 64, 4 channel, uint8 tiff
7676
SHA-1: 7DB3F1E464C5F38CAAECE8ABC8684EC66FC9FA68
7777
unmip.tif : 1024 x 1024, 4 channel, uint8 tiff
7878
SHA-1: 7DB3F1E464C5F38CAAECE8ABC8684EC66FC9FA68
79+
Select nonexistent subimage
80+
oiiotool ERROR: --subimage : Invalid -subimage (13): subimages-4.exr has 4 subimages
81+
Full command line was:
82+
> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio -echo "Select nonexistent subimage" subimages-4.exr --subimage 13 -o subimage13.exr
83+
Select nonexistent MIP level
84+
oiiotool ERROR: --selectmip : Selecting MIP level 14 of subimage 0, which has only 11 MIP levels
85+
Full command line was:
86+
> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio -echo "Select nonexistent MIP level" ../common/textures/grid.tx --selectmip 14 -o mip14.tif
7987
Comparing "subimages-2.exr" and "ref/subimages-2.exr"
8088
PASS
8189
Comparing "subimages-4.exr" and "ref/subimages-4-freetype2.7.exr"

testsuite/oiiotool-subimage/ref/out.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ mip4.tif : 64 x 64, 4 channel, uint8 tiff
7676
SHA-1: 7DB3F1E464C5F38CAAECE8ABC8684EC66FC9FA68
7777
unmip.tif : 1024 x 1024, 4 channel, uint8 tiff
7878
SHA-1: 7DB3F1E464C5F38CAAECE8ABC8684EC66FC9FA68
79+
Select nonexistent subimage
80+
oiiotool ERROR: --subimage : Invalid -subimage (13): subimages-4.exr has 4 subimages
81+
Full command line was:
82+
> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio -echo "Select nonexistent subimage" subimages-4.exr --subimage 13 -o subimage13.exr
83+
Select nonexistent MIP level
84+
oiiotool ERROR: --selectmip : Selecting MIP level 14 of subimage 0, which has only 11 MIP levels
85+
Full command line was:
86+
> oiiotool -colorconfig ../common/OpenColorIO/nuke-default/config.ocio -echo "Select nonexistent MIP level" ../common/textures/grid.tx --selectmip 14 -o mip14.tif
7987
Comparing "subimages-2.exr" and "ref/subimages-2.exr"
8088
PASS
8189
Comparing "subimages-4.exr" and "ref/subimages-4.exr"

testsuite/oiiotool-subimage/run.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# with changed freetype versions.
55
failpercent *= 2.0
66

7+
redirect = " >> out.txt 2>&1 "
8+
failureok = 1
9+
710
# test subimages
811
command += oiiotool ("--pattern constant:color=0.5,0.0,0.0 64x64 3 " +
912
"--pattern constant:color=0.0,0.5,0.0 64x64 3 " +
@@ -28,6 +31,12 @@
2831
command += info_command ("../common/textures/grid.tx", verbose=False)
2932
command += info_command ("unmip.tif", verbose=False)
3033

34+
# Error cases
35+
command += oiiotool ("-echo \"Select nonexistent subimage\""
36+
+ " subimages-4.exr --subimage 13 -o subimage13.exr")
37+
command += oiiotool ("-echo \"Select nonexistent MIP level\""
38+
+ " ../common/textures/grid.tx --selectmip 14 -o mip14.tif")
39+
3140
# Outputs to check against references
3241
outputs = [
3342
"subimages-2.exr", "subimages-4.exr",

0 commit comments

Comments
 (0)