diff options
Diffstat (limited to 'gl4java/utils/textures')
-rw-r--r-- | gl4java/utils/textures/AWTTextureLoader.java | 169 | ||||
-rw-r--r-- | gl4java/utils/textures/IOTextureLoader.java | 67 | ||||
-rw-r--r-- | gl4java/utils/textures/PPMAsciiTextureLoader.java | 88 | ||||
-rw-r--r-- | gl4java/utils/textures/PngTextureLoader.java | 160 | ||||
-rw-r--r-- | gl4java/utils/textures/TGATextureGrabber.java | 61 | ||||
-rw-r--r-- | gl4java/utils/textures/TGATextureLoader.java | 111 | ||||
-rw-r--r-- | gl4java/utils/textures/TextureGrabber.java | 116 | ||||
-rw-r--r-- | gl4java/utils/textures/TextureLoader.java | 41 | ||||
-rwxr-xr-x | gl4java/utils/textures/TextureTool.java | 610 |
9 files changed, 1423 insertions, 0 deletions
diff --git a/gl4java/utils/textures/AWTTextureLoader.java b/gl4java/utils/textures/AWTTextureLoader.java new file mode 100644 index 0000000..2df3145 --- /dev/null +++ b/gl4java/utils/textures/AWTTextureLoader.java @@ -0,0 +1,169 @@ +package gl4java.utils.textures;
+
+import gl4java.*;
+
+import java.awt.*;
+import java.awt.image.*;
+// import java.awt.Color.*;
+// import java.awt.color.*;
+import java.awt.event.*;
+import java.applet.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This Class implements the universal
+ * texture-loader using the AWT's standard interface !
+ *
+ * The number of image-types depends
+ * on the JDK version you use !
+ *
+ * @see TextureLoader
+ */
+public class AWTTextureLoader
+extends TextureLoader
+{
+ Component comp;
+
+ public AWTTextureLoader(Component comp, GLFunc gl, GLUFunc glu)
+ {
+ super(gl, glu);
+ this.comp=comp;
+ }
+
+ public boolean readTexture(String fname)
+ {
+ Image img = comp.getToolkit().getImage(fname);
+ return readTexture(comp, img);
+ }
+
+ public boolean readTexture(URL base, String uri)
+ {
+ try {
+ URL url = new URL (base, uri);
+ Image img = comp.getToolkit().getImage(url);
+ return readTexture(comp, img);
+ } catch (Exception ex) {
+ System.out.println("AWTTextureLoader.readTexture <"+
+ base+" / "+uri+"> failed !\n"+ex);
+ }
+ return false;
+ }
+
+ private boolean readTexture(Component comp, Image img)
+ {
+ try {
+ try {
+ MediaTracker tracker = new MediaTracker(comp);
+ tracker.addImage(img, 0);
+ tracker.waitForID(0);
+ }
+ catch ( Exception e ) {}
+
+ imageWidth = img.getWidth(comp);
+ imageHeight = img.getHeight(comp);
+ /* This is Java2 only code :-(
+ BufferedImage image =
+ new BufferedImage(imageWidth, imageHeight,
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics g = image.createGraphics();
+ g.drawImage(img,0,0,comp);
+
+ imageWidth = image.getWidth();
+ imageHeight = image.getHeight();
+ */
+
+ // Read entire PNG image (doesn't throw exceptions)
+ int[] iPixels = new int[imageWidth * imageHeight];
+
+ PixelGrabber pp=new PixelGrabber(img,
+ 0,0,
+ imageWidth, imageHeight,
+ iPixels,
+ 0,
+ imageWidth);
+ try
+ {
+ pp.grabPixels();
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println("interrupted waiting for pixel!");
+ error=true;
+ return false;
+ }
+ if ((pp.getStatus() & ImageObserver.ABORT) != 0)
+ {
+ System.err.println("image fetch aborted or errored");
+ error=true;
+ return false;
+ }
+
+ /* This is Java2 only code :-(
+ int imagetype = image.getType();
+ switch(imagetype)
+ {
+ case BufferedImage.TYPE_INT_RGB:
+ glFormat=GL_RGB;
+ break;
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ glFormat=GL_RGBA;
+ break;
+ default:
+ error=true;
+ System.err.println("unsupported format: "+imagetype);
+ return false;
+ };
+ */
+ //
+ // we are guessing the RGB type,
+ // because fetching the true type
+ // is Java2 only code :-(
+ //
+ glFormat=GL_RGB;
+
+ setTextureSize();
+ pixel=new byte[imageWidth * imageHeight * getComponents()];
+
+ int offset=0;
+ int aPixel;
+ int y_desc;
+ for(y_desc=imageHeight-1; y_desc>=0; y_desc--)
+ {
+ for(int x=0;x<imageWidth;x++)
+ {
+ aPixel = iPixels[y_desc*imageWidth + x];
+
+ // red
+ pixel[offset++]=
+ new Integer( (aPixel >> 16) & 0xff ).byteValue();
+
+ // green
+ pixel[offset++]=
+ new Integer( (aPixel >> 8) & 0xff ).byteValue();
+
+ // blue
+ pixel[offset++]=
+ new Integer( (aPixel ) & 0xff ).byteValue();
+
+ // alpha
+ if(glFormat==GL_RGBA)
+ pixel[offset++]=
+ new Integer( (aPixel >> 24) & 0xff ).byteValue();
+ }
+ }
+
+ return true;
+
+ } catch (Exception e) {
+ System.out.println("An exception occured, while loading a AWTTexture");
+ System.out.println(e);
+ error=true;
+ }
+ return false;
+ }
+
+}
+
diff --git a/gl4java/utils/textures/IOTextureLoader.java b/gl4java/utils/textures/IOTextureLoader.java new file mode 100644 index 0000000..4b06b93 --- /dev/null +++ b/gl4java/utils/textures/IOTextureLoader.java @@ -0,0 +1,67 @@ +package gl4java.utils.textures;
+
+import gl4java.*;
+import gl4java.utils.glut.*;
+
+import java.awt.*;
+import java.awt.Color.*;
+import java.awt.event.*;
+import java.applet.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This abstract Class implements the
+ * file and url based methods "readTexture",
+ * to call the specialised implementation
+ * of the stream based "readTexture" method !
+ *
+ * @see TextureLoader
+ */
+public abstract class IOTextureLoader
+extends TextureLoader
+{
+ protected IOTextureLoader(GLFunc gl, GLUFunc glu)
+ { super(gl, glu); }
+
+ public boolean readTexture(String fname)
+ {
+ boolean result = false;
+ InputStream is= null;
+ try {
+ is= new java.io.FileInputStream(fname);
+ result = readTexture(is);
+ } catch (Exception ex) {
+ System.out.println("IOTextureLoader.readTexture <"+
+ fname+"> failed !\n"+ex);
+ }
+ try {
+ if(is!=null) is.close();
+ } catch (Exception ex) {}
+ return result;
+ }
+
+ public boolean readTexture(URL base, String uri)
+ {
+ boolean result = false;
+ InputStream is= null;
+ try {
+ URL url = new URL (base, uri);
+ URLConnection urlcon = url.openConnection();
+ urlcon.setDoOutput(false);
+ urlcon.setDoInput(true);
+ is = urlcon.getInputStream();
+ result = readTexture(is);
+ } catch (Exception ex) {
+ System.out.println("IOTextureLoader.readTexture <"+
+ base+" / "+uri+"> failed !\n"+ex);
+ }
+ try {
+ if(is!=null) is.close();
+ } catch (Exception ex) {}
+ return result;
+ }
+
+ protected abstract boolean readTexture(InputStream is);
+}
+
diff --git a/gl4java/utils/textures/PPMAsciiTextureLoader.java b/gl4java/utils/textures/PPMAsciiTextureLoader.java new file mode 100644 index 0000000..b8d1610 --- /dev/null +++ b/gl4java/utils/textures/PPMAsciiTextureLoader.java @@ -0,0 +1,88 @@ +package gl4java.utils.textures;
+
+import gl4java.*;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.Color.*;
+import java.awt.event.*;
+import java.applet.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This is Class implements the PPM-Ascii
+ * texture-loader !
+ *
+ * @see IOTextureLoader
+ * @see TextureLoader
+ */
+public class PPMAsciiTextureLoader
+extends IOTextureLoader
+{
+ public PPMAsciiTextureLoader(GLFunc gl, GLUFunc glu)
+ {
+ super(gl, glu);
+ }
+
+ protected boolean readTexture(InputStream is)
+ {
+ try {
+ glFormat=GL_RGB;
+
+ DataInputStream reader = new DataInputStream ( is );
+
+ String lin=reader.readLine(); //P6
+ String subLin=lin.substring(0,1);
+
+ lin=reader.readLine();
+ subLin=lin.substring(0,1);
+
+ while (subLin.compareTo("#")==0)
+ {
+ lin=reader.readLine();
+ subLin=lin.substring(0,1);
+ }
+
+ char[] dim=lin.toCharArray();
+
+ int i=0;
+ char car=lin.charAt(i);
+ String blanco=new String(" ");
+ Character C=new Character(car);
+ car=C.charValue();
+ while (C.isDigit(car))
+ {
+ i++;
+ car=lin.charAt(i);
+ C=new Character(car);
+ }
+
+ String alto=lin.substring(0,i);
+ String ancho=lin.substring(i+1,lin.length());
+
+ Integer hh=new Integer(alto);
+ imageWidth=hh.intValue();
+ hh=new Integer(ancho);
+ imageHeight=hh.intValue();
+
+ pixel=new byte[imageWidth * imageHeight * getComponents()];
+
+ lin=reader.readLine(); //255
+
+ reader.read(pixel, 0, pixel.length);
+
+ reader.close();
+ setTextureSize();
+ return true;
+
+ } catch (Exception e) {
+ System.out.println("An exception occured, while loading a PPMAsciiTextureLoader");
+ System.out.println(e);
+ error=true;
+ }
+ return false;
+ }
+
+}
+
diff --git a/gl4java/utils/textures/PngTextureLoader.java b/gl4java/utils/textures/PngTextureLoader.java new file mode 100644 index 0000000..6cc9bb2 --- /dev/null +++ b/gl4java/utils/textures/PngTextureLoader.java @@ -0,0 +1,160 @@ +package gl4java.utils.textures; + +import gl4java.*; + +import java.awt.*; +import java.awt.image.*; +import java.awt.Color.*; +import java.awt.event.*; +import java.applet.*; +import java.io.*; +import java.net.*; + +import com.sixlegs.image.png.*; + +/** + * This is Class implements the PNG texture-loader + * while using the png-library in package + * "com.sixlegs.image.png" ! + * + * @see IOTextureLoader + * @see TextureLoader + */ +public class PngTextureLoader +extends IOTextureLoader +{ + protected boolean grayToAlpha = false; + + public PngTextureLoader(GLFunc gl, GLUFunc glu) + { + super(gl, glu); + } + + /** + * Set to 'true' to load grayscale images as alpha images + * (in other words, GL_ALPHA instead of GL_LUMINANCE) + */ + public void setGrayToAlpha(boolean b) + { + this.grayToAlpha = b; + } + + protected boolean readTexture(InputStream is) + { + try { + int len; + PngImage png = new PngImage(is); + + imageWidth = png.getWidth(); + imageHeight = png.getHeight(); + + // Read entire PNG image (doesn't throw exceptions) + int[] iPixels = new int[imageWidth * imageHeight]; + + PixelGrabber pp=new PixelGrabber(png, + 0,0, + imageWidth, imageHeight, + iPixels, + 0, + imageWidth); + try + { + pp.grabPixels(); + } + catch (InterruptedException e) + { + System.err.println("interrupted waiting for pixel!"); + error=true; + return false; + } + if ((pp.getStatus() & ImageObserver.ABORT) != 0) + { + System.err.println("image fetch aborted or errored"); + error=true; + return false; + } + + // bitDepth beachten + switch(png.getColorType()) + { + case PngImage.COLOR_TYPE_GRAY: + glFormat= grayToAlpha ? GL_ALPHA : GL_LUMINANCE; + break; + case PngImage.COLOR_TYPE_GRAY_ALPHA: + glFormat=GL_LUMINANCE_ALPHA; + break; + case PngImage.COLOR_TYPE_RGB: + glFormat=GL_RGB; + break; + case PngImage.COLOR_TYPE_RGB_ALPHA: + glFormat=GL_RGBA; + break; + case PngImage.COLOR_TYPE_PALETTE: + // todo: support COLOR_TYPE_INDEXED? + glFormat=GL_RGB; + break; + default: + error=true; + System.err.println("unsupported png color type: "+ + png.getColorType()); + return false; + }; + + int ncmpts = getComponents(); + pixel=new byte[imageWidth * imageHeight * ncmpts]; + + byte alpha=0; + byte red=0; + byte green=0; + byte blue=0; + int offset=0; + int aPixel; + for(int y=imageHeight-1; y>=0; y--) + { + for(int x=0;x<imageWidth;x++) + { + aPixel = iPixels[y*imageWidth + x]; + + switch (glFormat) + { + case GL_RGBA: + pixel[offset] = (byte)(aPixel>>16); + pixel[offset+1] = (byte)(aPixel>>8); + pixel[offset+2] = (byte)(aPixel>>0); + pixel[offset+3] = (byte)(aPixel>>24); + offset += 4; + break; + case GL_RGB: + pixel[offset] = (byte)(aPixel>>16); + pixel[offset+1] = (byte)(aPixel>>8); + pixel[offset+2] = (byte)(aPixel>>0); + offset += 3; + break; + case GL_LUMINANCE: + case GL_COLOR_INDEX: + pixel[offset] = (byte)(aPixel); + offset += 1; + break; + case GL_LUMINANCE_ALPHA: // todo: untested + pixel[offset] = (byte)(aPixel); + pixel[offset+1] = (byte)(aPixel>>24); + offset += 2; + break; + } + + } + } + + setTextureSize(); + return true; + + } catch (Exception e) { + System.out.println("An exception occured, while loading a PngTexture"); + System.out.println(e); + error=true; + } + return false; + } + +} + diff --git a/gl4java/utils/textures/TGATextureGrabber.java b/gl4java/utils/textures/TGATextureGrabber.java new file mode 100644 index 0000000..2d1c432 --- /dev/null +++ b/gl4java/utils/textures/TGATextureGrabber.java @@ -0,0 +1,61 @@ +package gl4java.utils.textures; + +import gl4java.*; + +import java.io.*; +import java.net.*; + +public class TGATextureGrabber +extends TextureGrabber +{ + public TGATextureGrabber(GLFunc gl) + { + super(gl); + } + + public boolean write2File(OutputStream os) + { + try { + DataOutputStream fout= new DataOutputStream(os); + + //write TGA header + fout.writeByte(0); //ID length, 0 because no image id field + fout.writeByte(0); //no color map + fout.writeByte(2); //image type (24 bit RGB, uncompressed) + fout.writeShort(0); //color map origin, ignore because no color map + fout.writeShort(0); //color map length, ignore because no color map + fout.writeByte(0); //color map entry size, ignore because no color map + fout.writeShort(0); //x origin + fout.writeShort(0); //y origin + short s = (short)width; + fout.writeByte((byte)(s & 0x00ff)); //image width low byte + fout.writeByte((byte)((s & 0xff00)>>8)); //image width high byte + s = (short)height; + fout.writeByte((byte)(s & 0x00ff)); //image height low byte + fout.writeByte((byte)((s & 0xff00)>>8)); //image height high byte + fout.writeByte(24); //bpp + fout.writeByte(0); //description bits + + //process image data: + // TGA pixels should be written in BGR format, + // so R en B should be switched + byte tmp; + for (int i=0; i<(width*height*3); i+=3) { + tmp=pixels[i]; + pixels[i]=pixels[i+2]; + pixels[i+2]=tmp; + } + + //write TGA image data + fout.write(pixels, 0, pixels.length); + + fout.flush(); + fout.close(); + } catch (Exception ex) { + System.out.println("TGATextureGrabber.write2File <os> failed !\n"+ex); + return false; + } + return true; + } +} + diff --git a/gl4java/utils/textures/TGATextureLoader.java b/gl4java/utils/textures/TGATextureLoader.java new file mode 100644 index 0000000..b0c915f --- /dev/null +++ b/gl4java/utils/textures/TGATextureLoader.java @@ -0,0 +1,111 @@ +package gl4java.utils.textures; + +import gl4java.*; + +import java.io.*; +import java.net.*; + +/** + * This is Class implements a TGA texture-loader ! + * At this time, this loader only supports + * loading files, which are saved with + * the TGATextureGrabber ! + * This means: 24 bpp, RGB, uncompressed, no-colormap, + * no image id-field ! + * + * @see IOTextureLoader + * @see TextureLoader + */ +public class TGATextureLoader +extends IOTextureLoader +{ + public TGATextureLoader(GLFunc gl, GLUFunc glu) + { + super(gl, glu); + } + + protected boolean readTexture(InputStream is) + { + try { + int cc; + + glFormat=GL_RGB; + + DataInputStream reader = new DataInputStream ( is ); + + //write TGA header + reader.readByte(); //ID length, 0 because no image id field + reader.readByte(); //no color map + cc = reader.readByte(); //image type (24 bit RGB, uncompressed) + if(cc!=2) + { + reader.close(); + System.out.println("TGATextureLoader: File is not 24bit RGB Data !"); + error=true; + return false; + } + reader.readShort(); //color map origin, ignore because no color map + reader.readShort(); //color map length, ignore because no color map + reader.readByte(); //color map entry size, ignore because no color map + reader.readShort(); //x origin + reader.readShort(); //y origin + + cc = reader.readByte(); // image width low byte + short s = (short)((short)cc & 0x00ff); + cc = reader.readByte(); // image width high byte + s = (short) ( (short)( ((short)cc & 0x00ff)<<8 ) | s ); + imageWidth = (int)s; + + cc = reader.readByte(); // image height low byte + s = (short)((short)cc & 0x00ff); + cc = reader.readByte(); // image height high byte + s = (short) ( (short)( ((short)cc & 0x00ff)<<8 ) | s ); + imageHeight = (int)s; + + cc=reader.readByte(); // 24bpp + if(cc!=24) + { + reader.close(); + System.out.println("TGATextureLoader: File is not 24bpp Data !"); + error=true; + return false; + } + reader.readByte(); //description bits + + if(3!=getComponents()) + { + reader.close(); + System.out.println("TGATextureLoader: Currenly only RGB (24bit) data is supported !"); + error=true; + return false; + } + + pixel=new byte[imageWidth * imageHeight * 3]; + + //read TGA image data + reader.read(pixel, 0, pixel.length); + + //process image data: + // TGA pixels should be written in BGR format, + // so R en B should be switched + byte tmp; + for (int i=0; i<imageWidth*imageHeight*3; i+=3) + { + tmp=pixel[i]; + pixel[i]=pixel[i+2]; + pixel[i+2]=tmp; + } + + reader.close(); + setTextureSize(); + return true; + + } catch (Exception ex) { + System.out.println("An exception occured, while loading a TGATexture"); + System.out.println(ex); + error=true; + } + return false; + } +} + diff --git a/gl4java/utils/textures/TextureGrabber.java b/gl4java/utils/textures/TextureGrabber.java new file mode 100644 index 0000000..d7d3bff --- /dev/null +++ b/gl4java/utils/textures/TextureGrabber.java @@ -0,0 +1,116 @@ +package gl4java.utils.textures; + +import gl4java.*; + +import java.io.*; +import java.net.*; + +/** + * This abstract Class defines the interface + * for ALL texture Grabbers ! + * The TextureGrabber's implementations are used to + * save the pixels of the GL Context to a file ! + * + * @see TextureTool + * @see GLImageCanvas + */ +public abstract class TextureGrabber +implements GLEnum, GLUEnum +{ + protected byte[] pixels=null; + protected int xpos; + protected int ypos; + protected int width; + protected int height; + protected GLFunc gl; + + public TextureGrabber(GLFunc gl) + { + this.gl=gl; + } + + /** + * Grab the pixels outta the OpenGL Frambuffer + * + * @param source the frambuffer source (like glReadBuffer), + * can be: GL_FRONT, GL_BACK, .... + * @param x the xpos + * @param y the ypos + * @param w the width + * @param h the height + * + * @see GLFunc#glReadBuffer + */ + public void grabPixels(int source, int x, int y, int w, int h) + { + int swapbytes[]={0}, lsbfirst[]={0}, rowlength[]={0}; + int skiprows[]={0}, skippixels[]={0}, alignment[]={0}; + + xpos=x; + ypos=y; + width=w; + height=h; + pixels=new byte[w * h * 3]; + + /* Save current modes. */ + gl.glGetIntegerv(GL_PACK_SWAP_BYTES, swapbytes); + gl.glGetIntegerv(GL_PACK_LSB_FIRST, lsbfirst); + gl.glGetIntegerv(GL_PACK_ROW_LENGTH, rowlength); + gl.glGetIntegerv(GL_PACK_SKIP_ROWS, skiprows); + gl.glGetIntegerv(GL_PACK_SKIP_PIXELS, skippixels); + gl.glGetIntegerv(GL_PACK_ALIGNMENT, alignment); + + /* Little endian machines (DEC Alpha, Intel 80x86, ... for example) could + benefit from setting GL_PACK_LSB_FIRST to GL_TRUE + instead of GL_FALSE, but this would require changing the + generated bitmaps too. */ + gl.glPixelStorei(GL_PACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_PACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, w); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_PACK_ALIGNMENT, 1); + + //get viewport data + gl.glReadBuffer(source); + gl.glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels); + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL_PACK_ALIGNMENT, alignment[0]); + + } + + public boolean write2File(String fname) + { + try { + OutputStream os= new java.io.FileOutputStream(fname); + return write2File(os); + } catch (Exception ex) { + System.out.println("TGATextureGrabber.write2File <"+ + fname+"> failed !\n"+ex); + } + return false; + } + + public boolean write2File(URL base, String uri) + { + try { + URL url = new URL (base, uri); + URLConnection urlcon = url.openConnection(); + urlcon.setDoOutput(true); + OutputStream os = urlcon.getOutputStream(); + return write2File(os); + } catch (Exception ex) { + System.out.println("TGATextureGrabber.write2File <"+ + base+" / "+uri+"> failed !\n"+ex); + } + return false; + } + + public abstract boolean write2File(OutputStream os); +} + diff --git a/gl4java/utils/textures/TextureLoader.java b/gl4java/utils/textures/TextureLoader.java new file mode 100644 index 0000000..36a8cfe --- /dev/null +++ b/gl4java/utils/textures/TextureLoader.java @@ -0,0 +1,41 @@ +package gl4java.utils.textures;
+
+import gl4java.*;
+import gl4java.utils.glut.*;
+
+import java.awt.*;
+import java.awt.Color.*;
+import java.awt.event.*;
+import java.applet.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This abstract Class defines the interface
+ * for ALL texture loaders !
+ *
+ * @see TextureTool
+ * @see GLImageCanvas
+ */
+public abstract class TextureLoader
+extends TextureTool
+{
+ protected TextureLoader(GLFunc gl, GLUFunc glu)
+ { super(gl, glu); }
+
+ /**
+ * Loads an Texture
+ *
+ * @param fname The filename
+ */
+ public abstract boolean readTexture(String fname);
+
+ /**
+ * Loads an Texture
+ *
+ * @param base The base URL
+ * @param uri The additional uri for the base URL
+ */
+ public abstract boolean readTexture(URL base, String uri);
+}
+
diff --git a/gl4java/utils/textures/TextureTool.java b/gl4java/utils/textures/TextureTool.java new file mode 100755 index 0000000..a842d1f --- /dev/null +++ b/gl4java/utils/textures/TextureTool.java @@ -0,0 +1,610 @@ +package gl4java.utils.textures; + +import gl4java.*; + +import java.awt.*; +import java.awt.Color.*; +import java.awt.event.*; +import java.applet.*; +import java.io.*; +import java.net.*; + +/** + * This Class implements basic functions, + * which are used by all TextureLoader implementations ! + * + * @see TextureLoader + */ +public abstract class TextureTool +implements GLEnum, GLUEnum +{ + protected GLFunc gl; + protected GLUFunc glu; + + /** + * just a default type ... + */ + protected byte[] pixel; + protected boolean pixelScaled; + + protected int imageWidth; + protected int imageHeight; + protected int textWidth; + protected int textHeight; + + protected int glFormat; + protected boolean error; + + public String toString() + { + return "Texture "+textWidth+"x"+textHeight+ + "[image "+imageWidth+"x"+imageHeight+ + "[bpc "+getComponents()+"]"+ + "]"; + } + + protected TextureTool(GLFunc gl, GLUFunc glu) + { + this.gl=gl; + this.glu=glu; + error=false; + pixelScaled = false; + } + + public final boolean isOk() { return !error; } + + public final int getGLFormat() { return glFormat; } + public int getGLBytesPerComponent() { return 1; } + public int getGLComponentFormat() { return GL_UNSIGNED_BYTE; } + + /** + * just a default for byte sized component's + */ + public int getComponents() + { + switch (glFormat) + { + case GL_RGBA: + return 4; + case GL_RGB: + return 3; + case GL_LUMINANCE_ALPHA: + return 2; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_COLOR_INDEX: + return 1; + default: + return 0; + } + } + + /** + * Dimension + */ + public final int getImageWidth() { return imageWidth; } + public final int getImageHeight() { return imageHeight; } + + public final int getTextureWidth() { return textWidth; } + public final int getTextureHeight() { return textHeight; } + + + public static final int getMaxTextureSize(GLFunc gl) + { + int[] maxSize=new int[1]; + gl.glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize); + return maxSize[0]; + } + + /** + * This method is called directly after loading + * the texture ! + * You normally do not need to call this method ! + * + * The textWidth/textHeight data is set correctly + * to a power of 2 ! + */ + public void setTextureSize() + { + int e_x, e_y, i; + + /* achieve the 2**e_x>=imageWidth, 2**e_y>=imageHeight */ + e_x=0; textWidth=1; + + while (textWidth<imageWidth) + { textWidth*=2; e_x++; } + + e_y=0; textHeight=1; + while (textHeight<imageHeight) + { textHeight*=2; e_y++; } + + int[] format = new int[1]; + + do { + gl.glTexImage2D(GL_PROXY_TEXTURE_2D, 0, + getComponents(), + textWidth, textHeight, + 0, + glFormat, + GL_UNSIGNED_BYTE, + (byte[])null); + glutReportErrors(); + + gl.glGetTexLevelParameteriv + (GL_PROXY_TEXTURE_2D, 0, + GL_TEXTURE_INTERNAL_FORMAT, format); + glutReportErrors(); + + + // + // if(format[0]!=glFormat) + // + if(format[0]==0) + { + System.out.println("text size too big: "+this.toString()+", "+format[0]+"!="+glFormat); + if(textWidth>textHeight) + { + e_x--; textWidth=1; + for(i=e_x; i>0; i--) + textWidth*=2; + } else { + e_y--; textHeight=1; + for(i=e_y; i>0; i--) + textHeight*=2; + } + } + } while (format[0]==0 && /* format[0]!=glFormat && */ + textWidth>1 && textHeight>1); + + } + + /** + * The image data, with the given + * Dimension and Format ! + */ + public final byte[] getTexture() { return pixel; } + + /** + * This method can be called, + * if you want to have a normal image-data size + * with the power of two ! + * + * The Ascpect-Ratio is dropped ! + * + * You can call this method directly after loading a + * texture ! + * + * The pixel store mode GL_UNPACK_ALIGNMENT & GL_PACK_ALIGNMENT, + * is set temporary to byte alignment, then back to default (4) ! + * + * The pixel store mode GL_UNPACK_ROW_LENGTH & GL_PACK_ROW_LENGTH, + * is set temporary to imageWidth, then back to default (0) ! + * + * @see GLUFunc#gluScaleImage + * @see GLFunc#glPixelStorei + */ + public boolean scaleTexture2Pow2() + { + if(pixelScaled) + return true; + + int swapbytes[]={0}, lsbfirst[]={0}, rowlength[]={0}; + int skiprows[]={0}, skippixels[]={0}, alignment[]={0}; + int unswapbytes[]={0}, unlsbfirst[]={0}, unrowlength[]={0}; + int unskiprows[]={0}, unskippixels[]={0}, unalignment[]={0}; + + setTextureSize(); + + if (textWidth != imageWidth || + textHeight != imageHeight) + { + int colorBytes; + + // speicher fuer scaliertes bild anlegen + byte[] buffer=new byte[textWidth * textHeight * + getComponents()]; + + /* Save current modes. */ + gl.glGetIntegerv(GL_PACK_SWAP_BYTES, swapbytes); + gl.glGetIntegerv(GL_PACK_LSB_FIRST, lsbfirst); + gl.glGetIntegerv(GL_PACK_ROW_LENGTH, rowlength); + gl.glGetIntegerv(GL_PACK_SKIP_ROWS, skiprows); + gl.glGetIntegerv(GL_PACK_SKIP_PIXELS, skippixels); + gl.glGetIntegerv(GL_PACK_ALIGNMENT, alignment); + gl.glGetIntegerv(GL_UNPACK_SWAP_BYTES, unswapbytes); + gl.glGetIntegerv(GL_UNPACK_LSB_FIRST, unlsbfirst); + gl.glGetIntegerv(GL_UNPACK_ROW_LENGTH, unrowlength); + gl.glGetIntegerv(GL_UNPACK_SKIP_ROWS, unskiprows); + gl.glGetIntegerv(GL_UNPACK_SKIP_PIXELS, unskippixels); + gl.glGetIntegerv(GL_UNPACK_ALIGNMENT, unalignment); + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_PACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, imageWidth); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if( glu.gluScaleImage(glFormat, + imageWidth, imageHeight, + GL_UNSIGNED_BYTE, + pixel, + textWidth, textHeight, + GL_UNSIGNED_BYTE, + buffer)!=0 ) + { + // glu failure + error=true; + } else { + pixel = buffer; + } + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL_PACK_ALIGNMENT, alignment[0]); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, unswapbytes[0]); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, unlsbfirst[0]); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, unrowlength[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, unskiprows[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, unskippixels[0]); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, unalignment[0]); + } + if(!error) + pixelScaled = true; + return pixelScaled; + } + + /** + * This method can be called, + * if you want to have an optimal image-data size + * which fits best into the texture-MEMORY ! + * + * The Ascpect-Ratio is not changed + * - seen from the texture-MEMORY-ratio + * to the netto-image-MEMORY-ratio ! + * + * If you want to render this result with the correct + * apsect-ration, + * you MUST set the vertices in relation to + * the textureWidth and textureHeight ! + * Look in the demo: "demos/MiscDemos/GLImageWorld1" ! + * + * You can call this method directly after loading a + * texture ! + * + * The pixel store mode GL_UNPACK_ALIGNMENT & GL_PACK_ALIGNMENT, + * is set temporary to byte alignment, then back to default (4) ! + * + * The pixel store mode GL_UNPACK_ROW_LENGTH & GL_PACK_ROW_LENGTH, + * is set temporary to imageWidth, then back to default (0) ! + * + * @see GLUFunc#gluScaleImage + * @see GLFunc#glPixelStorei + */ + public boolean scaleTexture4BestSize() + { + if(pixelScaled) + return true; + + setTextureSize(); + + if (textWidth != imageWidth || + textHeight != imageHeight) + { + int swapbytes[]={0}, lsbfirst[]={0}, rowlength[]={0}; + int skiprows[]={0}, skippixels[]={0}, alignment[]={0}; + int unswapbytes[]={0}, unlsbfirst[]={0}, unrowlength[]={0}; + int unskiprows[]={0}, unskippixels[]={0}, unalignment[]={0}; + int colorBytes; + + // speicher fuer scaliertes bild anlegen + byte[] buffer=new byte[textWidth * textHeight * + getComponents()]; + + int w=textWidth; + int h=textHeight; + + double iaspect = (double)imageWidth/ + (double)imageHeight; + + if(textWidth<textHeight) + h = (int) ((textWidth / iaspect)+0.5); + else + w = (int) ((textHeight * iaspect)+0.5); + + /* + System.out.println("scale4Best: size "+ + imageWidth+"/"+imageHeight+" -> "+w+"/"+h); + System.out.println("scale4Best: aspect (w/h) "+ + iaspect+" -> "+(double)w/(double)h); + */ + + /* Save current modes. */ + gl.glGetIntegerv(GL_PACK_SWAP_BYTES, swapbytes); + gl.glGetIntegerv(GL_PACK_LSB_FIRST, lsbfirst); + gl.glGetIntegerv(GL_PACK_ROW_LENGTH, rowlength); + gl.glGetIntegerv(GL_PACK_SKIP_ROWS, skiprows); + gl.glGetIntegerv(GL_PACK_SKIP_PIXELS, skippixels); + gl.glGetIntegerv(GL_PACK_ALIGNMENT, alignment); + gl.glGetIntegerv(GL_UNPACK_SWAP_BYTES, unswapbytes); + gl.glGetIntegerv(GL_UNPACK_LSB_FIRST, unlsbfirst); + gl.glGetIntegerv(GL_UNPACK_ROW_LENGTH, unrowlength); + gl.glGetIntegerv(GL_UNPACK_SKIP_ROWS, unskiprows); + gl.glGetIntegerv(GL_UNPACK_SKIP_PIXELS, unskippixels); + gl.glGetIntegerv(GL_UNPACK_ALIGNMENT, unalignment); + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_PACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, textWidth); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, imageWidth); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if( glu.gluScaleImage(glFormat, + imageWidth, imageHeight, + GL_UNSIGNED_BYTE, + pixel, + w, h, + GL_UNSIGNED_BYTE, + buffer)!=0 ) + { + // glu failure + error=true; + } else { + pixel = buffer; + imageWidth=w; + imageHeight=h; + } + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL_PACK_ALIGNMENT, alignment[0]); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, unswapbytes[0]); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, unlsbfirst[0]); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, unrowlength[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, unskiprows[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, unskippixels[0]); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, unalignment[0]); + } + if(!error) + pixelScaled = true; + return pixelScaled; + } + + /** + * This method loads the image into + * the current bind GL_TEXTURE_2D texture ! + * + * Be sure to have the GL-Context being current ! + * + * Be sure to have the GL_TEXTURE_2D bind to + * a textureName ! + * + * This method calls scaleTexture2Pow2() to + * make the image of the normal texture size := pow2 ! + * Then glTexImage2D is called with the texture properties ! + * + * The Ascpect-Ratio is dropped ! + * + * @see TextureTool#scaleTexture2Pow2 + * @see GLFunc#glGenTextures + * @see GLFunc#glBindTexture + * @see GLFunc#glTexImage2D + * @see GLFunc#glPixelStorei + */ + public boolean texImage2DScaled2Pow2() + { + // The Scaled Way + if(!scaleTexture2Pow2()) + return false; + + gl.glTexImage2D(GL_TEXTURE_2D, + 0, + getComponents(), + getTextureWidth(), + getTextureHeight(), + 0, + getGLFormat(), + getGLComponentFormat(), + getTexture()); // The Scaled Way + + return glutReportErrors(); + } + + /** + * This method loads the image into + * the current bind GL_TEXTURE_2D texture ! + * + * Be sure to have the GL-Context being current ! + * + * Be sure to have the GL_TEXTURE_2D bind to + * a textureName ! + * + * This method calls scaleTexture4BestSize() to + * make the image of the best fitting size + * relative to the texture-size! + * Then glTexImage2D is called with the texture properties ! + * + * The Ascpect-Ratio is not changed ! + * + * A fine example exists in "demos/MiscDemos/GLImageViewerWorld" ! + * + * @see TextureTool#scaleTexture4BestSize + * @see GLFunc#glGenTextures + * @see GLFunc#glBindTexture + * @see GLFunc#glTexImage2D + * @see GLFunc#glPixelStorei + */ + public boolean texImage2DScaled4BestSize() + { + // The Scaled Way + if(!scaleTexture4BestSize()) + return false; + + gl.glTexImage2D(GL_TEXTURE_2D, + 0, + getComponents(), + getTextureWidth(), + getTextureHeight(), + 0, + getGLFormat(), + getGLComponentFormat(), + getTexture()); // The Scaled Way + + return glutReportErrors(); + } + + /** + * This method loads the image into + * the current bind GL_TEXTURE_2D texture ! + * + * Be sure to have the GL-Context being current ! + * + * Be sure to have the GL_TEXTURE_2D bind to + * a textureName ! + * + * This method creates a target texture (glTexImage2D) + * without data, + * and substitutes only the unscaled image data (glTexSubImage2D) ! + * + * The benefits of this functions is, + * that the image/texture is not scaled ! + * A fine example exists in "demos/MiscDemos/GLImageViewerCanvas" ! + * + * The pixel store mode GL_UNPACK_ALIGNMENT, + * is set temporary to byte alignment, then back to default (4) ! + * + * The pixel store mode GL_UNPACK_ROW_LENGTH, + * is set temporary to imageWidth, then back to default (0) ! + * + * @param clear if true, the texture will be initially loaded with + * a dummy blank (black) array + * + * @see GLFunc#glGenTextures + * @see GLFunc#glBindTexture + * @see GLFunc#glTexImage2D + * @see GLFunc#glTexSubImage2D + * @see GLFunc#glPixelStorei + * @see GLImageCanvas + */ + public boolean texImage2DNonScaled(boolean clear) + { + int swapbytes[]={0}, lsbfirst[]={0}, rowlength[]={0}; + int skiprows[]={0}, skippixels[]={0}, alignment[]={0}; + int unswapbytes[]={0}, unlsbfirst[]={0}, unrowlength[]={0}; + int unskiprows[]={0}, unskippixels[]={0}, unalignment[]={0}; + + /* Save current modes. */ + gl.glGetIntegerv(GL_PACK_SWAP_BYTES, swapbytes); + gl.glGetIntegerv(GL_PACK_LSB_FIRST, lsbfirst); + gl.glGetIntegerv(GL_PACK_ROW_LENGTH, rowlength); + gl.glGetIntegerv(GL_PACK_SKIP_ROWS, skiprows); + gl.glGetIntegerv(GL_PACK_SKIP_PIXELS, skippixels); + gl.glGetIntegerv(GL_PACK_ALIGNMENT, alignment); + gl.glGetIntegerv(GL_UNPACK_SWAP_BYTES, unswapbytes); + gl.glGetIntegerv(GL_UNPACK_LSB_FIRST, unlsbfirst); + gl.glGetIntegerv(GL_UNPACK_ROW_LENGTH, unrowlength); + gl.glGetIntegerv(GL_UNPACK_SKIP_ROWS, unskiprows); + gl.glGetIntegerv(GL_UNPACK_SKIP_PIXELS, unskippixels); + gl.glGetIntegerv(GL_UNPACK_ALIGNMENT, unalignment); + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_PACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, 1); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, imageWidth); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + byte[] clrPixel = null; + + if(clear) + { + clrPixel= + new byte[textWidth * textHeight * getComponents()]; + } + + gl.glTexImage2D(GL_TEXTURE_2D, + 0, + getComponents(), + getTextureWidth(), + getTextureHeight(), + 0, + getGLFormat(), + getGLComponentFormat(), + clrPixel); + + // The unscaled way + /* + System.out.println("******* width "+getImageWidth()); + System.out.println("******* height "+getImageHeight()); + System.out.println("******* format "+getGLFormat()); + System.out.println("******* comps "+getGLComponentFormat()); + System.out.println("******* text "+getTexture()); + System.out.println("******* text.length "+getTexture().length); + */ + + gl.glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, 0, + getImageWidth(), + getImageHeight(), + getGLFormat(), + getGLComponentFormat(), + getTexture()); + + // System.out.println("+++++++++"); + + gl.glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL_PACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL_PACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL_PACK_ALIGNMENT, alignment[0]); + gl.glPixelStorei(GL_UNPACK_SWAP_BYTES, unswapbytes[0]); + gl.glPixelStorei(GL_UNPACK_LSB_FIRST, unlsbfirst[0]); + gl.glPixelStorei(GL_UNPACK_ROW_LENGTH, unrowlength[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_ROWS, unskiprows[0]); + gl.glPixelStorei(GL_UNPACK_SKIP_PIXELS, unskippixels[0]); + gl.glPixelStorei(GL_UNPACK_ALIGNMENT, unalignment[0]); + return glutReportErrors(); + } + + protected final boolean glutReportErrors() + { + int error; + + while ((error = gl.glGetError()) != GL_NO_ERROR) + __glutWarning("GL error: "+glu.gluErrorString(error)); + return error==GL_NO_ERROR; + } + + protected static final void __glutWarning(String str) + { + System.out.println("GLUT: Warning in (unamed): "+str+"\n"); + } +} + |