however I found that just keeping the GIF instead saved more bytes than trying to inline the data inside the class file (17 bytes to be precise, so it was close). I have 3 image files and I tried inlining them all into my one class file - though it did compress pretty well, the JAR that simply used GIFs turned out to be smaller.

It's hard to say without knowing what data you're packing, but there are a few things I can say:

1. You're probably not reducing your information in any significant fashion. Just changing the format is no guarantee of better results.

2. Whenever you change your compression method, it's always important to include the decoder into the computations. When I use SuperPackME, I'm accepting a fairly hefty cost in the code for the image decoder, but I more than make up for it in the space saved in the images. I did some tests with oNyx's JetPack game last year and found that the low number of images he used combined with the low number of colors meant that SuperPack (not the ME version) would actually be larger.

Keep in mind that you're wrestling with the theory of information. If you don't fully understand how your data is stored, it can be difficult to further reduce it.

Quote

something to note though, as I said before, I'm not familiar with bitpacking, so it is very possible that the String I made just isnt small enough. Do you know a better method to inline that image? do you have a tutorial for bitpacking? Im always open to learning something new

Bitpacking is a simple concept. There are 8 bits in a byte, right? So let's say you have an image that only has two colors. If you store it as a PNG, the PNG will store 4 bytes (32 bits) per pixel. That's a lot of wasted space for only two values! But if you look at each bit as a color, then you can pack the image into 1 bit per pixel. Here's the results for a 320x200 pixel image:

the change is noticable but why is it when you use pngout (or something similiar) it doesn't come close to 82K? The clouds.gif file itself is only 632 bytes! That's even smaller than the bitpack example above, unless I'm not doing math right (I am a bit tired ).

Also, when you say " look at each bit as a color," what do you mean exactly? (code-wise)

the change is noticable but why is it when you use pngout (or something similiar) it doesn't come close to 82K? The clouds.gif file itself is only 632 bytes! That's even smaller than the bitpack example above, unless I'm not doing math right (I am a bit tired ).

Your math is more or less fine. (Except that your image has three colors, meaning that you need 2 bits per pixel. That, and GIFs only store one byte per pixel, making the original ~20K in size.)

It's the compression you're not taking into account. The final GIF or PNG file will be compressed. You're trying to compare that against the raw bitpacked data. You have to look at both of them both before compression (which you do above) and after compression to see how they compare.

Now your clouds.gif file is 632 bytes. It's fully compressed down from 20K as one would expect it to be. Now when I run it through SuperPackME, the image actually balloons to 5260 bytes*. But if I run it through Infozip (the same step that is taken during JARing), the image drops to 575 bytes! A 57 byte savings! 7Zip would probably do an even better job.

Now if you have a number of these images, the difference in sizes would quickly add up. In addition, since SuperPackME separates the colors from the image data, the ZIP compressor can find further redundancy across multiple images! To give an example, take a look at the attached image. Your GIF and mine are a total of 1,802 bytes in size. SuperPacking again balloons the size to a whopping 15,256 bytes. But if you compress that with Infozip, you find that it's only 1,381 bytes! That's now a 421 byte savings! The compressor does so well because it sees that clouds.gif and camo-desert.gif have very similar image data. (3 colors each, many large fields of color. The values are the same since the actual RGB color is separated.) So it's able to reuse its compression tokens between them, thus resulting in better compression.

Quote

Also, when you say " look at each bit as a color," what do you mean exactly? (code-wise)

Basically, you modify each byte to put the bits where you want them. i.e.:

1. Start with the byte: byte b = 0; (b = 00000000 in binary)2. Add a bit: b |= 1; (b = 00000001 in binary)3. Shift the byte to the left by one position: b <<<= 1; (b = 00000010 in binary)4. Go to step 2 and repeat for the next bit.

Now with that figured out, you may want to reread the info on the SuperPack formats. It might make a lot more sense now. Also, the source code is available if you want to see bitpacking in action.

The PNG file format supports all sorts of palettized pixel formats, not just 8bpp.

The PNG format supports it, but Java doesn't. It was one of the first things I tried when I was trying to shrink images for the 4K contest. I found that Java's ImageIO libraries would throw an exception if the PNG had a low number of colors. I'm guessing that the programmers didn't have the 4K contest in mind when they wrote the loader code.

The PNG file format supports all sorts of palettized pixel formats, not just 8bpp.

The PNG format supports it, but Java doesn't. It was one of the first things I tried when I was trying to shrink images for the 4K contest. I found that Java's ImageIO libraries would throw an exception if the PNG had a low number of colors. I'm guessing that the programmers didn't have the 4K contest in mind when they wrote the loader code.

Try this out. This code will take a gif file and convert it to a simple string one character per color. It will produce source code in the image.gif.txt file. This code should be inlined in the game source file. I find the not doing the bit shifting and leaving the compression to the compression tools is best. I have tried superpackme and direct image loading. This way looks like the smallest.

