Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TIFF: refine logic for setting PhotometricInterpretation on output #3746

Merged
merged 1 commit into from
Jan 12, 2023

Conversation

lgritz
Copy link
Collaborator

@lgritz lgritz commented Jan 8, 2023

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:

oiiotool ycbcr_disguised_as_rgb.tif --iscolorspace YCbCb -o real_ycbcr.tif

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:

    oiiotool ycbcr_disguised_as_rgb.tif --iscolorspace YCbCb -o real_ycbcr.tif
@lgritz
Copy link
Collaborator Author

lgritz commented Jan 8, 2023

@christopherdavies

@lgritz lgritz merged commit c2781d7 into AcademySoftwareFoundation:master Jan 12, 2023
@lgritz lgritz deleted the lg-tiff branch January 13, 2023 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant