<blockquote>
<p>However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.</p>
</blockquote>
<p>There is. It's called... scaling the largest mipmap to produce the smaller ones. That's essentially what's happening when you generate mipmaps directly: you are &quot;compressing&quot; the lower mipmaps by taking advantage of the fact that all these images are algorithmically built from the largest mipmap. Since you only store the largest mipmap, the other mipmaps take up zero bytes. Then you &quot;decompress&quot; them by scaling them as they are loaded.</p>
<p>The principle cost of CPU scaling is not the computation of the lower-mipmap level itself. It's the memory bandwidth costs of reading from the higher mipmap and writing to the lower one. It doesn't really matter what your algorithm for computing the lower one is; if it requires reading every pixel of the higher mipmap, it's basically going to cost the same thing.</p>
<p>If you've got access to a GPU, you ought to be able to scale it there with rendering operations or even just linearly-interpolated blitting operations.</p>

CC BY-SA 4.0
2021-07-05T22:44:03.637Z
As far as I can tell, the main cost of scaling is the interpolation (note that hardware acceleration sadly is not available to me). If I understand your proposal correctly, it would use nearest interpolation by selecting the correct pixels, which is not okay in my case.
piegames
CC BY-SA 4.0
2021-07-05T22:55:32.183Z
@piegames: "*the main cost of scaling is the interpolation*" How did you make that determination? Your CPU either is extremely old (and thus closer to your memory bandwidth) or your code is highly unoptimized, doing things like int-to-float conversions and the like. Box filter scaling ought to be a few shifts and multiplies, nothing remotely like the thousands-of-cycle cost of a cache miss.
Nicol Bolas
CC BY-SA 4.0
2021-07-05T17:56:07.040Z
2021-07-05T18:01:52.140Z
2021-07-05T18:01:52.140Z
Nicol Bolas
<p>You could look into wavelet image compression, which effectively stores a mip pyramid &quot;top down&quot; with each level storing only the diffs from the next-smaller level. This would effectively let you reconstruct whichever mip level you wanted from the same file at load time, with the file being the same overall size as only the base mip. However, it is likely more expensive to decompress than PNG for the same reason.</p>
<p>The JPEG2000 format implements a wavelet compression method (as well as quantization and bitstream coding like other JPEG formats). I'm not sure if there are JPEG2000 libraries that support efficiently reconstructing multiple resolutions of the image while loading though.</p>

CC BY-SA 4.0
2021-07-05T17:47:36.943Z
PNG is going to be *smaller* than most BC formats, not bigger. The advantage of BC formats is that GPUs can read them directly, without decompression.
Nicol Bolas
CC BY-SA 4.0
2021-07-05T22:46:08.537Z
Storing only difference to the next higher level is an interesting idea. Maybe it can somehow be done on a pixel level instead of wavelets? Of course, this wouldn't save any pixels, but maybe they'd then contain less information and thus be better compressed by png?
piegames
CC BY-SA 4.0
2021-07-05T16:56:10.850Z
2021-07-06T04:57:23.173Z
2021-07-06T04:57:23.173Z
Nathan Reed
<p>Because scaling operations are prohibitively expensive in my current rendering stack, I have to pre-render my images in all desired sizes and cache the result on disk. At the moment, I do this by dumping one PNG file per image size. However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.</p>

CC BY-SA 4.0
2021-08-05T13:27:24.147Z
Is there a PNG compression scheme that allows block compression?
pmw1234
<image><compression><mipmap>
Space efficient storage/compression of multiple scaled values (mip maps)
piegames
# Space efficient storage/compression of multiple scaled values (mip maps)

(Asked by: username_0 on 2021-07-05)

Because scaling operations are prohibitively expensive in my current rendering stack, I have to pre-render my images in all desired sizes and cache the result on disk. At the moment, I do this by dumping one PNG file per image size. However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.

**Tags:** image, compression, mipmap

> **Comments:**
> **username_1**: Is there a PNG compression scheme that allows block compression?  

---

## 2 answers

### Answer by username_2 on 2021-07-05. Score: 1

> However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.

There is. It's called... scaling the largest mipmap to produce the smaller ones. That's essentially what's happening when you generate mipmaps directly: you are "compressing" the lower mipmaps by taking advantage of the fact that all these images are algorithmically built from the largest mipmap. Since you only store the largest mipmap, the other mipmaps take up zero bytes. Then you "decompress" them by scaling them as they are loaded.

The principle cost of CPU scaling is not the computation of the lower-mipmap level itself. It's the memory bandwidth costs of reading from the higher mipmap and writing to the lower one. It doesn't really matter what your algorithm for computing the lower one is; if it requires reading every pixel of the higher mipmap, it's basically going to cost the same thing.

If you've got access to a GPU, you ought to be able to scale it there with rendering operations or even just linearly-interpolated blitting operations.

> **Comments:**
> **username_0**: As far as I can tell, the main cost of scaling is the interpolation (note that hardware acceleration sadly is not available to me). If I understand your proposal correctly, it would use nearest interpolation by selecting the correct pixels, which is not okay in my case.  
> **username_2**: @username_0: "*the main cost of scaling is the interpolation*" How did you make that determination? Your CPU either is extremely old (and thus closer to your memory bandwidth) or your code is highly unoptimized, doing things like int-to-float conversions and the like. Box filter scaling ought to be a few shifts and multiplies, nothing remotely like the thousands-of-cycle cost of a cache miss.  

---

### Answer by username_3 on 2021-07-05. Score: 0

You could look into wavelet image compression, which effectively stores a mip pyramid "top down" with each level storing only the diffs from the next-smaller level. This would effectively let you reconstruct whichever mip level you wanted from the same file at load time, with the file being the same overall size as only the base mip. However, it is likely more expensive to decompress than PNG for the same reason.

The JPEG2000 format implements a wavelet compression method (as well as quantization and bitstream coding like other JPEG formats). I'm not sure if there are JPEG2000 libraries that support efficiently reconstructing multiple resolutions of the image while loading though.

> **Comments:**
> **username_2**: PNG is going to be *smaller* than most BC formats, not bigger. The advantage of BC formats is that GPUs can read them directly, without decompression.  
> **username_0**: Storing only difference to the next higher level is an interesting idea. Maybe it can somehow be done on a pixel level instead of wavelets? Of course, this wouldn't save any pixels, but maybe they'd then contain less information and thus be better compressed by png?  

---

