Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Storing image data in java files?  (Read 3695 times)
0 Members and 1 Guest are viewing this topic.
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Posted 2005-12-19 09:45:41 »

This is for the 4k competition.

I'm wondering if there is a way to store or define, let's say a tiny 150 byte gif image that is 16x16 and 8 color (incl. transparency), IN JAVA?

I must say gif format compresses those kind of images amazingly well, 256 pixels in 8 different colors in just 150 bytes Smiley I'm pretty sure I would need a whole lotta more of bytes to define that image in Java. Is there a trick for doing this or is it simply impossible?



Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #1 - Posted 2005-12-19 09:55:18 »

The obvious solutions like putting it into a string or some array doesnt work (its bigger). You could try superpackme (use the search function). Well, if you only use 8 colors you could use some palettelized string with characters >0 and <0x7f (eg 'a' to 'h'). Each pixel takes then only 1 byte and it gets zip compressed afterwards anyways.

弾幕 ☆ @mahonnaiseblog
Offline cylab

JGO Ninja


Medals: 38



« Reply #2 - Posted 2005-12-19 14:11:09 »

Quote
The obvious solutions like putting it into a string or some array doesnt work (its bigger).

I just tested this. A simple "Hello World" class file has 369 bytes. Adding a 256 byte array (private byte[] image=new byte[]{ <256 values> };) blows the class file up to 2035 bytes Sad

Mathias - I Know What [you] Did Last Summer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #3 - Posted 2005-12-19 14:18:58 »

And how big was the class file without the byte array?

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 744
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2005-12-19 19:04:46 »

8 colors = 3 bits per pixel
256px * 3 = 768 bits = 96 bytes (= 12 longs...?)

I think you can use less than 96 bytes by drawing your image through code.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline cylab

JGO Ninja


Medals: 38



« Reply #5 - Posted 2005-12-20 01:13:24 »

@Riven
I think he is after the smallest possible classfile size, which is dependent on the byte code javac produces to represent the image bytes.

@appel
without the byte[] it was 369bytes, so it needs 1666 bytes to represent 256 bytes in JVM byte code Sad it might be better to put the gif inside the jar (if the contest rules allow this) and use ImageIO.read(XYZ.class.getResource("small.gif"))


Mathias - I Know What [you] Did Last Summer!
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #6 - Posted 2005-12-20 11:46:22 »

I've discovered a method to compress my gif images from 2 kb down to mere ~200 bytes, and even strip away some Java code that does the getImage(), and hence maybe strip down those 2kb's in my 4kb project down to 0kb.

I'll simply define the images in a text file;
a) First line being the colors
b) All lines except 1st line will be pixels for seperate images.

Example, 4 color images.
Colors=0,0,0 234,234,123 94,38,123, 0,0,45 (R,G,B colors seperated by a whitespace character)
Image1=0032424312003242431200324243120032424312003242431200324243122341 (8x8 image, each decimal value represent a index in the color "table")


