Java-Gaming.org    
Featured games (78)
games approved by the League of Dukes
Games in Showcase (429)
Games in Android Showcase (89)
games submitted by our members
Games in WIP (468)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2]
  ignore  |  Print  
  Questions about TGA Files  (Read 7521 times)
0 Members and 1 Guest are viewing this topic.
Offline kevglass

JGO Kernel


Medals: 85
Projects: 22


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #30 - Posted 2006-12-02 05:00:58 »

Both of the public versions only support non-RLE, 24bit/32bit images. Thing can go astray if you pump anything else in. They also both create only POT sized buffers. So if you're passing in something like 1024x826, you'll get a buffer for 1024x1024.

Kev

Offline Eliwood

Junior Member




Stencyl


« Reply #31 - Posted 2006-12-02 05:23:44 »

I'll hold my breath on this, but I think my problem was that these weren't 24 or 32-bit TGA's to begin with. :/

I used ImageMagick, and apparently, it took my PNG's (which I think were 8-bit) and converted them over to 8-bit TGA's. That's my guess because your function's valiantly trying to load what it claims are 8-bit TGA's. Tongue

Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #32 - Posted 2006-12-02 06:48:44 »

1  
2  
3  
4  
5  
6  
7  
D:\>convert -colorspace RGB -depth 32 -background transparent -verbose eli.gif eli3.png
eli.gif GIF 50x50 50x50+0+0 PseudoClass 32c 8-bit 822b
eli.gif=>eli3.png GIF 50x50 50x50+0+0 PseudoClass 32c 16-bit 1.8457kb 0.030u 0:01

D:\>convert -verbose eli3.png eli3.tga
eli3.png PNG 50x50 50x50+0+0 DirectClass 8-bit 1.8457kb 0.010u 0:01
eli3.png=>eli3.tga PNG 50x50 50x50+0+0 DirectClass 8-bit 9.7832kb 0.020u 0:01


That worked for example (gives you a 32bit tga). But its quite crap like this. (Well, its not that bad... after compression its only about 25% bigger than it needs to be.)

TGA supports different 8bit modes. 15bit (5-5-5), 16bit (5-5-5-1), 24bit (8-8-8) and 32bit (8-8-8-8) afaict. However, I don't have a clue how to create anything else than those with a 24bit palette.

Well, I guess a semi logical step would be to create a java program, which can be used to convert 8bit gif/tga files to tga with 32bit palette. And adding some stuff to the loader to handle 24 and 32bit palettes (the other modes aren't any useful imo).

Or... create some custom format, which is easier to read/write.

Or... use dds and add the code for handling palletized stuff (in which case it would be cool if you share it).

弾幕 ☆ @mahonnaiseblog
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Eliwood

Junior Member




Stencyl


« Reply #33 - Posted 2006-12-02 07:18:45 »

Well, I got 24-bit TGA's loaded into Images, only after deciding to read all the documents (which are a bit poorly worded). It was just a matter of doing this:

1) Creating a Data Buffer and partitioning it correctly
2) Choosing the right Sample Model and understanding what parameters to plug in
3) Creating a writable raster and passing in the databuffer and sample model
4) Making a color model
5) Constructing a buffered image from raster and color model.

And this is the code that worked. I have yet to really be convinced that this is actually faster (in plain loading in, PNG wins by quite a bit still, which is not too great for the editor), but I'll see in-game. I suppose that for some of you, this is second nature, but I had absolutely no knowledge going into this, and there weren't any code samples online (that I could find). So not too bad for a few hours of work. Wink

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  
                DataBufferByte dataBuffer = new DataBufferByte
      (
         rawData,
         rawData.length
      );
     
      int[] offsets = {0,1,2};
     
      PixelInterleavedSampleModel sampleModel = new PixelInterleavedSampleModel
      (
         DataBuffer.TYPE_BYTE,
         texWidth,
         texHeight,
         3,
         3 * texWidth,
         offsets
      );
     
      WritableRaster raster = Raster.createWritableRaster
      (
         sampleModel,
         dataBuffer,
         new Point(0,0)
      );
     
      ColorModel cm = new ComponentColorModel
      (
         ColorSpace.getInstance
         (ColorSpace.CS_sRGB),
                        new int[] {8,8,8},
                        false,
                        false,
                        ComponentColorModel.OPAQUE,
                        DataBuffer.TYPE_BYTE
              );
     
      BufferedImage img = new BufferedImage(cm, raster, false, null);


First, just for my own knowledge. What does the flipping mean? When I passed in "false" it created an upside down image AND one that had inverted colors like the following. Does it just mean that it turned the picture upside down and reversed all the color channels (RGB -> BGR)?



Offline Evil-Devil

Senior Member


Medals: 2


Fir Tree Master


« Reply #34 - Posted 2006-12-02 13:08:46 »

TGA images stores their color values in BGRA order and were flipped normally. The easiest would be to import them and save the RGBA an reflipped version as your own tga image. That would make it impossible for reading it with alternative software, but you don't have to go through the B<>R flipping and image flipping.
Offline Eliwood

Junior Member




Stencyl


« Reply #35 - Posted 2006-12-02 18:48:30 »

Hmm. While I haven't rewritten the routine for loading these into textures, just speaking for the editor part, it's loading in significantly slower than the PNG version, presumably because the files are now megabytes big. (Well, to be precise, they are stored in a JAR file but then streamed out which decompresses them).

While I didn't do some formal timing experiments, just plain reading them in was notably slower. When I read in all the PNG's, it read each one instantly where as each TGA had a tiny pause (0.3 seconds perhaps?).

I'll post up the full source of what I'm doing because I think there might be room for improvement. It should be noted that I did modify Kev's function to not load into POT.

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  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
/**
    * Load a TGA image from the specified stream
    *
    * @param fis The stream from which we'll load the TGA
    * @param flipped True if we loading in flipped mode (used for cursors)
    * @return The Image
    * @throws IOException Indicates a failure to read the TGA
    */

   public static BufferedImage loadIntoImage(InputStream fis, boolean flipped) throws IOException {
      byte red = 0;
      byte green = 0;
      byte blue = 0;
      byte alpha = 0;
     
      BufferedInputStream bis = new BufferedInputStream(fis, 100000);
      DataInputStream dis = new DataInputStream(bis);
     
      // Read in the Header
     short idLength = (short) dis.read();
      short colorMapType = (short) dis.read();
      short imageType = (short) dis.read();
      short cMapStart = flipEndian(dis.readShort());
      short cMapLength = flipEndian(dis.readShort());
      short cMapDepth = (short) dis.read();
      short xOffset = flipEndian(dis.readShort());
      short yOffset = flipEndian(dis.readShort());
     
      width = flipEndian(dis.readShort());
      height = flipEndian(dis.readShort());
      pixelDepth = (short) dis.read();
     
      //We don't want to load into OpenGL
     //texWidth = get2Fold(width);
     //texHeight = get2Fold(height);
     
      texWidth = width;
      texHeight = height;
     
      short imageDescriptor = (short) dis.read();
      // Skip image ID
     if (idLength > 0) {
         bis.skip(idLength);
      }
     
      byte[] rawData = null;
      if (pixelDepth == 32)
         rawData = new byte[texWidth * texHeight * 4];
      else
         rawData = new byte[texWidth * texHeight * 3];
     
      if (pixelDepth == 24) {
         for (int i = height-1; i >= 0; i--) {
            for (int j = 0; j < width; j++) {
               blue = dis.readByte();
               green = dis.readByte();
               red = dis.readByte();
               
               int ofs = ((j + (i * texWidth)) * 3);
               rawData[ofs] = (byte) red;
               rawData[ofs + 1] = (byte) green;
               rawData[ofs + 2] = (byte) blue;
            }
         }
      } else if (pixelDepth == 32) {
         if (flipped) {
            for (int i = height-1; i >= 0; i--) {
               for (int j = 0; j < width; j++) {
                  blue = dis.readByte();
                  green = dis.readByte();
                  red = dis.readByte();
                  alpha = dis.readByte();
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs + 2] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }
               }
            }
         } else {
            for (int i = 0; i < height; i++) {
               for (int j = 0; j < width; j++) {
                  blue = dis.readByte();
                  green = dis.readByte();
                  red = dis.readByte();
                  alpha = dis.readByte();
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs + 2] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }
               }
            }
         }
      }
      fis.close();
     
      //End Kev's Code
     
      DataBufferByte dataBuffer = new DataBufferByte
      (
         rawData,
         rawData.length
      );
     
      int[] offsets = null;
     
      if(pixelDepth == 24)
      {
         int[] offsets24 = {0,1,2};
         offsets = offsets24;
      }
     
      else
      {
         int[] offsets32 = {0,1,2,3};
         offsets = offsets32;
      }
     
      PixelInterleavedSampleModel sampleModel = null;
     
      if(pixelDepth == 24)
      {
         sampleModel = new PixelInterleavedSampleModel
         (
            DataBuffer.TYPE_BYTE,
            texWidth,
            texHeight,
            3,
            3 * texWidth,
            offsets
         );
      }
     
      else
      {
         sampleModel = new PixelInterleavedSampleModel
         (
            DataBuffer.TYPE_BYTE,
            texWidth,
            texHeight,
            4,
            4 * texWidth,
            offsets
         );
      }
     
      WritableRaster raster = Raster.createWritableRaster
      (
         sampleModel,
         dataBuffer,
         new Point(0,0)
      );
     
      ColorModel cm = null;
     
      if(pixelDepth == 24)
      {
         cm = new ComponentColorModel
         (
            ColorSpace.getInstance
            (ColorSpace.CS_sRGB),
            new int[] {8,8,8},
            ffalse,
            false,
            ComponentColorModel.OPAQUE,
            DataBuffer.TYPE_BYTE
           );
      }
     
      else
      {
         cm = new ComponentColorModel
         (
            ColorSpace.getInstance(ColorSpace.CS_sRGB),
            new int[] {8,8,8,8},
            true,
            false,
            ComponentColorModel.TRANSLUCENT,
            DataBuffer.TYPE_BYTE
         );
      }
     
      BufferedImage img = new BufferedImage(cm, raster, false, null);

      return img;
   }


