diff --git a/src/pbrt/util/image.cpp b/src/pbrt/util/image.cpp index 1aaf299ba971ab73beaaedaeacaed3555c73287b..6091f297154b26702e2eba6c221eaf5f7bf42a15 100644 --- a/src/pbrt/util/image.cpp +++ b/src/pbrt/util/image.cpp @@ -918,46 +918,59 @@ bool Image::Write(std::string name, const ImageMetadata &metadata) const { if (HasExtension(name, "exr")) return WriteEXR(name, metadata); - if (NChannels() > 4) { - Error("%s: unable to write an %d channel image in this format.", name, - NChannels()); + // This copy will sometimes be wasteful but simplifies logic below... + Image outImage = *this; + + switch (NChannels()) { + case 1: + // all good; onward + break; + case 2: + Error("%s: unable to write a 2 channel image in this format.", name); return false; + case 3: { + ImageChannelDesc desc = outImage.GetChannelDesc({"R", "G", "B"}); + if (!desc) + // Still go for it with 3 channels. + Warning("%s: image has 3 channels but they are not R, G, and B. Image may be " + "garbled.", + name); + else + // Reorder them as RGB. + outImage = outImage.SelectChannels(desc); + break; } - - const Image *image = this; - Image rgbImage; - if (NChannels() == 4) { - ImageChannelDesc desc = GetChannelDesc({"R", "G", "B", "A"}); - if (desc) { - rgbImage = SelectChannels(GetChannelDesc({"R", "G", "B"})); - image = &rgbImage; - } else { - Error("%s: unable to write an 4 channel image that is not RGBA.", name); + default: { + ImageChannelDesc desc = outImage.GetChannelDesc({"R", "G", "B"}); + if (!desc) { + Error("%s: multi-channel image does not have R, G, and B. Unable to write to " + "this format.", + name); return false; + } else { + std::string err = StringPrintf("%s: ignoring additional channels for this " + "image format: ", + name); + for (const auto &ch : outImage.ChannelNames()) + if (ch != "R" && ch != "G" && ch != "B") + err += StringPrintf("\"%s\" ", ch); + Error("%s", err); } + + outImage = outImage.SelectChannels(desc); + break; } - if (NChannels() == 3 && *metadata.GetColorSpace() != *RGBColorSpace::sRGB) - Warning("%s: writing image with non-sRGB color space to a format that " - "doesn't store color spaces.", - name); - - if (NChannels() == 3) { - // Order as RGB - ImageChannelDesc desc = GetChannelDesc({"R", "G", "B"}); - if (!desc) - Warning("%s: 3-channels but doesn't have R, G, and B. " - "Image may be garbled.", - name); - else { - rgbImage = SelectChannels(desc); - image = &rgbImage; + } + CHECK(outImage.NChannels() == 1 || outImage.NChannels() == 3); + + ImageMetadata outMetadata = metadata; } } if (HasExtension(name, "pfm")) - return image->WritePFM(name, metadata); + return outImage.WritePFM(name, outMetadata); else if (HasExtension(name, "png")) - return image->WritePNG(name, metadata); + return outImage.WritePNG(name, outMetadata); else { Error("%s: no support for writing images with this extension", name); return false;