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

Clarify that RGBA means non-premultiplied alpha #13

Closed
nigeltao opened this issue Nov 25, 2021 · 6 comments
Closed

Clarify that RGBA means non-premultiplied alpha #13

nigeltao opened this issue Nov 25, 2021 · 6 comments

Comments

@nigeltao
Copy link

It's probably worth mentioning in the spec (or, if there's not a spec, in qoi.h) whether RGBA means premultiplied (associated) alpha or non-premultiplied (straight, unassociated) alpha.

https://en.wikipedia.org/wiki/Alpha_compositing#Straight_versus_premultiplied

If it's "whatever PNG does" then it's non-premultiplied alpha.

@phoboslab
Copy link
Owner

Except for iOS where all PNGs are premultiplied...

QOI gets exactly those values out, that you put in. As an interchange format (which QOI is not) I would cautiously hint towards un-premultiplied - which is what everyone assumes already. But I will not tell anyone if you put premultiplied alpha in it for your game :)

@nigeltao
Copy link
Author

Except for iOS where all PNGs are premultiplied...

I don't think that this is an accurate generalization.

On iOS, these premul-PNGs have an extra CgBI chunk, an Apple extension to the official PNG spec:

  • On a strict reading of the PNG spec, all PNG images are nonpremul (and those with CgBI chunks are invalid).
  • On a looser reading (Apple's implementation), all PNG images are nonpremul unless they have a CgBI chunk, in which case they're premul.

It's not the case where, on the same PNG file (without CgBI), Apple's decoding and libpng's decoding produce different pixels (in the premul vs nonpremul sense, not the four byte value sense).

The CgBI chunk is, in some way, similar to an iCCP color profile chunk. Both are optional chunks that a PNG decoder should ideally interpret by post-processing the pixels. In the iCCP case, it's running some sort of color management code, with the additional context of the destination screen's color profile. In the CgBI case, it's running a standard premul -> nonpremul conversion. In both cases, the output is RGBA_nonpremul.

If there's further image processing between PNG decode and blitting to the screen, and that further image processing includes a nonpremul -> premul conversion step, then there's an optimization where the premul -> nonpremul -> premul round trip can be avoided, for CgBI PNG images. But conceptually, that's just an optimization. There's still only one correct output (modulo rounding errors) for decoding a PNG, CgBI or not, iOS or not, whether we're ultimately decoding to RGBA_nonpremul or RGBA_premul.

Another analogy is that some PNG files are inherently 16 bits per channel, but we can still decode them to 8 bits per channel. This is a choice of the caller of the decoder library, not the encoder library. Likewise, CgBI PNG is inherently premul, but we can still choose to decode to nonpremul.

@nigeltao
Copy link
Author

If all producers and consumers agree beforehand that the four channels are actually RGBA_premul (or CMYK, or whatever) instead of RGBA_nonpremul, and those QOI images aren't shared elsewhere (e.g. they are first party game assets), then fine, go for it.

I'm talking about if I have a general-purpose image viewer (say, a web browser from the future) and I come across a QOI image on a website, with no further contextual information. Is it premul or non-premul RGBA? I still think that the spec should say something, even if there's an asterisk along the lines of "If all producers and consumers agree otherwise".

An alternative (like NIE, which I've mentioned elsewhere), is to stick a nonpremul vs premul bit in the header. Have the qoiconv.c encoder always choose nonpremul (or maybe it will depend, once stb_image can read CgBI PNGs). But other encoders can choose differently.

Even if you don't want to do the nonpremul vs premul bit now, if there's a chance you might in the future, that's another argment for versioning the header #12.

As an interchange format (which QOI is not)

Why not?

@nigeltao
Copy link
Author

(Oh, it's largely unrelated, but there's not really a better place for me to say this. Even though I've filed a number of issues, I think QOI is really great!)

@nigeltao
Copy link
Author

Given the confusion in #23 and the mention in #28, perhaps this issue should be re-opened?

@nigeltao
Copy link
Author

this issue should be re-opened?

Sorry, I only just saw what you wrote in #28:

3c) I'm against an option for premultiplied alpha, because it puts more burden on any QOI implementation to decode in the right pixel format. We should just specify that QOI images have un-premultiplied alpha.

That works for me.

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

No branches or pull requests

2 participants