Edit: I also tried GZipping, and I saw no real improvement.


Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #36 - Posted 2006-12-03 00:35:23 »

If you want quick loading, you shouldn't be compressing it in the first place.

Compressing TGA with ZIP or GZ, is basicly the same as using PNG, because PNG uses similair algorithms.

You should do a comparison loading plain PNG / TGA files, not in a Zip or JAR.

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

Junior Member




Stencyl


« Reply #37 - Posted 2006-12-03 01:09:59 »

If you want quick loading, you shouldn't be compressing it in the first place.

Compressing TGA with ZIP or GZ, is basicly the same as using PNG, because PNG uses similair algorithms.

You should do a comparison loading plain PNG / TGA files, not in a Zip or JAR.

That's what I did already and it's exactly the same loading time. I just threw in the compression comment to say that that's something *additional* I tried as a second experiment.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #38 - Posted 2006-12-03 02:36:01 »

dis.readByte()
might have a significant overhead, even if there is a BufferedInputStream backing it.

Try to read the whole file in a single byte[] and use that in your loops.

My gut-feeling tells me it will make it 4-8x faster... tell me how it works out

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

Junior Member




Stencyl


« Reply #39 - Posted 2006-12-03 07:30:45 »

dis.readByte()
might have a significant overhead, even if there is a BufferedInputStream backing it.

Try to read the whole file in a single byte[] and use that in your loops.

My gut-feeling tells me it will make it 4-8x faster... tell me how it works out

I'll see if that helps any. It sounds plausible that it will be faster, but I'm not so sure about 4-8x faster. Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Eliwood

Junior Member




Stencyl


« Reply #40 - Posted 2006-12-03 08:55:51 »

Ok, it's MUCH better now but not the 4-8x you promised. Wink