Writing a codec for png files is incredibly easy, the documentation on the format is both clear and concise,and its usage of zlib for compression simplifies the task still further.It is embarrasing that Sun are having such problems implementing such a trivial codec,and extremely annoying that a problem raised 16 months ago, that could be fixed by one person in less than a week, has been delayed for so long.Untold man hours have been wasted by different people detecting and having to work around this bug.

Having said that, my confidence in the team overseeing image manipulation related systems within J2SE is already pretty low.I recently came to install JAI, and was mystified to find a download page with 16 installers!!!

BTW, one note on SuperPackME. I've said this before and I'll say it again. If you use SuperPackME, DO NOT UNDER ANY CIRCUMSTANCE tile your images inside a single file. They should be split up into separate and discrete images. If you combine them, you WILL screw up SuperPackME's attempts to make your data more compressable.

It is embarrasing that Sun are having such problems implementing such a trivial codec,and extremely annoying that a problem raised 16 months ago, that could be fixed by one person in less than a week, has been delayed for so long.Untold man hours have been wasted by different people detecting and having to work around this bug.

1. I'm surprised more people haven't simply picked up JIMI and used that instead.

2. I wouldn't be so critical. Even fixing a small bug requires a HUGE effort for QA and regression testing. Sun's customers require very high reliability between versions. A single regression could cost millions of dollars (or lives).

Quote

Having said that, my confidence in the team overseeing image manipulation related systems within J2SE is already pretty low.I recently came to install JAI, and was mystified to find a download page with 16 installers!!!

Well, demystify yourself. The variety of installers was Sun's attempt to "help". They stopped providing them with newer APIs when they realized that it was a Good Thing(TM) when programmers had to learn how to install libraries. Just download a ZIP file and be happy.

Quote

This, coupled with the poorly documented, and badly designed JAI API makes me think it doesn't deserve to be branded as an official Sun product.

THAT, I agree with. However, the ImageIO stuff came partly from the work on JAI. So I wouldn't be too critical of the ancient API. I'm actually surprised that anyone uses it anymore. In most situations where exceptional image processing needs to be performed, it tends to be easier to roll your own solution rather than going with a generic one that might meet your needs.

Quote

If Java was Open Source, issues like this would be fixed within days - not years.

I have slightly modifed Rick's Convert program to achieve another 53 bytes from the orignial version posted with my 4bit input gif.

what i have done it anaylsed the frequency of the 'printable' characters in a class file which has gone though proguard and jarg and have most frequent colour palette indecies from the input graphic correspond with the hightest 'printable' character frequencies.

This 53 byte saving plus the much shorter code needed to create palette swapped images has reduced the size of the jar a total of 203 bytes.

It may or may not help you with your 4k games, but i offer it for people to use if they wish.

// order the colormap to correspond with the best order colour mapIndexColorModelicm = (IndexColorModel) image.getColorModel();int[] palette=newint[icm.getMapSize()];icm.getRGBs(palette);int[] colourFreq=newint [icm.getMapSize()];

Good wook. I have a version that does the same thing. However I did not think to oder the characters by the freq in the class file. I just picked mine by what I thought the freq was. As I hava a bunch of level data. I ordered mine by that order. I will have to try and look at the class file freq and see if my off the cuff ordering is sub optimal

Thanks, for the code. I tried it but it actually added a few bytes. I guess although it was now using more frequent characters it could not find as many long patterns to compress. Also I was already using the top 3 most frequent charaters so it did not have a chance to improve much. Still it was worth the try.

Thanks, for the code. I tried it but it actually added a few bytes. I guess although it was now using more frequent characters it could not find as many long patterns to compress. Also I was already using the top 3 most frequent charaters so it did not have a chance to improve much. Still it was worth the try.

did you remember to analyze the class *with out* the embedded graphic. including the embedded graphic will skew the statistics.

// order the colormap to correspond with the best order colour mapIndexColorModelicm = (IndexColorModel) image.getColorModel();int[] palette=newint[icm.getMapSize()];icm.getRGBs(palette);int[] colourFreq=newint [icm.getMapSize()];

out.flush();out.close(); }catch(Exception _ex) {System.out.println("USAGE: java Convert <image> <transparent Colour X> <transparent Colour Y>");System.out.println("Output: <image>.txt - the data and logic to be embedded into your game.");System.out.println("");System.out.println("The transparent Colour X,Y are the co-ordinates of the colour in the image which is to be deemed transparent.");System.out.println("IMPORTANT: THE X,Y CO-ORDINATES MUST BE OF THE *FIRST* OCCURANCE OF THE TRANSPARENT COLOUR.");System.out.println("These co-ordinates are optional. In their absence the pixel (0,0) will be deemed transparent.");// System.out.println("have no-transparency set the transparent Colour X to -1 and transparent Colour X to -1");

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org