-
Notifications
You must be signed in to change notification settings - Fork 95
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
Add initial support for the QOI image format #148
Conversation
This looks perfect. I'm holding off with merging purely because QOI hasn't been finalized yet. |
Definitely! I'll wait for phoboslab/qoi#37 to be closed before making further updates to the PR. N.B. besides loading PNG images and saving them to QOI (and then loading back the result) to check if the code was working correctly, I have also tested:
|
It looks like the format is now finalized (though, the issue still hasn't been closed). However, one change I noticed which might make it weird to support the format is regarding the added // The colorspace in this qoi_desc is a bitmap with 0000rgba where a 0-bit
// indicates sRGB and a 1-bit indicates linear colorspace for each channel. You
// may use one of the predefined constants: QOI_SRGB, QOI_SRGB_LINEAR_ALPHA or
// QOI_LINEAR. The colorspace is purely informative. It will be saved to the
// file header, but does not affect en-/decoding in any way.
#define QOI_SRGB 0x00
#define QOI_SRGB_LINEAR_ALPHA 0x01
#define QOI_LINEAR 0x0f From what I understand, My understanding is that, internally, tev's images use "sRGB/Rec.709" primaries and have linear color channels (as a result of the Hence, should we always encode QOI files as Also, I'm not sure if storing the |
This is 100% correct!
LDR image savers are already passed Thanks again! |
src/imageio/QoiImageLoader.cpp
Outdated
auto typedData = reinterpret_cast<unsigned char*>(decodedData); | ||
size_t baseIdx = i * numChannels; | ||
for (int c = 0; c < numChannels; ++c) { | ||
if (isSRGBChannel[c]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should just be the corresponding bit of the colorspace field, i.e. if (desc.colorspace & (0x8 >> c)) {
(can get rid of the switch statement above)
It looks like the format has been finalized (e.g. see this comment from the author floooh/qoiview#2 (comment)). Though, as mentioned in my last comment, Since it's noted in |
My understanding is that "purely informative" merely refers to the fact that the qoi encoding routine doesn't care about the meaning of the channel. As such, tev should treat the bitfield exactly as the spec says: if the bit is high, the channel should be treated as linear, and if the bit is low, srgb. If tev (and other image viewers) started to ignore the spec, then all hell would break loose in terms of compatibility. :p |
Ok! I'm just worried about images looking slightly wrong because initializing Should tev display any sort of "warnings" about this to notify users? If not, I think changing the code as you suggested (#148 (comment)) seems good to me. |
I think it's best to wait and see how much of an issue this becomes in the wild before emitting warnings. Your concern is very real and valid, though... perhaps at some point in the future it will indeed make sense to ignore the alpha bit and just assume linear. |
Just made the change mentioned above and, funnily enough, already came across the linear vs. sRGB OETF encoded alpha problem using The first image from Wikipedia's entry on PNG is used as Here's how it looks compared to the original And here is how it looked before (i.e. assuming Also, it seems like there might still be some changes to the format encoding (see nigeltao/qoi2-bikeshed#14 (comment)). Thus, I think it might be best to give it a few more days before assuming the QOI format is finalized and merging this PR. |
Oh boy. Maybe worth opening an issue over at I don't want to steal your credit -- but let me know if you don't want to. Then I'll go ahead. |
No worries! Feel free to open the issue, I think you are better suited to explain why they are incorrect (and maybe influence in modifications to the meaning of the default value, if the format still suffers any changes). Here's the three images side-by-side for comparison (PNG from Wikipedia, QOI following the We can clearly see that using |
Actually, this may well be the other way around. QOI_SRGB looks correct to me, whereas the other two images have a visible halo. Perhaps tev is interpreting the alpha channel of PNG images wrong? I will investigate further before making a ruckus. Thank you for creating that side-by-side! |
I noticed this as well (especially in the green dice), but it seems to be a weird "artifact" from the original image itself: https://en.wikipedia.org/wiki/Portable_Network_Graphics#/media/File:PNG_transparency_demonstration_1.png (at least it seems so to me, looking at the image on Chrome). Though, it's worth it to make sure anyway. |
Digging a little deeper, the PNG image spec seems to mandate linear alpha. See section 2.7 of http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#DR.Alpha-channel
Also, see https://www.w3.org/TR/2003/REC-PNG-20031110/#4Concepts.Implied-alpha section section 12.2
Now I'm starting to doubt the correctness of the PNG image on Wikipedia. Argh. |
This discussion reminds me of PNG + sRGB + cutout/decal AA = problematic and A PNG Puzzle. Although I'd have to read them again, here's an interesting bit that maybe stands out:
N.B. those posts are from 2016. |
<rant> Imagine representing a candle flame as an image. It should have a yellow-ish color (near 0xFFFFFF, but not quite there), yet should be almost fully transparent (alpha near zero). In premultiplied alpha form, this is very easy to do. But without premultiplied alpha, the flame needs exceedingly large pixel values (which are impossible to represent in 8bit), just so the multiply by alpha doesn't result in a near-black color. |
I updated the Also, a separate |
Amazing, thank you so much! I ended up cleaning up a little (adding credits and rebasing), but accidentally force-pushed directly to the Your commits are all in and I'll push a new release soonish. :) |
This PR adds support for the new "Quite OK Image" format (qoi), targeting the new
cpp20
branch.