@@ -443,7 +443,7 @@ Oiiotool::remember_input_channelformats(ImageRecRef img)
443443 if (input_channelformats[subchname] == " " )
444444 input_channelformats[subchname] = chtypename;
445445 } else {
446- if (input_channelformats[chname] ! = " " )
446+ if (input_channelformats[chname] = = " " )
447447 input_channelformats[chname] = chtypename;
448448 }
449449 }
@@ -764,39 +764,23 @@ set_output_dataformat(ImageSpec& spec, TypeDesc format,
764764 std::map<std::string, std::string>& channelformats,
765765 int bitdepth)
766766{
767- // Account for default requested format
768767 if (format != TypeUnknown)
769768 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" ];
787772 for (int c = 0 ; c < spec.nchannels ; ++c) {
788773 std::string chname = spec.channel_name (c);
789774 auto subchname = Strutil::fmt::format (" {}.{}" , subimagename,
790775 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]);
793779 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 ;
797783 }
798- } else {
799- spec.channelformats .clear ();
800784 }
801785
802786 // Eliminate the per-channel formats if they are all the same.
@@ -809,6 +793,11 @@ set_output_dataformat(ImageSpec& spec, TypeDesc format,
809793 spec.channelformats .clear ();
810794 }
811795 }
796+
797+ if (bitdepth)
798+ spec.attribute (" oiio:BitsPerSample" , bitdepth);
799+ else
800+ spec.erase_attribute (" oiio:BitsPerSample" );
812801}
813802
814803
@@ -835,37 +824,71 @@ adjust_output_options(string_view filename, ImageSpec& spec,
835824 // format as the input, or else she would have said so).
836825 // * Otherwise, just write the buffer's format, regardless of how it got
837826 // 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.
840872 if (fileoptions.contains (" type" )) {
841873 requested_output_dataformat.fromstring (fileoptions.get_string (" type" ));
842- requested_output_channelformats.clear ();
874+ requested_channelformats.clear ();
875+ spec.channelformats .clear ();
843876 } else if (fileoptions.contains (" datatype" )) {
844877 requested_output_dataformat.fromstring (
845878 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 ();
868881 }
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+
869892
870893 // Tiling strategy:
871894 // * If a specific request was made for tiled or scanline output, honor
0 commit comments