Whereas before, it would take about 4-5 seconds to load it all in, it's more around 1.5 seconds to load in 16 24-bit or 32-bit TGA files all of the 1024x864 variant with file sizes of 2593 KB. That all said, PNG's still loaded in marginally faster at about 1 I'd estimate. I'll post up the code in case I goofed up somewhere, but I did about what you said. I actually tried a variant where it read the whole file in, and it came out slower than the solution I'm posting where I read in the header as normal, then bulk read the image data and then use arrays from there.

All in all, it's at least within the same order of magnitude now and more than acceptable for me, especially since the game won't ever load this many images of this size at once, usually 1 per level and occasionally several if they are animated or if there's a background and foreground image.

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  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
public static BufferedImage loadIntoImage(InputStream fis, boolean flipped) throws IOException {
      byte red = 0;
      byte green = 0;
      byte blue = 0;
      byte alpha = 0;
     
      BufferedInputStream bis = new BufferedInputStream(fis, 100000);
      DataInputStream dis = new DataInputStream(bis);
     
      // Read in the Header
     short idLength = (short) dis.read();
      short colorMapType = (short) dis.read();
      short imageType = (short) dis.read();
      short cMapStart = flipEndian(dis.readShort());
      short cMapLength = flipEndian(dis.readShort());
      short cMapDepth = (short) dis.read();
      short xOffset = flipEndian(dis.readShort());
      short yOffset = flipEndian(dis.readShort());
     
      width = flipEndian(dis.readShort());
      height = flipEndian(dis.readShort());
      pixelDepth = (short) dis.read();
     
      texWidth = width;
      texHeight = height;
     
      short imageDescriptor = (short) dis.read();
     
      // Skip image ID
     if(idLength > 0)
      {
         bis.skip(idLength);
      }
     
      //Now we stop the normal process, read in bulk and then process.
     byte[] allData = null;
      byte[] rawData = null;
     
      if (pixelDepth == 32)
      {
         allData = new byte[texWidth * texHeight * 4];
         rawData = new byte[texWidth * texHeight * 4];
      }
      else
      {
         allData = new byte[texWidth * texHeight * 3];
         rawData = new byte[texWidth * texHeight * 3];
      }
     
      dis.read(allData);
     
      int pos = 0;
     
      if (pixelDepth == 24) {
         for (int i = height-1; i >= 0; i--) {
            for (int j = 0; j < width; j++) {
               blue = allData[pos];
               pos++;
               green = allData[pos];
               pos++;
               red = allData[pos];
               pos++;
               
               int ofs = ((j + (i * texWidth)) * 3);
               rawData[ofs] = (byte) red;
               rawData[ofs + 1] = (byte) green;
               rawData[ofs + 2] = (byte) blue;
            }
         }
      } else if (pixelDepth == 32) {
         if (flipped) {
            for (int i = height-1; i >= 0; i--) {
               for (int j = 0; j < width; j++) {
                  blue = allData[pos];
                  pos++;
                  green = allData[pos];
                  pos++;
                  red = allData[pos];
                  pos++;
                  alpha = allData[pos];
                  pos++;
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs + 2] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }
               }
            }
         } else {
            for (int i = 0; i < height; i++) {
               for (int j = 0; j < width; j++) {
                  blue = allData[pos];
                  pos++;
                  green = allData[pos];
                  pos++;
                  red = allData[pos];
                  pos++;
                  alpha = allData[pos];
                  pos++;
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs + 2] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }
               }
            }
         }
      }
      fis.close();
     
      //End Kev's Code
     
      DataBufferByte dataBuffer = new DataBufferByte
      (
         rawData,
         rawData.length
      );
     
      int[] offsets = null;
     
      if(pixelDepth == 24)
      {
         int[] offsets24 = {0,1,2};
         offsets = offsets24;
      }
     
      else
      {
         int[] offsets32 = {0,1,2,3};
         offsets = offsets32;
      }
     
      PixelInterleavedSampleModel sampleModel = null;
     
      if(pixelDepth == 24)
      {
         sampleModel = new PixelInterleavedSampleModel
         (
            DataBuffer.TYPE_BYTE,
            texWidth,
            texHeight,
            3,
            3 * texWidth,
            offsets
         );
      }
     
      else
      {
         sampleModel = new PixelInterleavedSampleModel
         (
            DataBuffer.TYPE_BYTE,
            texWidth,
            texHeight,
            4,
            4 * texWidth,
            offsets
         );
      }
     
      WritableRaster raster = Raster.createWritableRaster
      (
         sampleModel,
         dataBuffer,
         new Point(0,0)
      );
     
      ColorModel cm = null;
     
      if(pixelDepth == 24)
      {
         cm = new ComponentColorModel
         (
            ColorSpace.getInstance
            (ColorSpace.CS_sRGB),
               new int[] {8,8,8},
               false,
               false,
               ComponentColorModel.OPAQUE,
               DataBuffer.TYPE_BYTE
           );
      }
     
      else
      {
         cm = new ComponentColorModel
         (
            ColorSpace.getInstance(ColorSpace.CS_sRGB),
                new int[] {8,8,8,8},
                true,
                false,
                ComponentColorModel.TRANSLUCENT,
                DataBuffer.TYPE_BYTE
            );
      }
     
      BufferedImage img = new BufferedImage(cm, raster, false, null);

      return img;
   }



Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #41 - Posted 2006-12-03 12:55:49 »

