TIFF: refine logic for setting PhotometricInterpretation on output #3746
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Some background: TIFF allows for pixel values to be encoded in some alternative color spaces, like YCbCr, CIELAB, etc., and this is indicated by the TIFF PhotometricInterpretation tag. Since in practice we almost never encounter these encodings in the wild, and they require a lot of custom code to handle (for example, YCbCr also comes along with the ability to subsample the chroma, and options for different placements of the subsampled positions, yuck), for most of these cases we just lean on libtiff's ability to convert the whole thing to RGBA for us, and so in that case, we return to the user the pixels as RGBA, and set the "tiff:ColorSpace" metadata just as an advisory to indicate how it had been encoded in the file. But we don't support writing any of those. (One exception is that we do allow reading and writing of CMYK files.)
OK, but now what about a case where the app already has the data in one of these spaces (such as YCrCb; and let's ignore the whole subsampling miasma and assume we don't want to support that), and all we want to do is write that data to a TIFF file -- without any kind of data conversion -- but to set the TIFF tags properly to indicate that the data in the file is what we know it to be?
A related special case of this is: what if we have a TIFF file that has YCbCr data but neglected to mark it as such (I'm staring daggers at a certain widely used compositing package right now), and to fix this, we want to use OIIO to just copy the file and set the right tags?
It turns out that in the status quo, it is surprisingly difficult to do this. There is just nothing in our existing TIFF output code that will write any of those photometric tags for those spaces, and no way to communicate that this is what we desire.
Whew. Now here's what this patch does:
If the "oiio:ColorSpace" attribute (our usual way to indicate presumed color space of the pixel data) says that the pixels are already in one of those color spaces (specifically, "YCbCr", "CIELAB", "ICCLAB", "ITULAB", "LOGL", "LOGLUV"), then we set the PhotometricInterpretation tag as such in the TIFF file that we write.
We still DO NOT interpret that as a request to convert pixel data from any other space into this one. In other words, the TIFF output does not convert color spaces (except for RGB <-> CMYK); this merely lets us output a file that correctly says the data are what the app thinks they are.
A bunch of minor refactoring was necessary because of some unobvious coupling and order dependencies. For example, the sgilog compression techniques MUST be used with the LOGLUV color space, and vice versa. You have to know how both should be set before checking that they are compatible, and if they are not, adjust something that it's not too late to change.
So the punchline at the end is that if you had a TIFF file that has YCbCr encoded pixels, but for some reason it's marked as ordinary RGB, you can fix it as follows: