@@ -443,7 +443,7 @@ Oiiotool::remember_input_channelformats(ImageRecRef img)
443
443
if (input_channelformats[subchname] == " " )
444
444
input_channelformats[subchname] = chtypename;
445
445
} else {
446
- if (input_channelformats[chname] ! = " " )
446
+ if (input_channelformats[chname] = = " " )
447
447
input_channelformats[chname] = chtypename;
448
448
}
449
449
}
@@ -764,39 +764,23 @@ set_output_dataformat(ImageSpec& spec, TypeDesc format,
764
764
std::map<std::string, std::string>& channelformats,
765
765
int bitdepth)
766
766
{
767
- // Account for default requested format
768
767
if (format != TypeUnknown)
769
768
spec.format = format;
770
- if (bitdepth)
771
- spec.attribute (" oiio:BitsPerSample" , bitdepth);
772
- else
773
- spec.erase_attribute (" oiio:BitsPerSample" );
774
-
775
- // See if there's a recommended format for this subimage
776
- std::string subimagename = spec[" oiio:subimagename" ];
777
- if (format == TypeUnknown && subimagename.size ()) {
778
- auto key = Strutil::fmt::format (" {}.*" , subimagename);
779
- if (channelformats[key] != " " )
780
- spec.format = TypeDesc (channelformats[key]);
781
- }
782
-
783
- // Honor any per-channel requests
784
- if (channelformats.size ()) {
785
- spec.channelformats .clear ();
786
- spec.channelformats .resize (spec.nchannels , spec.format );
769
+ spec.channelformats .resize (spec.nchannels , spec.format );
770
+ if (!channelformats.empty ()) {
771
+ std::string subimagename = spec[" oiio:subimagename" ];
787
772
for (int c = 0 ; c < spec.nchannels ; ++c) {
788
773
std::string chname = spec.channel_name (c);
789
774
auto subchname = Strutil::fmt::format (" {}.{}" , subimagename,
790
775
chname);
791
- if (channelformats[subchname] != " " && subimagename.size ())
792
- spec.channelformats [c] = TypeDesc (channelformats[subchname]);
776
+ TypeDesc chtype = spec.channelformat (c);
777
+ if (subimagename.size () && channelformats[subchname] != " " )
778
+ chtype = TypeDesc (channelformats[subchname]);
793
779
else if (channelformats[chname] != " " )
794
- spec. channelformats [c] = TypeDesc (channelformats[chname]);
795
- else
796
- spec.channelformats [c] = spec. format ;
780
+ chtype = TypeDesc (channelformats[chname]);
781
+ if (chtype != TypeUnknown)
782
+ spec.channelformats [c] = chtype ;
797
783
}
798
- } else {
799
- spec.channelformats .clear ();
800
784
}
801
785
802
786
// Eliminate the per-channel formats if they are all the same.
@@ -809,6 +793,11 @@ set_output_dataformat(ImageSpec& spec, TypeDesc format,
809
793
spec.channelformats .clear ();
810
794
}
811
795
}
796
+
797
+ if (bitdepth)
798
+ spec.attribute (" oiio:BitsPerSample" , bitdepth);
799
+ else
800
+ spec.erase_attribute (" oiio:BitsPerSample" );
812
801
}
813
802
814
803
@@ -835,37 +824,71 @@ adjust_output_options(string_view filename, ImageSpec& spec,
835
824
// format as the input, or else she would have said so).
836
825
// * Otherwise, just write the buffer's format, regardless of how it got
837
826
// that way.
838
- TypeDesc requested_output_dataformat = ot.output_dataformat ;
839
- auto requested_output_channelformats = ot.output_channelformats ;
827
+
828
+ // spec is what we're going to use for output.
829
+
830
+ // Accumulating results here
831
+ TypeDesc requested_output_dataformat;
832
+ std::map<std::string, std::string> requested_channelformats;
833
+ int requested_output_bits = 0 ;
834
+
835
+ if (was_direct_read && nativespec) {
836
+ // If the image we're outputting is an unmodified direct read of a
837
+ // file, assume that we'll default to outputting the same channel
838
+ // formats it started in.
839
+ requested_output_dataformat = nativespec->format ;
840
+ for (int c = 0 ; c < nativespec->nchannels ; ++c) {
841
+ requested_channelformats[nativespec->channel_name (c)]
842
+ = nativespec->channelformat (c).c_str ();
843
+ }
844
+ requested_output_bits = nativespec->get_int_attribute (
845
+ " oiio:BitsPerSample" );
846
+ } else if (ot.input_dataformat != TypeUnknown) {
847
+ // If the image we're outputting is a computed or modified image, not
848
+ // a direct read, then assume that the FIRST image we read in provides
849
+ // a template for the output we want (if we ever read an image).
850
+ requested_output_dataformat = ot.input_dataformat ;
851
+ requested_channelformats = ot.input_channelformats ;
852
+ requested_output_bits = ot.input_bitspersample ;
853
+ }
854
+
855
+ // Any "global" format requests set by -d override the above.
856
+ if (ot.output_dataformat != TypeUnknown) {
857
+ // `-d type` clears the board and imposes the request
858
+ requested_output_dataformat = ot.output_dataformat ;
859
+ requested_channelformats.clear ();
860
+ spec.channelformats .clear ();
861
+ if (ot.output_bitspersample )
862
+ requested_output_bits = ot.output_bitspersample ;
863
+ }
864
+ if (!ot.output_channelformats .empty ()) {
865
+ // `-d chan=type` overrides the format for a specific channel
866
+ for (auto && c : ot.output_channelformats )
867
+ requested_channelformats[c.first ] = c.second ;
868
+ }
869
+
870
+ // Any override options on the -o command itself take precedence over
871
+ // everything else.
840
872
if (fileoptions.contains (" type" )) {
841
873
requested_output_dataformat.fromstring (fileoptions.get_string (" type" ));
842
- requested_output_channelformats.clear ();
874
+ requested_channelformats.clear ();
875
+ spec.channelformats .clear ();
843
876
} else if (fileoptions.contains (" datatype" )) {
844
877
requested_output_dataformat.fromstring (
845
878
fileoptions.get_string (" datatype" ));
846
- requested_output_channelformats.clear ();
847
- }
848
- int requested_output_bits = fileoptions.get_int (" bits" ,
849
- ot.output_bitspersample );
850
-
851
- if (requested_output_dataformat != TypeUnknown) {
852
- // Requested an explicit override of datatype
853
- set_output_dataformat (spec, requested_output_dataformat,
854
- requested_output_channelformats,
855
- requested_output_bits);
856
- } else if (was_direct_read && nativespec) {
857
- // Do nothing -- use the file's native data format
858
- spec.channelformats = nativespec->channelformats ;
859
- set_output_dataformat (spec, nativespec->format ,
860
- requested_output_channelformats,
861
- (*nativespec)[" oiio:BitsPerSample" ].get <int >());
862
- } else if (ot.input_dataformat != TypeUnknown) {
863
- auto mergedlist = ot.input_channelformats ;
864
- for (auto & c : requested_output_channelformats)
865
- mergedlist[c.first ] = c.second ;
866
- set_output_dataformat (spec, ot.input_dataformat , mergedlist,
867
- ot.input_bitspersample );
879
+ requested_channelformats.clear ();
880
+ spec.channelformats .clear ();
868
881
}
882
+ requested_output_bits = fileoptions.get_int (" bits" , requested_output_bits);
883
+
884
+ // At this point, the trio of "requested" variable reflect any global or
885
+ // command requests to override the logic of what was found in the input
886
+ // files.
887
+
888
+ // Set the types in the spec
889
+ set_output_dataformat (spec, requested_output_dataformat,
890
+ requested_channelformats, requested_output_bits);
891
+
869
892
870
893
// Tiling strategy:
871
894
// * If a specific request was made for tiled or scanline output, honor
0 commit comments