This code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
                  blue = allData[pos];
                  pos++;
                  green = allData[pos];
                  pos++;
                  red = allData[pos];
                  pos++;
                  alpha = allData[pos];
                  pos++;
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs + 2] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }


Is not very fast. First of all, why do you have that (alpha==0), it won't chnage anything, and when you were to mipmap your image, you'd get ugly dark edges in your scaled images. So I'd suggest you take that out.

For the real deal, why not change it in:

1  
2  
3  
4  
5  
6  
7  
8  
                  int ofs = ((j + (i * texWidth))  << 2);
                 
                  rawData[ofs       ] = allData[pos + 2];
                  rawData[ofs + 1] = allData[pos + 1];
                  rawData[ofs + 2] = allData[pos       ];
                  rawData[ofs + 3] = allData[pos + 3];

                  pos += 4;

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

JGO Kernel


Medals: 85
Projects: 22


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #42 - Posted 2006-12-03 14:52:42 »

The alpha == 0 check is bespoke for icon loading where only the rgb value is used but where black is used as transparent on some systems for bitmask only transparency. - a hack to apply some form of alpha in these cass as well.

The getByte() replacement sounds useful (I'll add soon) but PNG is still faster to just load data wise. As i mentioned at the top of the thread (I think) the percieved gain with TGA for most peope is the lack of data -> buffered image -> gl texture process when you've written a custom loader that can give you the data in the right fomat straight away.i.e. data -> texture.

The bottle neck with usng ImageIO is the conversion from buffered image to texture, not the data loading?

Kev

Offline Eliwood

Junior Member




Stencyl


« Reply #43 - Posted 2006-12-03 18:27:06 »

The alpha == 0 check is bespoke for icon loading where only the rgb value is used but where black is used as transparent on some systems for bitmask only transparency. - a hack to apply some form of alpha in these cass as well.

The getByte() replacement sounds useful (I'll add soon) but PNG is still faster to just load data wise. As i mentioned at the top of the thread (I think) the percieved gain with TGA for most peope is the lack of data -> buffered image -> gl texture process when you've written a custom loader that can give you the data in the right fomat straight away.i.e. data -> texture.

The bottle neck with usng ImageIO is the conversion from buffered image to texture, not the data loading?

Kev

Which is why... after all of this, I think I'll go with storing the image both as a PNG and a TGA. PNG for the editor and non-game related tasks and TGA for the game itself. Since I already stick everything in a JAR, the TGA's took up practically no space anyways (<< less than the space the PNG's took in the JAR).

Offline Eliwood

Junior Member




Stencyl


« Reply #44 - Posted 2006-12-03 18:53:48 »

This code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
                  blue = allData[pos];
                  pos++;
                  green = allData[pos];
                  pos++;
                  red = allData[pos];
                  pos++;
                  alpha = allData[pos];
                  pos++;
                 
                  int ofs = ((j + (i * texWidth)) * 4);
                 
                  rawData[ofs] = (byte) red;
                  rawData[ofs + 1] = (byte) green;
                  rawData[ofs + 2] = (byte) blue;
                  rawData[ofs + 3] = (byte) alpha;
                 
                  if (alpha == 0) {
                     rawData[ofs + 2] = (byte) 0;
                     rawData[ofs + 1] = (byte) 0;
                     rawData[ofs] = (byte) 0;
                  }


Is not very fast. First of all, why do you have that (alpha==0), it won't chnage anything, and when you were to mipmap your image, you'd get ugly dark edges in your scaled images. So I'd suggest you take that out.

For the real deal, why not change it in:

1  
2  
3  
4  
5  
6  
7  
8  
                  int ofs = ((j + (i * texWidth))  << 2);
                 
                  rawData[ofs       ] = allData[pos + 2];
                  rawData[ofs + 1] = allData[pos + 1];
                  rawData[ofs + 2] = allData[pos       ];
                  rawData[ofs + 3] = allData[pos + 3];

                  pos += 4;


I don't notice much of a performance gain from this. It might be 0.1 seconds faster. Kinda hard to tell unless I try some formal benchmarking or operate on a larger dataset.

Offline Eliwood

Junior Member




Stencyl


« Reply #45 - Posted 2006-12-05 07:28:31 »

Simply put, it works wonders. My loading times are down to practically nothing now. Thanks guys!

Offline Kova

Senior Member





« Reply #46 - Posted 2006-12-05 12:48:48 »

wait a second, what works? Can you write a small conclusion?
I was quickly going through this thread, not fully reading everything and I noticed you guys talk about TGA as fastest for loading. Now in test PNG is better. I guess I could read everything (and I will) but still you could write a conclusion in few sentences, I like that Smiley
Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #47 - Posted 2006-12-05 13:02:51 »

>Now in test PNG is better.

Java2D. The TGAs are 32bit and the PNGs are 8bit (indexed).

In lwjgl there is no awt fiddling... therefore its a lot faster there.

>TGA as fastest for loading

DXTn is the fastest. Its directly loaded (unless a software decoding fallback for ancient cards is used), its 1/4th or 1/6th of the size (compared to raw stuff like tga) and its also quite compressible on top (zip/lzma/whatever).

edit: But DXTn isn't suitable for all kinds of images. There has to be some catch, right? Wink

弾幕 ☆ @mahonnaiseblog
Offline Eliwood

Junior Member




Stencyl


« Reply #48 - Posted 2006-12-05 18:09:59 »

>Now in test PNG is better.

Java2D. The TGAs are 32bit and the PNGs are 8bit (indexed).

In lwjgl there is no awt fiddling... therefore its a lot faster there.

>TGA as fastest for loading

DXTn is the fastest. Its directly loaded (unless a software decoding fallback for ancient cards is used), its 1/4th or 1/6th of the size (compared to raw stuff like tga) and its also quite compressible on top (zip/lzma/whatever).

edit: But DXTn isn't suitable for all kinds of images. There has to be some catch, right? Wink

DXTn's that lossy compression format, isn't it? I'm done with this image loading stuff for the moment, but I might look into that down the line if I'm greedy about performance. Smiley

Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #49 - Posted 2006-12-06 07:14:47 »

Yes, its lossy (therefore its not suitable for all kinds of images). But generally it works very well, I would say.

弾幕 ☆ @mahonnaiseblog
Pages: 1 [2]
  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.

theagentd (6 views)
2014-04-24 23:00:44

xsi3rr4x (83 views)
2014-04-15 18:08:23

BurntPizza (75 views)
2014-04-15 03:46:01

UprightPath (86 views)
2014-04-14 17:39:50

UprightPath (69 views)
2014-04-14 17:35:47

Porlus (86 views)
2014-04-14 15:48:38

tom_mai78101 (109 views)
2014-04-10 04:04:31

BurntPizza (169 views)
2014-04-08 23:06:04

tom_mai78101 (265 views)
2014-04-05 13:34:39

trollwarrior1 (217 views)
2014-04-04 12:06:45
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
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!