Wavelet Image Compression

If there is something important you think is missing in the current version of ZGameEditor then you can post a feature request here!

Moderator: Moderators

Post Reply
keymasher
Posts: 39
Joined: Sun Feb 20, 2011 8:54 am

Wavelet Image Compression

Post by keymasher »

Today I was trying to pull off Iñigo's wavelet image comprssion in zge (scroll down to see the colour images) since my textures raw data are huge in zges final output.

The idea is to separate the chroma(greyscale) and luminance and blend them back together.

But I had some troubles combining a 32x32 image with a 256x256 image. I was hoping to BitmapFromFile then BitmapZoomRotate then BitmapCombine with another BitmapFromFile.

Or is there someway of compressing the textures? From the threads I read i saw either go procedural or hope upx compresses it enough.
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

Hmm,

The only way for that to make sense is when you "pack" 4 greyscale pixels per integer in a Array, and construct your Bitmap from that. When importing a greyscale image using BitmapFromFile, ZGE still treats it as a 24-bit per pixel source ( although it will compress better using UPX at that point ) causing you to end up with more data then the original full-size color image.

And UPX can actually increase* the size of your image data depending on their nature .. there's always the option of porting / writing your own compression library though.

*If that's the case, give the UPX LZMA option a try in Tools>Settings.

K
Last edited by Kjell on Thu Feb 24, 2011 1:37 pm, edited 1 time in total.
keymasher
Posts: 39
Joined: Sun Feb 20, 2011 8:54 am

Post by keymasher »

thats a great idea, i have to pass out now, but ill make that my exercise for tomorrow and post my work :)
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

try this,. .

Post by jph_wacheski »

I had wanted to do something similar for different reasons, previously,. but you question gave me an idea,. I just store the image data in an array and then pull it back out in the larger bitmap. Seems to work great.

Perhaps both the BitmapLoad and the BitmapFromFile components could have an "Upscale" tick box? It could be usefull to also have them load smaller images, and just place them in the top left of the larger bitmap,. . then flips and stuff could be preformed..,

The luma/chroma compresion is very interesting,. the human mind is a strange object eh. face recognition is also an interesting field of study.. ,

NOTE: the F5 key is your friend when working with bitmaps,. esp. like this,. .
Attachments
up_sample.zgeproj
an example of upsampleing to an array,.
(1.5 KiB) Downloaded 512 times
iterationGAMES.com
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

:)

Yea that approach works just fine ( in fact, you have to take that route when loading external images during runtime ).

Seems like keymasher wants to interpolate between the pixels though instead of simply using nearest neighbor. Attached is a example ( written for performance, not for clarity ).

K
Attachments
Bilinear.zgeproj
Updated ( contained a small mistake )
(2.82 KiB) Downloaded 519 times
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

@keymasher

By the way, in case you're wondering how to store & retrieve 4 grayscale pixels from a single integer .. use something like this.

Code: Select all

int P, P1, P2, P3, P4;

// Four unsigned 8-bit values ( 0-255 range )

P1 = 16;
P2 = 32;
P3 = 48;
P4 = 64;

// Generate 32-bit integer from four 8-bit values.

P = (P1<<24)+(P2<<16)+(P3<<8)+P4;

// Generate four 8-bit values from 32-bit integer

P1 = (P & 0xFF000000) >> 24; // P1 = P >> 24
P2 = (P & 0x00FF0000) >> 16;
P3 = (P & 0x0000FF00) >>  8;
P4 = (P & 0x000000FF) >>  0; // P4 = P & 0xFF
K
keymasher
Posts: 39
Joined: Sun Feb 20, 2011 8:54 am

Post by keymasher »

I figured directly populating an array would be slow and horrible to manage in zge script, so I decided to pack all the data into an image. I tried using grayscale(8 bit values) but I noticed the amount of data just overshot the previous bitmap size.

I also noticed than adaptive indexed colour of chroma actually didnt look to bad, and then when you overlay the luminance its pretty damn good!

I figured I could then split up a 24 bit integer(pixel information) into 6, 4bit indexed colours AND save the 16 colour palette with room to spare. Doing this I could fit all the data I needed into the next smallest texture size - i.e a 256x256 image became a 128x128 'image' with palette data.

So I wrote a python script to pack all the data in an image and output it (its in the attached zip), requires pil. Just feed it your grayscale image and it'll do the rest.

Now I had this image I had to unpack it in ZGE, and I thought I got pretty close, but something went horribly wrong, my ChromaPalette Array seems to be all 0's.

Also, as it stands it would be abit cumbersome to setup for multiple textures.

I've attached all my work - hoping that someone can see where I went wrong.
Attachments
SmallTextures.zip
(532.01 KiB) Downloaded 513 times
User avatar
VilleK
Site Admin
Posts: 2274
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Found one thing, changed:

Code: Select all

int v = ChromaPalette[ChromaOutput[xpos*ypos]];
To:

Code: Select all

float v = ChromaPalette[ChromaOutput[xpos*ypos]] / 256.0;
Because when you assign this.r etc in a bitmapexpression it expects colors in float values.
Attachments
SmallTextures.zgeproj
(28.86 KiB) Downloaded 533 times
keymasher
Posts: 39
Joined: Sun Feb 20, 2011 8:54 am

Post by keymasher »

Alright so i fixed my ghetto encoder/decoder and working great, tho it had nothing to do with wavelets.

While searching for more information I found that haar wavelet compression has already been implemented in delphi by another demoscene coder(toxic avenger/ainc) and he released source to public domain

http://ainc.de/Wavelet.htm

Would it be worth implementing into zge?
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

Well,

One of the reasons that ZGE has such a small footprint is because the runner doesn't include any format decoders. If we're going to break that, I think it should be for something a little more conventional .. like JPG.

A wavelet ZLibrary can certainly be useful though. Here's a size comparison based on a 512x512 image ( 64x64 chroma ).

Image

JPG brings it down to only 37 KB though ( uncompressed & similar quality ), compared to the 151 KB of the Wavelet ( LZMA compressed ).

K
luminarious
Posts: 4
Joined: Thu Sep 24, 2009 5:14 pm
Contact:

Smallest public domain JPEG library, in C

Post by luminarious »

Could this be used as inspiration in providing some support for JPEG/ PNG/ BMP/ TGA without considerably bloating things? http://nothings.org/stb_image.c
User avatar
Kjell
Posts: 1876
Joined: Sat Feb 23, 2008 11:15 pm

Post by Kjell »

:?

There's some major overlap in features between those formats. PNG & TGA both do the same thing as BMP / PIC + GIF combined, but use a different ( lossless ) compression method. And HDR is a straight-up Bitmap ( RGBE ) format with a re-purposed Alpha Channel. JPG is the only truly different one ( as it is lossy ).

Don't get me wrong, I use external TGA / PIC ( Softimage ) files in my ZGE projects all the time, nor do I care much about footprint ..

K
Post Reply