Here's how I would do it:
F03F8590CU2Z (I'll be using the ascii value of those to represent numbers from 0-255)
0032424312003242431200324243120032424312003242431200324243122341
1210000012231023041023012302022020230031030401230123012303204012
0032424312003242431200324243120032424312003242431200324243122341
1210000012231023041023012302022020230031030401230123012303204012
0032424312003242431200324243120032424312003242431200324243122341
1210000012231023041023012302022020230031030401230123012303204012
0032424312003242431200324243120032424312003242431200324243122341
1210000012231023041023012302022020230031030401230123012303204012

Those are a few 8x8 4 colors images, if they were GIF they would take up a lot of space. But since that's a text file, it will get compressed A LOT in the JAR file, I've tested this method and it takes 4 32x32 8 color images from 1,5k down to mere 180 bytes, and I'll also save an overhead in the javacode since I only need to read a text file, and not images.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #7 - Posted 2005-12-20 13:57:48 »

I've performed some more tests on this method, and it compresses one image just about 10-20%.
This method pays off when you're storing multiple small low colored images in the same file.

Here are the results of a test:

Test #1
Number of images: 1
GIF image(s) size: 280 bytes
Output file size: 240 bytes

Test #2
Number of images: 2
GIF image(s) size: 790 bytes
Output file size: 340 bytes

Test #3
Number of images: 3
GIF image(s) size: 800 bytes
Output file size: 450 bytes



Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Rick

Junior Member


Projects: 1


Java games rock!


« Reply #8 - Posted 2005-12-21 03:03:40 »

Here is an even simpler way I found to have simple images.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
        int[] colors = new int[256];
        colors['*'] = 0xFFFFFFFF; // white

        byte[] data =  ("   ***   "+
                        " ******* "+
                        " ******* "+
                        "**  *  **"+
                        "**  *  **"+
                        "*********"+
                        "*** * ***"+
                        " ******* "+
                        " * * * * ").getBytes();


        BufferedImage image = g.getDeviceConfiguration().createCompatibleImage(9,9, Transparency.BITMASK);
        // or BufferedImage image = new BufferedImage(9,9); If you want to save space but don't care too much about speed.

        for(int i = 0;i<data.length;i++)
        {
            image['K'].setRGB(i%9,i/9,colors[data[i]]);           
        }


No need to load images or text files. No need to write complicated bit shifting code.
Just draw the image using what ever characters you like. Try to use the same ones for all images so they compress well.
Then set the color of each character. No need to set the transparent character color as if it is not initialized in the color array it will be set as 0 any way.

I wrote a utility to take a gif and produce the text data, but you can also eaisly just manually draw such simple images by hand.

The simplicity of the creation  of the image plus letting the zip utility do all the work of compressing seams to win. At least for my images. Don't forget to change the 9 to match what ever image size you need.

The example image is the skull from my LadyBug game.
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #9 - Posted 2005-12-21 11:00:55 »

I've actually found a new method that compresses the number of bytes used down to 1/3 from what was previously used in my idea, and that's excluding the compression. (I Think!)

Could you send me the image generation tool you used for your ladybug game?

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Rick

Junior Member


Projects: 1


Java games rock!


« Reply #10 - Posted 2005-12-21 15:40:23 »

Here is the code for the image converter to use type java Convert image.gif. The converted file will be in image.gif.txt.
Just cut and past the code into your application. Let me know if you find improvements on the method.


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.util.*;
import java.io.*;

public class Convert
{

    public static void main(String args[])
    {
        try
        {
            String colorMap = "*.@0123456789abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            BufferedImage image;
            int color;
            Hashtable hash = new Hashtable();
            String s;
            image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResource(args[0]));
            int width = image.getWidth();
            int height = image.getHeight();

            PrintWriter out = new PrintWriter(new FileWriter(args[0]+".txt"));

            for(int y = 0;y<height;y++)
            {
                if(y ==0)
                    out.print("data = (\"");
                else
                    out.print("
       \"");
                for(int x = 0;x<width;x++)
                {
                    color = image.getRGB(x,y);
                    s = (String) hash.get(Integer.toHexString(color));
                    if(s == null)
                    {
                        if((color & 0xFF000000) == 0xFF000000)
                            s = ""+colorMap.charAt(hash.size());
                        else // use space for transparent pixels
                           s = " ";
                        hash.put(Integer.toHexString(color),s);
                    }

                    out.print(s);
                }
                if(y == height-1)
                    out.println("\").getBytes();");
                else
                    out.println("
\"+");
               
            }

            out.println("int[] colors = new int[256];");
            Enumeration enumeration = hash.keys();
            while(enumeration.hasMoreElements())
            {
                String key = (String) enumeration.nextElement();
                out.println("colors['"+hash.get(key)+"'] = 0x"+key+";");
            }

            out.println("image = g.getDeviceConfiguration().createCompatibleImage("+width+","+height+", Transparency.BITMASK);");
            out.println("for(int i = 0;i<data.length;i++)");
            out.println("{");
            out.println("image.setRGB(i%"+width+",i/"+width+",colors[data[i]]);");            
            out.println("}");

            out.flush();
            out.close();
        }
        catch(Exception _ex) { }
    }
}
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #11 - Posted 2005-12-21 16:21:43 »

