[HN Gopher] Quite OK Image is now my favorite asset format
___________________________________________________________________
Quite OK Image is now my favorite asset format
Author : nalgeon
Score : 184 points
Date : 2022-12-18 04:20 UTC (18 hours ago)
(HTM) web link (nullprogram.com)
(TXT) w3m dump (nullprogram.com)
| smallstepforman wrote:
| It's amazing how unaware people are of lossless WebP. Compared to
| PNG, it decodes faster, compresses better, with a minor code size
| increase. When it comes to games though, BC7 all the way ...
| mhd wrote:
| Back in the (DOS) days, Targa/TGA was somewhat popular for the
| asset usage. Simple format plus RLE for a small size benefit.
| qayxc wrote:
| Amazing how few people do some basic research - this isn't new
| or exciting at all. TGA is fine and has been around for
| decades.
|
| It also has the added benefit that many applications still
| support it natively. I really don't get the appeal of inventing
| yet another custom file format that has so few objective
| benefits.
| mhd wrote:
| It's a cute format. Better than most RLE images, if I
| remember correctly, getting you a good way towards PNG.
|
| So might not be best for every situation, but why not have
| that in your toolkit? Especially if being able to understand
| all of your stack is important to you.
| layer8 wrote:
| Unlike QOI, TGA only has RLE as a means of compression, and
| therefore has worse compression on many images than QOI. At
| the same time, TGA supports a much larger range of format
| variants (arbitrary color depths, color palettes, grayscale
| mode), making it much more complex to implement than QOI.
| qayxc wrote:
| And what exactly stops a decoder from simply disregarding
| unnecessary format variants?
|
| If you go as far as to implement your own decoder anyway,
| this argument is simply not applicable. Supporting only a
| subset of the format is perfectly acceptable - see TIFF,
| for example; not every application supports every possible
| feature.
| layer8 wrote:
| You still need extra code to check that the format
| variant matches your expectations. I guess you could go
| very bare-bones and just assume that it's in the right
| format and only check for buffer overflows, at the cost
| that errors will be harder to diagnose when the format is
| wrong. And you'd still have the overhead of the larger
| metadata structures of TGA.
|
| The fact is, none of the existing formats is a perfect
| fit for the embedded use-case here. It makes sense to
| introduce a new, simple and straightforward format if it
| addresses certain typical use-cases better than existing
| formats do.
| andreareina wrote:
| "linear" is not a color space. Presumably they mean something
| like, sRGB but with linear gamma, but without understanding the
| design goals of this format it's hard to say what purpose the
| linear encoding serves.
| kaetemi wrote:
| Pretty much all modern 3D rendering is done in this color space
| that supposedly doesn't exist.
|
| Also, normal maps should be flagged as linear, since they
| should not get converted from the sRGB curve upon sampling.
| andreareina wrote:
| Linear is a _class_ of color spaces, so which one? It 's like
| if I said some data is in "text format". Is it JSON? YAML?
| XML? The Unity docs[1] refer to linear vs gamma, _not_ linear
| vs sRGB. Same with other resources I 'm finding. They do call
| out sRGB as the standard non-linear space, which is
| consistent with what I'm saying: linear and gamma are classes
| of color spaces, so which linear space is it?
|
| Normal maps aren't images for all that they have an intuitive
| visual representation. In particular they don't have colors
| therefore a color space has no meaning.
|
| ETA: a better analogy is "plain text encoded": it's probably
| utf8, but it could be windows-1252, windows-1250, or who
| knows what else.
|
| [1] https://docs.unity3d.com/Manual/LinearLighting.html
| kaetemi wrote:
| Rendering pipelines are in linear RGB. Which has rgb(1,1,1)
| and rgb(0,0,0) the same as sRGB, but with 1.0 gamma.
|
| When loading images into the GPU, you flag them as either
| sRGB or linear. When sampling from a shader the GPU will
| convert sRGB to linear (this is a hardware feature because
| many images are in sRGB space), and not make any changes to
| textures flagged as linear.
|
| Rendering is done in linear RGB space in properly coded
| game engines, and the final output is generally also linear
| (with some post processing magic to stay in boundaries).
| The final swap will convert it to sRGB or whatever your
| display profile is set to, this is handled by the display
| driver as well.
| ninepoints wrote:
| You're slightly confused I think. We operate and perform
| lighting in linear color spaces, but the choice of white
| point and primaries offers a few degrees of freedom. LDR
| renderers might opt to stay within linear sRGB primaries,
| but it's easy to clip against the gamut boundary if doing
| HDR lighting. A color transform is needed to go to
| Rec2020 or wider.
| kaetemi wrote:
| Possibly, I might be. (Hence, post processing magic,
| regarding white points and clipping.) Wasn't the final
| color space transform handled by the driver? I don't
| recall having to do any manual color transforms to
| present a linear RGB render target correctly on an sRGB
| display, at least. Haven't had the chance yet to
| experiment with high gamut displays, unfortunately, so I
| might be missing something.
|
| Fortunately I mostly just deal with embedded graphics
| that do their technically incorrect blending math in
| unmanaged sRGB/display space. (:
| bscphil wrote:
| Does that just mean that the color space is untagged /
| undefined? (That is in practice how I see a lot of games
| rendered - way oversaturated on my wide gamut screen.)
| csande17 wrote:
| For normal maps, the correct color space is definitely "no
| color space", because the R/G/B channels are used to store
| a 3D vector and not an actual color.
|
| For video game graphics, the ideal color space is "looks
| good on the median user's television once we apply our
| gamma curve", which is not actually a real color space.
| It's more like a statistical distribution of color spaces.
| bscphil wrote:
| Normal maps, certainly. I was more confused by the
| parent's claim that this applied to "pretty much all
| modern 3D rendering".
|
| With video game graphics I'm surprised that PC games
| aren't handled differently. To the extent that TVs aren't
| garbage (huge assumption) traditional SDR TVs mostly
| target sRGB. But PC monitors can be almost anything,
| there are a ton of wide gamut (e.g. P3) screens out
| there, and saturated games can be retina-searing on them.
| csande17 wrote:
| It'd probably be reasonable to say the _output_ of a game
| 's 3D renderer is sRGB or something, and to call the eye-
| searing colors on your P3 monitor a bug.
|
| But I think kaetemi's comment was talking about the
| intermediate calculations, which don't usually use sRGB.
| The "linear" color space used for those doesn't need to
| have a rigorous definition; even if there's no
| mathematically correct way to map a video-game-linear
| color to an sRGB color, the game company just hand-tweaks
| it until the game looks good.
| kaetemi wrote:
| The output is either linear RGB in modern pipelines or
| unspecified probably-sRGB for older pipelines (which
| usually have wrong lighting math).
|
| It's the driver that does the linear RGB to display space
| conversion when the engine swaps the render buffer.
|
| In the case of non-specified probably-sRGB color space I
| have no idea if it converts from sRGB to your display
| space, or if it just does nothing because it not
| specified.
| andreareina wrote:
| It sounds like gp's issue is only with games, i.e.
| everything else is rendering correctly. Which sounds to
| me like the video driver isn't applying the correct
| output profile (but the OS does so regular applications
| work).
|
| Can you actually specify a color profile in the driver
| itself? I haven't had a color managed workflow in forever
| but I remember only ever being able to tell the OS.
| bscphil wrote:
| Yeah, I believe the issue here is that games are not
| usually color managed because that would require tagging
| the rendered image with a space and then converting it,
| which would probably delay the render by at least a
| frame.
| kaetemi wrote:
| In practice, linear texture means "don't mess with the data
| when sampling", and sRGB texture means "please convert to
| linear when sampling" (this is a hardware feature).
|
| On modern engines, rendering is done in linear. A lot of
| older engines render in unmanaged maybe-sRGB and look like
| potato, in which case tagging the textures does nothing.
|
| In general either the final render output is linear or "I
| don't care" probably sRGB, in the first case it's up to
| your display driver to do the final conversion to your
| display color space, in which case colors should look
| correct, but the game engine may have already limited
| colors (by some post processing magic) within sRGB
| boundaries if it's not aware of your display range. Or it
| may have messed up if it can't make sense if the display
| range. In the other case, I'm not sure if there's a solid
| definition, the driver will probably assume the color space
| is already good.
| iainmerrick wrote:
| _Presumably they mean something like, sRGB but with linear
| gamma_
|
| Yes, it's exactly that, because:
|
| - almost all the time, the display is sRGB, so that's your
| gamut;
|
| - almost all the time, you want to do your lighting and
| compositing in a linear space.
|
| - and sometimes your channels are normals or something, not
| colors at all, as others have noted.
|
| So it's linear in the sRGB 0..255 gamut.
|
| It is a bit of a shame that most easy-to-use tools and
| workflows are limited to sRGB, so it's really fiddly to support
| HDR displays and print.
| esperent wrote:
| > almost all the time, the display is sRGB, so that's your
| gamut;
|
| This is becoming less and less of a safe statement. On the
| one hand "yay HDR"!
|
| On the other hand, we're in for many years of weird bugs. For
| example recently I've been working on an app that I want to
| look good in HDR and I tried to share screenshots. Everything
| looked good to me. People on the other side were complaining
| about weird colors. Several hours of investigation later I
| realized that Windows was _switching color spaces in my
| screenshots_. Pressing the print screen button gave me a
| subtly different result than what I was actually seeing and
| of course I didn 't spot it when emailing off the screen
| shots.
| lifthrasiir wrote:
| IIRC it is a late addition and only added because of people
| wanting some kind of color space guarantee. I don't think it
| was ever accurately specified what they do mean---presumably
| both share the sRGB color gamut and only differ by transfer
| functions, but it's a frequent misconception [1] that transfer
| functions can be parametrized with a single value, gamma, so I
| guess that's where the "linear" came from (implying gamma =
| 1.0).
|
| [1] The sRGB EOTF has a nominal gamma of 2.2 but it is actually
| a piecewise function with gamma varying from 1.0 to 2.4.
| mananaysiempre wrote:
| Compare how Netpbm declared[1] that colour images are BT.709
| (HDTV) relatively late in its existence, and seemingly every
| other implementation ignores that and treats them as sRGB
| (same--or close enough--primaries, different transfer
| function).
|
| [1] https://netpbm.sourceforge.net/doc/ppm.html
| esperent wrote:
| > I guess that's where the "linear" came from (implying gamma
| = 1.0).
|
| "Linear" means the colors are stored in a state that means
| you can do linear transformations on them (basic math in
| other words) without loss. You can't do this with gamma
| corrected colors - for example as you say, the sRGB EOTF is a
| piecewise function so by definition it's not a linear
| transformation.
|
| So yes, when talking about "linear" colors, they still come
| from some gamut like sRGB or a larger HDR gamut. The linear
| part means they are safe for use in a renderer's internals.
| andreareina wrote:
| I've implemented color-managed workflows so I should have
| suspected that _of course_ sRGB would be like that, it _has_
| to.
| lifthrasiir wrote:
| Yeah, if you have the slightest experience with color space
| you would know that's a misconception, but I've seen enough
| cases where the 2.2 gamma is uniformly applied throughout
| the brightness curve...
| Dylan16807 wrote:
| Okay, the decoder is less than a kilobyte. But where is that an
| advantage over a 50KB PNG decoder, when the compression ratio
| suffers so much?
| jchw wrote:
| The QOI benchmarks shows it only lagging a small bit behind PNG
| in compression ratio, while performing much faster (multiples)
| in both encoding and decoding. Doesn't seem like an awful
| trade-off. Surely you'd expect a much larger, slower and more
| sophisticated encoder and decoder would at least net 25-50%
| improvements to compression ratio, but it seems to net much
| less.
|
| If you are artificially or truly constrained in either CPU
| usage, or maybe just static code size, it seems like it would
| have some appeal, even if niche.
| duskwuff wrote:
| > The QOI benchmarks shows it only lagging a small bit behind
| PNG in compression ratio
|
| The benchmarks are misleading. By size, they mostly consist
| of photographs and other true-color images, which neither
| compressor handles well. This has the effect of hiding QOI's
| lackluster performance on synthetic images which PNG does
| compress well.
|
| In particular, QOI performs _dramatically_ worse than PNG on
| synthetic images containing any sort of vertical pattern. As
| a worst-case example, an image consisting of a single line of
| noise repeated vertically will compress down to basically
| nothing in PNG, but QOI will fail to compress it at all.
| jchw wrote:
| Yes, but the point is that it's not really that far off.
| PNG will outperform in screenshots with a lot of empty
| space, so if you were dealing with that situation,
| obviously PNG is better. OTOH, QOI still performs
| relatively well: while the difference is multiples in some
| cases, to me it seems that those cases are mostly ones
| where PNG's compression ratio is obscenely good, and
| therefore QOI is actually still producing reasonably small
| image files, too.
|
| I can see that QOI performs well for what you might use as
| texture maps for 3D rasterization, for example. Definitely
| seems to have some applicability to me.
| mananaysiempre wrote:
| > The QOI benchmarks shows it only lagging a small bit behind
| PNG in compression ratio, while performing much faster
| (multiples) in both encoding and decoding.
|
| Presumably that's with stock libpng, which uses zlib. I
| wonder if anyone tried patching it to use the substantially
| faster (on x86) libdeflate[1] instead? It doesn't do
| streaming, but you shouldn't really need that for PNG
| textures.
|
| [1] https://github.com/ebiggers/libdeflate
| jitl wrote:
| I came away from reading the article wondering what context I
| was missing. What use-case is the author targeting? It feels
| like I need to read more about this author to understand the
| article.
| atoav wrote:
| In the first paragraph they say:
|
| > QOI has become my default choice for embedded image assets.
|
| Embedded means they are working on stuff with low amounts of
| storage, computing speed and memory. If you are developing
| for embedded you are developing for electronics products
| typicyally. Every byte you can shave off can ultimately
| increase the return on investment. Using a traditional image
| format on embedded might not be possible because you don't
| have the program memory to store a complex decoder. If you
| decoder is 10 times bigger than the assets it is meant to
| decode, maybe there is not so much benefit in using it.
|
| The simplest decoder you can go with would be just storing
| the value of the pixels in a bitmap and teading that out of
| that array. This however has the downside that you got no
| compression on the assets at all. If you have very simple
| color spaces (e.g. 1bit), tiny resolutions and few assets
| this might be an acceptable choice, but the choice gets worse
| as you get more assets, higher resolutions more channels or
| more bits per channel.
|
| That means according to the author there is a space between
| just storing bitmaps and just using a png decoder where there
| were no good goto solutions before and they found a good
| solution with QOI.
| Dylan16807 wrote:
| > That means according to the author there is a space
| between just storing bitmaps and just using a png decoder
| where there were no good goto solutions before and they
| found a good solution with QOI.
|
| What space? I feel like that's an assumption you're making
| and it might be true or it might not be, but even if you're
| right that's very vague and I want more specificity.
| pizza wrote:
| QOI lies between uncompressed images and entropy coded
| compressed images. It also happens to work heuristically
| quite well for such a simple spec. Maybe its defining
| feature is its simplicity, foremost (and as a consequence
| of that, speed, secondarily)
| Dylan16807 wrote:
| I know where it lies on the compression spectrum, I'm
| asking what use case prefers it.
| pizza wrote:
| Wherever the codec has to be as small as possible and do
| as little as possible while not caring about the payload
| size
| skitter wrote:
| Article mentions images embedded in the application, not
| computers embedded in another device.
| bscphil wrote:
| I think it's in the title: _assets_. The example case is
| replacing the BMP assets used by a game with QOI with a
| resulting 10x size reduction:
| https://github.com/skeeto/chess/commit/5c123b3
|
| I think this functions as a test case. For a game as simple
| as a chess UI, PNG would probably be fine unless you're code-
| golfing on the final output binary size or refusing to use
| common dependencies. But for _some_ programs (e.g. large
| video games), preloading all your assets is very common and
| decoding speed can be crucial. Maybe the assets could even be
| left in compressed form in memory in order to reduce the
| system requirements? I 'm not sure if this is common or not.
|
| Side note: video game assets are often _enormous_ in size
| because developers refuse to implement even very basic
| compression because of the supposed performance impact.
| Getting the decompression speed up can result in tremendous
| reduction in disk usage because it allows doing compression
| without losing performance.
| maccard wrote:
| > I'm not sure if this is common or not.
|
| > Side note: video game assets are often enormous in size
| because developers refuse to implement even very basic
| compression
|
| Be generous; you even said in your previous sentence you
| don't know if it's common or not, so how do you know
| developers refuse to implement basic compression? If it's
| that easy, I'm sure there are plenty of AAA game studios
| (including mine) that will hire you to just implement basic
| compression.
|
| There are enormous tradeoffs to make that are platform
| dependent; read speeds from external media are _incredibly_
| slow but from internal media may be fast. Some assets are
| stored on disk to mask loading/decompression. Lastly,
| assets are just enormous these days. A single 4k texture is
| just shy of 70MB before compression and a modern game is
| going to be made of a large number of these (likely
| hundreds of them), and many games are shipping with HDR -
| these are multiples of the size. That's becore you get to
| audio, animation, 3d models, or anything else.
|
| My current projects source assets are roughly 300Gb, and
| our on disk size is 3GB or so. My last project was 5Tb of
| source assets and 60GB on disk. Of course we're using
| compression.
| bscphil wrote:
| > Be generous; you even said in your previous sentence
| you don't know if it's common or not, so how do you know
| developers refuse to implement basic compression? If it's
| that easy, I'm sure there are plenty of AAA game studios
| (including mine) that will hire you to just implement
| basic compression.
|
| The thing I said I didn't know whether it was common was
| keeping assets in compressed form _in memory_. I admit I
| don 't know much of the specifics of how game rendering
| works. What I _do_ know something about is the extremely
| poor compression applied to many video games in their on-
| disk form. I 'm willing to grant that your studio may
| indeed be an exception to this, but the general principle
| isn't possible to deny. Just by enabling _lossless_
| Windows file compression on a game folder, you can
| frequently see the size of a game on disk drop by 50% or
| more, as I discuss in my comment here:
| https://news.ycombinator.com/item?id=34042164
|
| Surely a lossless format designed specifically for
| encoding assets would be even more effective and fast
| than generic Windows file compression!
| jcpham2 wrote:
| I was trying to explain to my son the other day when he
| was complaining about the Xbox without the drive slot. I
| asked him how big of a download Fortnite or call of duty
| were - I think he said 60 gigs and then I told him blu
| ray tops out at 50gb.
|
| He understands why the Xbox doesn't have the cd slot
| anymore.
| listenallyall wrote:
| Complex games used to be delivered on multiple floppy
| disks, later multiple CDs. I don't see the capacity of a
| single Blu-ray disc being a limiting factor.
| maccard wrote:
| One of the big limiting factors for a game like Fortnite
| is that the assets change significantly over time.
| Textures, materials, animations, audio have all changed
| dramatically over the last few years. There's likely very
| little from the initial install that is still usable, and
| thats before you get to file load order and
| fragmentation.
| tracker1 wrote:
| I don't recall having to swap discs on PS1/2/3/4 at all.
| zerocrates wrote:
| In addition to other examples given, Metal Gear Solid 1
| memorably has a disc-swap.
|
| Games heavy on prerendered video frequently were multi-
| disc: Final Fantasy 7 is three discs, 8 is four, 9 is
| four... Xenogears is multiple discs, as is Chrono Cross.
| Lots of JRPGs, though not exclusively: Riven was on 5 (!)
| discs, again a case of a lot of prerendered content.
|
| It was pretty rare on PS2 with DVDs, and as far as I know
| totally eliminated on PS3 with Blu-ray (Metal Gear Solid
| 4 has/had an "install swap" where it would copy over from
| the disc only a chapter at a time, but all coming from
| one disc).
|
| Then the concept made a comeback by the tail end of the
| PS4's life, with several games having "play" and
| "install" discs, though these aren't quite the same
| experience, as you just use the install/data disc once
| then put it away. Fittingly one of these PS4 multi-disc
| games is the remake of Final Fantasy 7 (one that covers
| only a relatively small portion of the original, to
| boot).
| maccard wrote:
| Offhand, many final fantasy games shipped on multiple
| discs, as did armoured core. Gran turismo and oddworld.
|
| The last of us part 2 and GTA 5 both needed multiple
| discs on PS4.
| tomku wrote:
| PS1 had dozens of games that shipped on multiple discs,
| PS2 had somewhat fewer but the ones that I remember off
| the top of my head are Xenosaga 2 and 3.
| willis936 wrote:
| FFVII shipped on 3 discs. Most of it was cutscenes and
| you better believe they were compressed to hell.
| willis936 wrote:
| It doesn't work as well for games like fortnite.
| Matchmaking map playlists tied to specific discs? Sure,
| it could be done.
| flohofwoe wrote:
| > video game assets are often enormous in size because
| developers refuse to implement even very basic compression
| because of the supposed performance impact
|
| This claim needs some real world evidence to back it up
| (and usually it's not about a performance impact, but
| instead a perceived image quality impact).
|
| IME a lot of care is taken for compressing asset data, and
| if there would be a chance to reduce the asset size by
| another few percent _without losing too much detail_ (that
| 's the important part), it would be done. In the end,
| textures need to end up in memory as one of the GPU
| compatible hardware compressed texture formats (e.g. BCx) -
| which is important not only for reducing memory usage, but
| mainly for increasing texture sampling performance on the
| GPU (reduced memory bandwidth and better cache locality
| when reading texture data from GPU memory).
|
| Those hardware-compressed texture formats rule out any of
| the popular image formats like JPEG, PNG etc... that might
| have a better overall compression, but are hard to decode
| on the fly to one of the hardware texture formats (but
| there are now alternatives like
| https://github.com/BinomialLLC/basis_universal), but even a
| generic lossless compressor (even good old zip) on top of
| BCx is already a good start.
| bscphil wrote:
| > This claim needs some real world evidence to back it up
| (and usually it's not about a performance impact, but
| instead a perceived image quality impact).
|
| We're talking lossless compression here, so image quality
| is not the issue.
|
| Fortunately someone else has already done this research.
| There's a tool for Windows to control the compact.exe
| behavior for individual folders called CompactGUI:
| https://github.com/IridiumIO/CompactGUI
|
| They maintain a database of compression results here: htt
| ps://docs.google.com/spreadsheets/d/14CVXd6PTIYE9XlNpRsxJ
| ...
|
| Reductions in storage use of greater than 50% are so
| common that they're hardly even worth remarking on. My
| experience with compressing a bunch of games is that the
| biggest gains come from compressing bloated asset packs.
| Hard to know what else could be taking up more than 50%
| of the storage space in a particular game.
| duskwuff wrote:
| > But for some programs (e.g. large video games),
| preloading all your assets is very common and decoding
| speed can be crucial.
|
| Those games typically don't need lossless image
| compression. There are much better (and faster) algorithms
| for lossy texture compression, many of which can even be
| decoded directly by the GPU. The S3TC family is one popular
| example.
|
| One interesting commercial product in this space is Oodle
| Texture: http://www.radgametools.com/oodletexture.htm
| kaetemi wrote:
| Lossy causes some issues with normal maps, so QOI seems
| good for those cases where lossless is preferred to
| balance loading (and streamed loading) performance and
| space use, but yes, in general S3TC is good for sRGB
| color textures in PC games.
|
| Using a lossy hardware compression (like S3TC) that's
| natively supported by the hardware is especially a good
| way to save on GPU RAM! Double the texture resolution for
| free, essentially.
| bscphil wrote:
| It's true that lossless is often not the best approach,
| although it's worth pointing out that anyone can
| implement Quite OK while both the approaches you mention
| are not really friendly to open source.
| duskwuff wrote:
| S3TC is patent-free as of October 2017, and is
| implemented in open-source graphics drivers.
| bscphil wrote:
| Are the best available compressors for the format open
| source as well? That would be news to me, although I
| admit I haven't looked into the format in quite some
| time.
|
| More generally, my point about video games was just that
| you can frequently cut their size by 50-75% just by
| turning on file compression on the game directory.
| Developers are obviously missing some easy wins in this
| area - including huge wins with lossless compression
| alone.
| ImHereToVote wrote:
| Use Universal Basis
| edflsafoiewq wrote:
| Look at Rich Geldreich's bc7enc_rdo.
| slimsag wrote:
| basisu (Binomial's Basis Universal GPU Texture Codec) is
| pretty much state of the art here. Open source, offers
| excellent compression and very quickly decodes to pretty
| much all GPU native formats.
| iainmerrick wrote:
| basisu is really impressive, but it's not perfect for all
| use cases.
|
| I tried using it in a WebGL game, but found that a)
| decoding was too slow, and b) the quality was too low.
|
| PNG is much bigger, so you'd think it wouldn't be good
| for a web game, _but_ once an image has been downloaded
| and cached, the most important factor is the decode-and-
| upload time. On the web, PNG and JPEG handily beat basisu
| there.
|
| In a different situation, basisu could have worked out
| for me. On native rather than web, maybe the decode time
| would have been fine. With more photographic rather than
| geometric assets, maybe the quality would have been fine.
| slimsag wrote:
| PNG/JPEG are not natively understood by GPUs, though.
| GPUs have compressed formats they natively understand,
| and basisu can transcode to them quickly. You'll be
| burning a lot more GPU texture memory as you'll be asking
| the GPU store raw image data instead of compressed image
| data.
| kaetemi wrote:
| The advantage of using a native hardware compression
| format is that you save on GPU RAM, which is especially
| useful for web which may display on mobile systems.
| willis936 wrote:
| What performance penalty? Decoding is often faster than
| moving more bits from storage.
| dmix wrote:
| It reminds me of that Steve Jobs insult thread, it's a
| technology looking for an audience.
|
| The pitch as I can tell is that the specification is simple.
| So the guy who spends a lot of time writing code based on
| specifications likes it?
|
| I guess that's the niche audience. Maybe a better pitch would
| be "image format specifications should be more like QOI".
| adgjlsfhk1 wrote:
| if you throw lz4 or zstd on top of it, of it, it actually can
| beat png
| oefrha wrote:
| So, if you throw another >100KB decoder on top of the 1KB
| decoder, you can beat png (haven't verified). What's the
| point.
| adgjlsfhk1 wrote:
| lz4 is also pretty small
| https://nigeltao.github.io/blog/2022/qoir.html is an
| implementation of QOI with some tweaks+lz4 and it's still
| pretty tiny
| masklinn wrote:
| Also I could see it with zstd (which is a lot more than
| 100k, though very fast indeed) but I'm a bit doubtful about
| lz4, it's generally worse than deflate (which png uses) at
| compression and qoi lacks filtering.
| duskwuff wrote:
| QOI's QOI_OP_DIFF and QOI_OP_LUMA opcodes can act like
| horizontal filtering once the results are fed into a
| stream compressor. There's nothing to provide vertical
| filtering, though, which is a pretty huge limitation.
|
| I wonder if you'd get better compression using a zigzag
| scan?
| adgjlsfhk1 wrote:
| there was some work done to find better scan
| arrangements. unfortunately, is pretty hard to do so
| without storing the previous row in memory which has a
| pretty large effect on speed
| robinsonb5 wrote:
| I once ported an LZ4 decoder from 68k to my own toy CPU
| design - the lz4_depack routine weighs in at a whopping 72
| bytes. https://github.com/robinsonb5/EightThirtyTwoDemos/bl
| ob/maste...
| duskwuff wrote:
| > if you throw lz4 or zstd on top of it, of it, it actually
| can beat png
|
| PNG is literally just "perform some simple filtering on the
| image data, then run that through zlib and wrap it with some
| metadata". It shouldn't come as any great surprise that you
| can outperform PNG with a newer stream compressor. You'd
| probably get even better results by using PNG's filters
| instead of QOI.
| nh2 wrote:
| > You'd probably get even better results by using PNG's
| filters instead of QOI
|
| Did anybody ever try this? It would be quite interesting
| and does not seem too difficult.
|
| The only thing I could find is
| https://github.com/catid/Zpng which does not use the normal
| PNG filtering.
| mananaysiempre wrote:
| LZ4[1] intentionally compresses _worse_ than Deflate--where
| Deflate is LZ77 with Huffman in a bitstream, LZ4 is just
| LZ77 with a good choice of octet-aligned encoding. It's
| "we're saturating Gigabit Ethernet and have some compute
| left over" compression, not "we need to squeeze our backups
| as much as possible" compression. If filtering+LZ4 does
| better than Deflate, then you've chosen the filter well.
|
| Curiously, for some kinds of serialized binary data varints
| or even zero-packing[2] can be a good enough filter[3].
|
| [1] https://lz4.github.io/lz4/
|
| [2] https://capnproto.org/encoding.html#packing
|
| [3] https://news.ycombinator.com/item?id=24073752
| masklinn wrote:
| Given the context, simplicity and control. I assume part of the
| inefficiency can be reclaimed by compressing the assets
| separately, although the lack of filtering would hurt.
|
| Encoding and decoding speed as well, because qoi is much
| simpler (simplistic even) it decodes at 3x libpng (which I'd
| assume is more relevant than the 20x compression for OP, though
| then encode might be more relevant for other applications but
| then IO trade offs rear their ugly heads).
| makapuf wrote:
| Its a tradeoff. Decoder is real fast and can be used in
| embedded contexts (or ported to languages simply). Encoder is
| also really fast which can be useful for game textures by
| example.
| whateveracct wrote:
| golf
| Dylan16807 wrote:
| Golf of what sort? It's hard to beat RLE or RLE+palette for
| minimal code size. I'd expect either one of those to be a
| tenth the size of a QOI decoder.
| adgjlsfhk1 wrote:
| these do well on synthetic images but really poorly with
| noise. QOI manages pretty good performance even with noise.
| Dylan16807 wrote:
| That doesn't really explain the code golf answer.
| eps wrote:
| QOI is in the same ballpark as RLE simplicty-wise but
| performs much better in a larger number of common cases.
| That's very much "golf".
| Dylan16807 wrote:
| I don't know about that. My estimate would be that QOI is
| ten times as complex as RLE and ten times less complex
| than DEFLATE-style compression. It could (barely) share a
| ballpark with either one.
| AceJohnny2 wrote:
| Embedded.
|
| We're currently fighting to gain 10-20kB in our binary.
| masklinn wrote:
| Ah but will you trade that for 5MB in assets?
| AceJohnny2 wrote:
| Eh, the assets can be streamed. The decoder resides in
| .text
| audunw wrote:
| Embedded can mean many different things, so it's still
| not clear what the challenge is..
|
| But it sounds to me like you're trying to reduce the
| amount of code on the NVM of an MCU, where space is very
| limited, but you have slower off-chip (QSPI, SDC, ..)
| memory where you can store images?
| ardwindo wrote:
| Some people consider implementation simplicity as a virtue.
|
| It's nice to be able to understand large parts of your stack at
| a source code level.
|
| I'd like to see more minimal viable X.
| spullara wrote:
| Yeah, but that doesn't make any sense at all. So, don't
| listen to them. If any photo saves 50kb from compression you
| can easily see that thinking this is a mistake.
| csande17 wrote:
| JavaScript developers tell me that disk space and network
| bandwidth are cheap these days. While they're mostly saying
| that to try and justify extremely bad architectural
| decisions (what's a couple thousand NPM dependencies
| between friends?), maybe we can apply that logic here.
| Maybe it's worth making every image file twice as big, if
| we can use a much simpler decoder implementation that's not
| a constant source of bugs and security vulnerabilities.
| Dylan16807 wrote:
| By using a bespoke decompressor? No thanks. Take a
| standard format and make sure all array bounds are
| checked. Data-oriented compression formats tend not to be
| very complicated and can be implemented with few
| instances of simple data structures.
| hnlmorg wrote:
| I'm not saying I agree with them but I do sympathise with
| the argument.
|
| Is old timers spent the first part of our career understand
| most, if not all, of the technology stack. It's actually
| really empowering having that level insight. So I can see
| why people might still crave for those days of simplicity
| back.
|
| It's not not a decision I'd personally follow but I do see
| the attraction in their decision.
| Dylan16807 wrote:
| It's worth understanding DEFLATE, and then you can have
| the same amount of insight into PNG.
| hnlmorg wrote:
| I'm no expert in this field but from what I've learned
| about PNG and deflate, there is a little more to PNG than
| just deflate.
| Dylan16807 wrote:
| Yes but you can learn those parts just about trivially.
| mananaysiempre wrote:
| A minimal viable Deflate decompressor (that you'd need for
| PNG) is not exactly complex[1], although slower than mainline
| zlib.
|
| [1] https://github.com/madler/zlib/tree/master/contrib/puff
| rsp1984 wrote:
| _There are a lot of dimensions on which QOI could be improved,
| but most cases involve trade-offs, e.g. more complexity for
| better compression. The areas where QOI could have been strictly
| better, the dimensions on which it is not on the Pareto frontier,
| are more meaningful criticisms -- missed opportunities._
|
| This summer I spent a lot of time researching lossless
| compression formats as a streaming format for our 3D capture and
| reconstruction engine. QOI was on our list too.
|
| My biggest criticism about QOI is that in many cases it doesn't
| compress at all, or even _increases_ size. It works well on the
| demo images that come with the package but these are carefully
| selected. It also works well on high-res, high-quality images
| with lots of single-color background and /or smooth gradients.
| But give it grainy, noisy, smaller-format images and it
| completely breaks down.
|
| We ended up sticking with PNG, which btw. has fast open source
| implementations too [1][2].
|
| [1] https://libspng.org/ [2] https://github.com/richgel999/fpng
| phoboslab wrote:
| While what you're saying is true - QOI performs badly with some
| types of images - I want to push back on the notion that the
| demo images have been "carefully selected" to tell a narrative.
| TFA alleges the same. This is absolutely not the case!
|
| The benchmark suite[1] I compiled contains many different types
| of images. The "industry standard" sets like the Kodak and
| Tecnick Photos, texture packs and icons are complete. No images
| have been removed from these sets. Some of the other
| collections (photos and game screenshots from Wikipedia and
| those from pngimg.com) are a random sample. I did not remove
| any images just because they compressed badly.
|
| Also, the fact that some images compress badly is a non issue,
| _if_ the whole set of assets that you need for your game /app
| combined have an acceptable compression ratio. If that's not
| the case, by all means, chose another image format.
|
| On average, for a lot of assets types, QOI usually performs
| quite ok.
|
| [1] https://qoiformat.org/benchmark/
| rsp1984 wrote:
| Fair enough. In our testing we couldn't get it to compression
| ratios lower than ~90% on the kind of images we tested (low
| quality webcam-type sensors, sub-VGA resolution), while it
| achieved very impressive compression ratios on the demo
| images, so I assumed a selection was made. Perhaps it's just
| works really well for certain kinds of images and doesn't for
| others.
| MacsHeadroom wrote:
| Low quality sensor photographs are all but impossible to
| compress because they're filled with compressions worst
| nightmare: random noise.
|
| Lossless compression of random noise isn't possible and
| lossy compression of it requires content aware algorithms
| (e.g. AI) to get results.
|
| Even if you don't readily see the random noise, it's there.
| Subtly changing the hues of pixels just slightly enough to
| be incompressible.
| rsp1984 wrote:
| These sorts of images do compress quite ok though (pun
| intended) with PNG.
| CJefferson wrote:
| While you can't compress the random noise itself, it's
| often easy to still get decent compression of the whole
| image, depending on how serious the noise is.
|
| Imagine an image with large blocks of constant colour in
| 8-bit colour depth has 2 bits of random noise on every
| pixel. We indeed can't ever compress to less than 2 bits
| per pixel, but we can still get down to that.
| brookst wrote:
| And the frustrating thing is that the "noise" is actually
| information; it tells you something about the capture
| device and encoding toolchain. It's just an incredibly
| inefficient way to encode "this was captured on a cheap
| image sensor on a severely memory constrained device"
| theamk wrote:
| They might be impossible to compress using RLE-based
| mechanisms, but the theoretical possibility is there. The
| noise range for the pixels is not 0-255, so the image has
| less entropy than a fuly random one and thus should be
| compressable.
|
| I am imagining something like a "base layer" with
| averaged brightness + arithmetic coding for differences
| might do it.
| adgjlsfhk1 wrote:
| QOI will be pretty bad with exceptionally noisy images.
| that said, if you denoise first, you aren't degrading image
| quality.
| skrebbel wrote:
| > QOI usually performs quite ok
|
| Nice :-)
| fedeb95 wrote:
| Since when writing encoders and decoders in one sitting is a
| metric for a good asset format?
| citizenpaul wrote:
| My fav format is whatever is widely supported so I don't have to
| bash my head on the wall dealing with all kinds of conversions
| and other issues.
|
| My least fav is when some system i have to deal with creator
| chose their superior fav obscure format that no one uses and now
| i have to deal with it too.
| eska wrote:
| Is RGBA order really less common than ARGB?
| kevingadd wrote:
| Depends on your platform, there are some platforms where the
| compositor/hardware demand ARGB and some where they demand
| RGBA. As a result if your backbuffer/etc are not in that format
| you eat some overhead.
|
| This isn't a big justification for it in a texture format,
| though. A channel swap isn't that expensive to do at load time
| and the driver can often do it for you during the upload
| depending on the API you're using. If you really want to load
| blazing fast your textures should be pre-compressed in hardware
| formats that you can mmap in, not stored in QOI or PNG.
| dottedmag wrote:
| Without sacrificing much simplicity channel swap can be made
| even more inexpensive with PSHUFB on x86 or VTBL on aarch64.
| dannyw wrote:
| Sounds like a great way to lose your files in 10 years unless you
| re-implement the decoder after wading through link rot.
| aaron695 wrote:
| dottedmag wrote:
| The size of decoder is so small, so one can append the source
| code of decoder to most images and not make them much bigger in
| the process.
| nness wrote:
| I spend some free time reverse-engineering obscure game
| formats, and my observations is that this is universally true
| of everything.
| ardwindo wrote:
| The author notes his decoder is 100 lines of libc-free C code:
| these files are safe!
| qayxc wrote:
| Why wouldn't they just use TGA? Just as simple, more flexible
| if need be and understood even today by most image
| manipulation programs and 3d modelling software.
| gregp87 wrote:
| I'm developing game engine + game and since several months I use
| the QOI format. This format is amazing in my situation: I can
| load the textures much faster compare to PNG. Generally, it is
| 2-3 times faster even if the size on disk is 1.5x-2.5x larger.
| Note: I use a NVME disk and I'm not sure my statement is still
| true on less performant hard drive.
| Dylan16807 wrote:
| Try Zstandard. It can decompress about four times as fast as
| zlib, so it should do very well on PNGs. Also give LZ4 a shot.
| ninepoints wrote:
| Why are you using PNGs as a texture format? Generally, you'll
| use BC textures for the most part, or barring that, your images
| will be compressed as part of your archive format with some
| sort of super-compression algorithm that compresses the pakfile
| block-by-block. Perhaps you're referring to your texture
| compression/conversion pipeline which ingests PNG from your DCC
| tool of choice?
| bsdetector wrote:
| There's a run length for identical pixels but no run length for
| literal pixels.
|
| Some images barely compress which means there should be many runs
| of uncompressed pixels. Even if only a few pixels long, not
| having a byte of overhead for each should improve size on these
| pictures. Maybe they just wanted it to win on throughput by
| having fewer branches.
___________________________________________________________________
(page generated 2022-12-18 23:03 UTC)