Know what? The code is now yours, do whatever you want with itā¦
well that rocks
[quote]Know what? The code is now yours, do whatever you want with itā¦
[/quote]
fine - I will.
Index: TargaFile.java
===================================================================
RCS file: /cvs/xith3d/src/com/xith3d/imaging/TargaFile.java,v
retrieving revision 1.1
diff -u -w -r1.1 TargaFile.java
--- TargaFile.java 19 Jul 2003 00:42:42 -0000 1.1
+++ TargaFile.java 9 Dec 2003 11:29:31 -0000
@@ -1,7 +1,9 @@
package com.xith3d.imaging;
-import java.io.*;
-
+import java.awt.image.BufferedImage;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
/**
* Handles dealing with targa image files.
* +--------------------------------------+
@@ -10,7 +12,7 @@
* | Bitmap Data |
* +--------------------------------------+
*/
-public class TargaFile implements ImageFile {
+public class TargaFile implements com.xith3d.imaging.ImageFile {
private byte FHimageIDLength = 0;
private byte FHcolorMapType = 0; // 0 = no pallete
@@ -24,6 +26,8 @@
private short FHheight = 0;
private byte FHbitCount = 0; // 16,24,32
private byte FHimageDescriptor = 0; // 24 bit = 0x00, 32-bit=0x08
+ private int filePointer = 0;
+ private byte fileContents[] = null;
private byte[] data = null;
@@ -50,6 +54,31 @@
return data.length;
}
+ public static BufferedImage getBufferedImage(String filename){
+ TargaFile loader = new TargaFile();
+ loader.load(filename);
+
+ int width = loader.getWidth(),
+ height = loader.getHeight(),
+ bytePerPixel = loader.getBPP()/8;
+
+ BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+ byte[] imageData = loader.getData();
+
+ for(int j = height - 1; j >= 0; j--)
+ for(int i = 0; i < width; i++) {
+ int index = ((height - 1 - j) * width + i) * bytePerPixel;
+ byte alpha = (bytePerPixel == 4) ? imageData[index + 3] : (byte)255;
+ int color = ( alpha & 0xFF) << 24|
+ (imageData[index + 2] & 0xFF) << 16|
+ (imageData[index + 1] & 0xFF) << 8|
+ (imageData[index + 0] & 0xFF);
+ bufferedImage.setRGB(i,j, color);
+ }
+ return bufferedImage;
+ }
+
public void printHeaders() {
System.out.println("-----------------------------------");
System.out.println("File Header");
@@ -82,31 +111,36 @@
FHheight = 0;
FHbitCount = 0;
FHimageDescriptor = 0;
+ filePointer = 0;
+
+ InputStream dis = ClassLoader.getSystemResourceAsStream(filename);
- File file = null;
- RandomAccessFile dis = null;
- try
- {
- file = new File(filename);
- dis = new RandomAccessFile(file,"r");
+ try{
+ if( dis == null)
+ dis = new FileInputStream(filename);
+
+ fileContents = new byte[dis.available()];
+ dis.read(fileContents);
+ try{dis.close();}catch(Exception x){}
// read the file header
- FHimageIDLength = (byte)dis.readUnsignedByte();
- FHcolorMapType = (byte)dis.readUnsignedByte();
- FHimageType = (byte)dis.readUnsignedByte();
- FHcolorMapOrigin = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHcolorMapLength = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHcolorMapDepth = (byte)dis.readUnsignedByte();
- FHimageXOrigin = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHimageYOrigin = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHwidth = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHheight = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHbitCount = (byte)dis.readUnsignedByte();
- FHimageDescriptor = (byte)dis.readUnsignedByte();
-
- if(FHimageType!=2 && FHimageType!=3) // only deal with these two types
- {
- dis.close();
+ FHimageIDLength = (byte)readUnsignedByte();
+ FHcolorMapType = (byte)readUnsignedByte();
+ FHimageType = (byte)readUnsignedByte();
+ FHcolorMapOrigin = readShort();
+ FHcolorMapLength = readShort();
+ FHcolorMapDepth = (byte)readUnsignedByte();
+ FHimageXOrigin = readShort();
+ FHimageYOrigin = readShort();
+ FHwidth = readShort();
+ FHheight = readShort();
+ FHbitCount = (byte)readUnsignedByte();
+ FHimageDescriptor = (byte)readUnsignedByte();
+
+ if(FHimageType!=2 && FHimageType!=3) { // only deal with these two types
+ if(FHimageType == 10)
+ loadCompressed();
+ fileContents = null;
return;
}
@@ -114,30 +148,100 @@
// allocate memory for the pixel data
data = new byte[FHwidth*FHheight*bytesPerPixel];
-
// read the pixel data
- dis.read(data,0,data.length);
+ System.arraycopy(fileContents, filePointer, data, 0, data.length);
- if(FHbitCount==24 || FHbitCount==32)
- {
- // swap the R and B values to get RGB, bitmap color format is BGR
- for(int loop=0;loop<data.length;loop+=bytesPerPixel)
- {
+ if(FHbitCount==24 || FHbitCount==32){
+ // swap the R and B values to get RGB, targa color format is BGR
+ for(int loop=0;loop<data.length;loop+=bytesPerPixel){
byte btemp = data[loop];
data[loop] = data[loop+2];
data[loop+2] = btemp;
}
}
+ fileContents = null;
}
- catch(Exception x)
- {
+ catch(Exception x){
x.printStackTrace();
System.out.println(x.getMessage());
}
- finally
- {
- try{dis.close();}catch(Exception x){}
+
+ }
+
+ public void loadCompressed() {
+ printHeaders();
+ int bytesPerPixel = (FHbitCount/8);
+ data = new byte[FHwidth*FHheight*bytesPerPixel];
+
+ int pixelcount = FHwidth*FHheight,
+ currentbyte = 0,
+ currentpixel = 0;
+
+ byte[] colorbuffer = new byte[bytesPerPixel];
+
+ try{
+ do{
+ int chunkheader = 0;
+ chunkheader = (int)readUnsignedByte();
+ System.out.println(chunkheader);
+ if(chunkheader < 128){
+ chunkheader++;
+ for(short counter = 0; counter < chunkheader; counter++){
+
+ readColorBuffer(colorbuffer);
+ data[currentbyte + 0] = colorbuffer[2];
+ data[currentbyte + 1] = colorbuffer[1];
+ data[currentbyte + 2] = colorbuffer[0];
+
+
+ if(bytesPerPixel == 4)
+ data[currentbyte + 3] = (byte)readUnsignedByte();
+
+ currentbyte += bytesPerPixel;
+ currentpixel++;
+ if(currentpixel > pixelcount)
+ throw new IOException("Too many pixels read");
+ }
+ }
+ else{
+ chunkheader -= 127;
+ readColorBuffer(colorbuffer);
+ for(short counter = 0; counter < chunkheader; counter++){ // by the header
+ data[currentbyte + 0] = colorbuffer[2];
+ data[currentbyte + 1] = colorbuffer[1];
+ data[currentbyte + 2] = colorbuffer[0];
+
+ if(bytesPerPixel == 4)
+ data[currentbyte + 3] = (byte)readUnsignedByte();
+
+ currentbyte += bytesPerPixel;
+ currentpixel++;
+ if(currentpixel > pixelcount)
+ throw new IOException("Too many pixels read");
+ }
+ }
+ } while (currentpixel < pixelcount);
}
+ catch(Exception x){
+ x.printStackTrace();
+ System.out.println(x.getMessage());
+ }
+ }
+
+ private void readColorBuffer(byte[] buffer){
+ buffer[0] = (byte)readUnsignedByte();
+ buffer[1] = (byte)readUnsignedByte();
+ buffer[2] = (byte)readUnsignedByte();
+ }
+
+ private int readUnsignedByte(){
+ return (int) fileContents[filePointer++] & 0xFF;
+ }
+
+ private short readShort(){
+ int s1 = (fileContents[filePointer++] & 0xFF),
+ s2 = (fileContents[filePointer++] & 0xFF) << 8;
+ return ((short)(s1 | s2));
}
public static void main(String[] args) {
Index: WindowsBitmapFile.java
===================================================================
RCS file: /cvs/xith3d/src/com/xith3d/imaging/WindowsBitmapFile.java,v
retrieving revision 1.1
diff -u -w -r1.1 WindowsBitmapFile.java
--- WindowsBitmapFile.java 19 Jul 2003 00:42:42 -0000 1.1
+++ WindowsBitmapFile.java 9 Dec 2003 11:29:32 -0000
@@ -1,6 +1,8 @@
package com.xith3d.imaging;
-import java.io.*;
+import java.awt.image.BufferedImage;
+import java.io.InputStream;
+import java.io.FileInputStream;
/**
* Handles dealing with windows bitmap files. This class doesn't handle palettized files.
@@ -14,9 +16,8 @@
* | Bitmap Data |
* +--------------------------------------+
*/
-public class WindowsBitmapFile implements ImageFile {
+public class WindowsBitmapFile implements com.xith3d.imaging.ImageFile {
- private byte[] FHtype = new byte[2];
private int FHsize = 0;
private short FHreserved1 = 0;
private short FHreserved2 = 0;
@@ -33,6 +34,8 @@
private long IHypelsPerMeter = 0;
private int IHcolorsUsed = 0;
private int IHcolorsImportant = 0;
+ private int filePointer = 0;
+ private byte[] fileContents = null;
private byte[] data = null;
@@ -59,6 +62,29 @@
return data.length;
}
+ public static BufferedImage getBufferedImage(String filename){
+ WindowsBitmapFile loader = new WindowsBitmapFile();
+ loader.load(filename);
+
+ int width = loader.getWidth(),
+
+ height = loader.getHeight();
+
+ BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+ byte[] imageData = loader.getData();
+ for(int j = height - 1; j >= 0; j--)
+ for(int i = 0; i < width; i++) {
+ int index = ((height - 1 - j)* width + i) * 3,
+ color= ( 255 & 0xFF) << 24|
+ (imageData[index + 2] & 0xFF) << 16|
+ (imageData[index + 1] & 0xFF) << 8|
+ (imageData[index + 0] & 0xFF);
+ bufferedImage.setRGB(i,j, color);
+ }
+ return bufferedImage;
+ }
+
public void printHeaders() {
System.out.println("-----------------------------------");
System.out.println("File Header");
@@ -100,50 +126,54 @@
IHypelsPerMeter = 0;
IHcolorsUsed = 0;
IHcolorsImportant = 0;
+ filePointer = 0;
+
+ InputStream dis = ClassLoader.getSystemResourceAsStream(filename);
- File file = null;
- RandomAccessFile dis = null;
try
{
- file = new File(filename);
- dis = new RandomAccessFile(file,"r");
+ if( dis == null)
+ dis = new FileInputStream(filename);
+
+
+ fileContents = new byte[dis.available()];
+ dis.read(fileContents);
+ try{dis.close();}catch(Exception x){}
- dis.read(FHtype,0,2);
+ short magicNumber = readShort();
+ // FHtype
// make sure it's windows bitmap file
- if(FHtype[0]!='B' || FHtype[1]!='M')
+ if(magicNumber != 19778)
{
- dis.close();
+ fileContents = null;
return;
}
// read the file header
- FHsize = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- FHreserved1 = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHreserved2 = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- FHoffsetBits = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
+ FHsize = readInt();
+ FHreserved1 = readShort();
+ FHreserved2 = readShort();
+ FHoffsetBits = readInt();
// read the info header
- IHsize = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHwidth = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHheight = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHplanes = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- IHbitCount = (short)(dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- IHcompression = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHsizeImage = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHxpelsPerMeter = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8);
- IHypelsPerMeter = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHcolorsUsed = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
- IHcolorsImportant = (dis.readUnsignedByte() | dis.readUnsignedByte()<<8 | dis.readUnsignedByte()<<16 | dis.readUnsignedByte()<<24);
+ IHsize = readInt();
+ IHwidth = readInt();
+ IHheight = readInt();
+ IHplanes = readShort();
+ IHbitCount = readShort();
+ IHcompression = readInt();
+ IHsizeImage = readInt();
+ IHxpelsPerMeter = readInt();
+ IHypelsPerMeter = readInt();
+ IHcolorsUsed = readInt();
+ IHcolorsImportant = readInt();
// allocate memory for the pixel data
data = new byte[IHsizeImage];
- // move to the pixel data
- dis.seek(FHoffsetBits);
-
- // read the pixel data
- dis.read(data,0,IHsizeImage);
+ System.arraycopy(fileContents, FHoffsetBits, data, 0, IHsizeImage);
+ fileContents = null;
// swap the R and B values to get RGB, bitmap color format is BGR
for(int loop=0;loop<IHsizeImage;loop+=3)
@@ -158,11 +188,21 @@
x.printStackTrace();
System.out.println(x.getMessage());
}
- finally
- {
- try{dis.close();}catch(Exception x){}
}
+
+ private short readShort(){
+ int s1 = (fileContents[filePointer++] & 0xFF),
+ s2 = (fileContents[filePointer++] & 0xFF) << 8;
+ return ((short)(s1 | s2));
}
+
+ private int readInt(){
+ return (fileContents[filePointer++] & 0xFF) |
+ (fileContents[filePointer++] & 0xFF) << 8|
+ (fileContents[filePointer++] & 0xFF) << 16|
+ (fileContents[filePointer++] & 0xFF) << 24;
+ }
+
public static void main(String[] args) {
WindowsBitmapFile bf = new WindowsBitmapFile();
I canāt test it but as I am only using JPG and PNG files
Iām guessing the code is Davidās so heāll have to commit it (or at least approve the changes and I could commit it from my local copy).
Will.
[quote]Download
PS: To whoever wrote those two classes:
When I was making the changes, I tried reading the files using a DataInputStream, but for some reason when I attempted loading a file from a jar, it threw an exception about mark/reset, function that I used to compensate the lack of rewind().
Anyways I switched to regular InputStream and now everything is ok
[/quote]
The classes were originally written by me, as well as the initial versions of the scene graph classes. I wasnāt getting any farther with my LWJGL implementation so I gave the code to David so he didnāt have to waste time implementing the basics of the graph.
Iām extreemly happy this happened, you all are making one heck of a good library, way better than I could have done.
EDIT: original thread http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=LWJGL;action=display;num=1049466445;start=0
The thread were it went to David http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=News;action=display;num=1056635395;start=32#32
Scott,
Thanks for the background info - we really should add a credit to you in the project and an @author tag in those files for your contribution!
Will.
Funny, when I put a demo together in a jar file and move it around on my pc 4 partitions, it works just fine meaning that it loads the media from within the jar parent.
However when I set up a JNLP file, it fails miserably to load my images through WindowsBitmapFile or TargaFile classes.
When I put the mentioned classes in the same directory than the main class, everything works.
Now that pisses me off to no extent >:(
JWS is a fickle thing. I had many problems getting images to work too, even though I had done that many times previously just with plain jar files.
???
Will.
[quote]Funny, when I put a demo together in a jar file and move it around on my pc 4 partitions, it works just fine meaning that it loads the media from within the jar parent.
However when I set up a JNLP file, it fails miserably to load my images through WindowsBitmapFile or TargaFile classes.
When I put the mentioned classes in the same directory than the main class, everything works.
[/quote]
I experienced the same problem. Thanks to Kevās ClassLoader three-line-tutorial I replaced the following stream loading line of code (of a static class file) :
InputStream ist = Myklass.class.getClass().getResourceAsStream(file_url);
whith the following one:
InputStream ist = Myklass.class.getClassLoader().getResourceAsStream(file_url);
Any everything works fine now. Thereās something with the security manager which the first line didnāt take into account. So while it worked fine on local JARs, it failed with JNLP because of security issues.
( As usual, the file_url is relative. Say, the directory hierarchy of your JAR would look like:
./com/name/your_application/...*.class
./pictures/portrait.png
Then file_url would be equal to āpictures/portrait.pngā for example. )
Tried that, still fails when I attempt loading media through JWS :ā(
:sad:
As you might guess, martian madness uses a fair bit of media⦠what error are you getting exactly? And what code are you using to reference the files?
It could be something in WindowsBitmapFile and TargerFile classes causing the problem. The class loader access to the jar file doesnāt seem to be identical in JWS as to standard ClassLoader.
Kev
[quote]As you might guess, martian madness uses a fair bit of media⦠what error are you getting exactly? And what code are you using to reference the files?
It could be something in WindowsBitmapFile and TargerFile classes causing the problem. The class loader access to the jar file doesnāt seem to be identical in JWS as to standard ClassLoader.
Kev
[/quote]
Umm I think somethings is wrong with my system as I canāt get beyond the settings screen in Martian Madness :
PS: It loads the music just fine though
Coo, do you have the Java Web Start console up?
Kev
Assuming that weāre talking about MM, nope there is no console up: Just plain sound and music.
Not even a window unless I select fullscreen to only be greeted by a blank frame.
PS: None of the tutorial demos that use textures work, for example crude tank only shows white meshesā¦
Iām positive my Xith3D.jar is up to date though
Thereās a configuration option for Web Start that allows you to see the java console as the app is runningā¦
Interesting tho, you see the setup window (which must be loading images?) but you canāt load anything else⦠bizaare!
The option is in File->Preferences, in the Advanced Tab.
Kev
[quote]PS: None of the tutorial demos that use textures work, for example crude tank only shows white meshesā¦
Iām positive my Xith3D.jar is up to date though
[/quote]
prey tell - is xith3d.jar in your jre/lib/ext directory?
Dunno if youāve read this doco recently: http://xith.org/tutes/GettingStarted/html/deploying_xith3d_games_with.html
It now carries the warning: āBe warned that there may be conflicts if you have Xith3D installed (i.e. xith3d.jar) into your java classpath (i.e. jre/lib/ext/ā)
And this doco: http://xith.org/installing.php
Now says:
Donāt ask me why JWS does this caus the only reason I can think of is because itās lame.
I tore out my hair for the best part of an afternoon finding that outā¦
Trust me - the textures in the Xith3D JWS demos (official and GSG) work.
Will.
Score, yay, happy.png
After taking a look at the oggloader, I made few modifications and got everything working not only with Jar files, but also JWS.
Yay again
public static BufferedImage getBufferedImage(Object file){
WindowsBitmapFile loader = new WindowsBitmapFile();
if(file instanceof String)
loader.load((String)file);
else
if(file instanceof URL)
loader.load((URL)file);
else
if(file instanceof InputStream)
loader.load((InputStream)file);
else
return (BufferedImage)null;
int width = loader.getWidth(),
height = loader.getHeight();
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
byte[] imageData = loader.getData();
for(int j = height - 1; j >= 0; j--)
for(int i = 0; i < width; i++) {
int index = ((height - 1 - j)* width + i) * 3,
color= ( 255 & 0xFF) << 24|
(imageData[index + 2] & 0xFF) << 16|
(imageData[index + 1] & 0xFF) << 8|
(imageData[index + 0] & 0xFF);
bufferedImage.setRGB(i,j, color);
}
return bufferedImage;
}
public void load(URL url) {
try {
dis = new java.io.BufferedInputStream(url.openStream());
} catch(Exception ex) {
System.err.println("file " + url + " could not be loaded");
}
load();
}
/**
* Loads the file from an input stream.
*/
public void load(InputStream data) {
try{
dis = new java.io.BufferedInputStream(data);
}catch(Exception e){
}
load();
}
To use it with a jar or jws application
private BufferedImage loadBitmap(String textureName){
try{
return com.xith3d.imaging.WindowsBitmapFile.getBufferedImage(getClass().getClassLoader().getResource(textureName));
}catch(Exception e){
System.out.println(e);
}
return (BufferedImage)null;
}
Ah - so youāre not using the standard com.xith3d.loaders.texture.TextureLoader class?
Itās method to load the image is called āloadImageFastā and can handle loading images from a Jar (and JWS). That method calls DirectBufferedImage.loadImage. If that method could load Targa and Bitmap files as well that would be great.
No point having two different BufferedImage loading methods - any change we can merge them?
Will.
Done tweaking the imaging package:
It now supports wicked fast image writing to the disk in the bmp, TGA32 and TGA 24 formats.
It also is capable of loading the mentioned media from as a JWS application, Jar file, or a local directory.
Quick note on how to use it:
TargaFile.saveTargaFile(view.getSnapshot(canvas), true); For 32 bpp TGA screenshots
TargaFile.saveTargaFile(view.getSnapshot(canvas), false); for 24 bpp TGAscreenshots
WindowsBitmapFile.saveBitmapFile(view.getSnapshot(canvas)); for 24 bpp BMP screenshots.
To load a media, the following linea of code will work regardless of the type of application (be it JWS, JAR or local application):
private Texture loadTexture(String filename){
BufferedImage bufferedImage = null;
try{
bufferedImage = WindowsBitmapFile.getBufferedImage(getClass().getClassLoader().getResource(filename));
if(bufferedImage.getWidth() <= 0)
throw new Exception();
}catch(Exception e){
bufferedImage = WindowsBitmapFile.getBufferedImage(filename);
}
return TextureLoader.tf.loadTexture(bufferedImage, "RGBA" , true ,
Texture.MULTI_LEVEL_LINEAR,
Texture.MULTI_LEVEL_LINEAR,
Texture.CLAMP_TO_EDGE);
}