That's not a good algorithm/way for what I'm trying to accomplish, I believe.

It took a 32x32 8 color GIF image of size 348 bytes and blew it up to 1,75kb txt file. And I tried zipping that text  file, and it was around 700 bytes.

I want to take low-color tiny images (16x16, 32x32) and compact them so they'll be a around 20% of the original gif size, once they're packed into the jar file. External or internal (in the java code).


I'm gonna try and implement my idea, and see if it's better.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Rick

Junior Member


Projects: 1


Java games rock!


« Reply #12 - Posted 2005-12-21 17:22:41 »

No. You don't zip the txt file it produces. You inline the code produced in your class file and compile it. Then zip it. You need to compare the size of that to the size of your text file plus the code needed to load the text file. Just trying to load a text file will use lots of bytes. My method does not need to load any file so there is very little code over head. The string that stores the image will get merged once compiled and should compact when ziped nicely.  I created 12 8X5 images in about 50 bytes. The for loop to reconstruct the images will also get compressed with the other for loops in your code. You need to compare this method of loading images imbeded in your whole application with your method to see the real results.
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #13 - Posted 2005-12-21 21:33:46 »

Ok, point taken. I'll still compare both (when i have time) and let you guys know.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Anon666

Junior Member




aka Abuse/AbU5e/TehJumpingJawa


« Reply #14 - Posted 2005-12-22 02:30:22 »

Everything you have done thus far is just duplicating what JBanes' SuperPackMe (and related) stuff does.

It is a simple operation to encode arbitrary binary files into a utf8 string.
However, due to the way the utf8 format works, your data will compress better if you store it in nibble (4bit) chunks.

If you want a more specialized image format to take advantage of known image format specifications; JBanes also has a very good system already outlined.
Ofcourse, only you can decide if the overhead of  the additional code to decode the custom format outweigh the gains from said format.

I seriously suggest you take a look at SuperPackMe.
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #15 - Posted 2005-12-22 07:01:10 »

I did check out superpackme, but I just couldn't figure out how to *use* it. Lacking some examples.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #16 - Posted 2005-12-22 13:46:44 »

Ok, I tried superpackme, and it didn't do anything for me. It reduced the size of my images by only 3%.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #17 - Posted 2005-12-24 00:02:52 »

Well, I made a new compressor that compresses better than SuperPackMe.

Test 1

Input files: 9
Input file sizes (total): 1.668 bytes

SuperPackMe
- Output file: 1.500 bytes
- Size after gzip compression (size in jar): 1.251 bytes

My new method:
- Output file: 2.226 bytes
- Size after gzip compression (size in jar): 1.061 bytes

Difference: 1.251 -1.061 = 190 bytes chopped off the 4K JAR!


Test 2

Input files: 1 (9 sprites in 1 gif image, 16 colors) (I took those 9 images and put them into a 9 * 32x32 grid image.)
Input file size: 1.614 bytes

SuperPackMe
- Output file: 5.811 bytes
- Size after gzip compression (size in jar): 1.737 bytes

My new method:
- Output file: 2.040 bytes
- Size after gzip compression (size in jar): 1.096 bytes

Difference: 1.737-1.096 = 641 bytes chopped off the 4K JAR!


Conclusion

My new method always beats superpackme after the output file has been gzipped. And I believe the retrieval procedure also has a less overhead.
The drawback from my method is that it can only use 16 colors max. But in most cases, especially for 4K games, that is enough.

I don't know why SuperPackMe packed the single image so badly, maybe it's the overhead of having only a single image in one file?


Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

E.R. Fleming (15 views)
2014-07-29 03:07:13

E.R. Fleming (5 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (50 views)
2014-07-17 23:47:54

danieldean (42 views)
2014-07-17 23:41:23

MustardPeter (44 views)
2014-07-16 23:30:00
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!