Skip to content

Commit 21dbd07

Browse files
authored
fix(oiiotool): -d SUBIMAGENAME.* didn't work properly (#5048)
The docs described a syntax where you could use `-d` to change the data type of all channels in one subimage of a multi-subimage image. But it didn't work, as revealed in #5047. Fixes #5047 --------- Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 3092c42 commit 21dbd07

3 files changed

Lines changed: 52 additions & 10 deletions

File tree

src/oiiotool/oiiotool.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -819,20 +819,26 @@ get_value_override(string_view localoption, string_view defaultval)
819819
static void
820820
set_output_dataformat(ImageSpec& spec, TypeDesc format,
821821
std::map<std::string, std::string>& channelformats,
822-
int bitdepth)
822+
int bitdepth, int subimage_index, int nsubimages)
823823
{
824824
if (format != TypeUnknown)
825825
spec.format = format;
826826
spec.channelformats.resize(spec.nchannels, spec.format);
827827
if (!channelformats.empty()) {
828828
std::string subimagename = spec["oiio:subimagename"];
829+
// If this is one of several subimages and it doesn't have a name, let
830+
// it be referred to be "subimage0N".
831+
if (nsubimages > 1 && subimagename.size() == 0)
832+
subimagename = Strutil::format("subimage{:02}", subimage_index);
833+
auto subwildcard = Strutil::format("{}.*", subimagename);
829834
for (int c = 0; c < spec.nchannels; ++c) {
830835
std::string chname = spec.channel_name(c);
831-
auto subchname = Strutil::fmt::format("{}.{}", subimagename,
832-
chname);
836+
auto subchname = Strutil::format("{}.{}", subimagename, chname);
833837
TypeDesc chtype = spec.channelformat(c);
834838
if (subimagename.size() && channelformats[subchname] != "")
835839
chtype = TypeDesc(channelformats[subchname]);
840+
else if (subimagename.size() && channelformats[subwildcard] != "")
841+
chtype = TypeDesc(channelformats[subwildcard]);
836842
else if (channelformats[chname] != "")
837843
chtype = TypeDesc(channelformats[chname]);
838844
if (chtype != TypeUnknown)
@@ -862,6 +868,7 @@ set_output_dataformat(ImageSpec& spec, TypeDesc format,
862868
static void
863869
adjust_output_options(string_view filename, ImageSpec& spec,
864870
const ImageSpec* nativespec, const Oiiotool& ot,
871+
int subimage_index, int nsubimages,
865872
bool format_supports_tiles,
866873
const ParamValueList& fileoptions,
867874
bool was_direct_read = false)
@@ -944,7 +951,8 @@ adjust_output_options(string_view filename, ImageSpec& spec,
944951

945952
// Set the types in the spec
946953
set_output_dataformat(spec, requested_output_dataformat,
947-
requested_channelformats, requested_output_bits);
954+
requested_channelformats, requested_output_bits,
955+
subimage_index, nsubimages);
948956

949957

950958
// Tiling strategy:
@@ -5850,8 +5858,8 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
58505858
bool ok = true;
58515859
if (do_tex || do_latlong || do_bumpslopes) {
58525860
ImageSpec configspec;
5853-
adjust_output_options(filename, configspec, nullptr, ot, supports_tiles,
5854-
fileoptions);
5861+
adjust_output_options(filename, configspec, nullptr, ot, 0, 1,
5862+
supports_tiles, fileoptions);
58555863
prep_texture_config(ot, configspec, fileoptions);
58565864
ImageBufAlgo::MakeTextureMode mode = ImageBufAlgo::MakeTxTexture;
58575865
if (do_shad)
@@ -5878,10 +5886,10 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
58785886
} else {
58795887
// Non-texture case
58805888
std::vector<ImageSpec> subimagespecs(ir->subimages());
5881-
for (int s = 0; s < ir->subimages(); ++s) {
5889+
for (int s = 0, send = ir->subimages(); s < send; ++s) {
58825890
ImageSpec spec = *ir->spec(s, 0);
5883-
adjust_output_options(filename, spec, ir->nativespec(s), ot,
5884-
supports_tiles, fileoptions,
5891+
adjust_output_options(filename, spec, ir->nativespec(s), ot, s,
5892+
send, supports_tiles, fileoptions,
58855893
(*ir)[s].was_direct_read());
58865894
// If it's not tiled and MIP-mapped, remove any "textureformat"
58875895
if (!spec.tile_pixels() || ir->miplevels(s) <= 1)
@@ -5923,7 +5931,7 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
59235931
for (int m = 0, mend = ir->miplevels(s); m < mend && ok; ++m) {
59245932
ImageSpec spec = *ir->spec(s, m);
59255933
adjust_output_options(filename, spec, ir->nativespec(s, m), ot,
5926-
supports_tiles, fileoptions,
5934+
s, send, supports_tiles, fileoptions,
59275935
(*ir)[s].was_direct_read());
59285936
if (s > 0 || m > 0) { // already opened first subimage/level
59295937
if (!out->open(tmpfilename, spec, mode)) {

testsuite/oiiotool-copy/ref/out.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ rgbahalf-zfloat.exr : 38 x 38, 5 channel, half/half/half/half/float openexr
2828
screenWindowWidth: 1
2929
oiio:subimages: 1
3030
openexr:lineOrder: "increasingY"
31+
Reading sub-formats.exr
32+
3 subimages: 64x64 [h,h,h], 64x64 [h,f,h], 64x64 [h,h,h,h]
33+
oiio:subimages: 3
34+
oiio:subimages: 3
35+
oiio:subimages: 3
36+
Reading sub-formats2.exr
37+
3 subimages: 64x64 [h,h,h], 64x64 [f,f,f], 64x64 [h,h,h,h]
38+
oiio:subimages: 3
39+
oiio:subimages: 3
40+
oiio:subimages: 3
41+
Reading sub-formats3.exr
42+
3 subimages: 64x64 [h,h,h], 64x64 [f,f,f], 64x64 [h,h,h]
43+
oiio:subimages: 3
44+
oiio:subimages: 3
45+
oiio:subimages: 3
3146
explicit -d uint save result:
3247
uint8.tif : 128 x 128, 3 channel, uint8 tiff
3348
tile size: 16 x 16

testsuite/oiiotool-copy/run.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,25 @@
3636
command += oiiotool ("src/rgbaz.exr -d half -d Z=float -o rgbahalf-zfloat.exr")
3737
command += info_command ("rgbahalf-zfloat.exr", safematch=1)
3838

39+
# test -d SUBIMAGE.NAME=fmt to change data format of one subimage
40+
command += oiiotool ("--create 64x64 3 --attrib oiio:subimagename subimageA " +
41+
"--create 64x64 3 --attrib oiio:subimagename subimageB " +
42+
"--create 64x64 4 --attrib oiio:subimagename subimageC " +
43+
"--siappendall -d half -d subimageB.G=float -o sub-formats.exr")
44+
command += info_command ("sub-formats.exr", extraargs="--metamatch subimages")
45+
# test -d SUBIMAGE.*=fmt to change data format of one channel of one subimage
46+
command += oiiotool ("--create 64x64 3 --attrib oiio:subimagename subimageA " +
47+
"--create 64x64 3 --attrib oiio:subimagename subimageB " +
48+
"--create 64x64 4 --attrib oiio:subimagename subimageC " +
49+
"--siappendall -d half -d subimageB.*=float -o sub-formats2.exr")
50+
command += info_command ("sub-formats2.exr", extraargs="--metamatch subimages")
51+
# test -d SUBIMAGE.*=fmt to change data format of one channel of one subimage,
52+
# when no subimages are named (they wil be upon output) but it will still
53+
# recognize "subimage{:02}".
54+
command += oiiotool ("--create 64x64 3 --dup --dup " +
55+
"--siappendall -d half -d subimage01.*=float -o sub-formats3.exr")
56+
command += info_command ("sub-formats3.exr", extraargs="--metamatch subimages")
57+
3958

4059
# Some tests to verify that we are transferring data formats properly.
4160
#

0 commit comments

Comments
 (0)