---- Reported by alang 2007-04-12 04:00:50 ---- Attached is an example application showing that gluScaleImage does not always scale correctly. Run the application with and without the following JVM command line argument: -Djogl.glu.nojava When the application is ran *with* this command line argument the texture is displayed correctly. When the application is ran without the texture is not scaled correctly. -------------------------------------------- Attached application: JOGLTexture.java import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.nio.*; import java.util.*; import javax.imageio.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; /** * Example JOGL application showing bug when using gluScaleImage. The application * simply displays a quad with a texture map. Load any non square image, the * sample included is 134x57. Run the application with and without the following * JVM command line argument: * * -Djogl.glu.nojava * * When the application is ran *with* this command line argument the texture is * displayed correctly. When the application is ran without the texture is not * scaled correctly. * * Run environment: * Machine : Dell Precision M70 laptop * OS : Windows XP SP2 * Graphics : NVIDIA Quadro FX Go1400 * Drivers : lastest from DELL dated: 22/03/2006 ver. 8.4.3.0 * JVM : j2sdk1.4.2_10 * JOGL : release 1.1.0-rc3 from Feb 14 2007 * * @author Alan Michael Gay, AVS Inc. */ public class JOGLTexture extends Frame implements GLEventListener, ImageConsumer { // Name of example mage file to load String nonSquareImageFileName = ".\\non-squareimage.jpg"; // // OpenGL variables. // private GLU glu = new GLU(); private int textureName; // // Workspace variables for consuming image. // boolean imageComplete = false; private int imageWidth = 0; private int imageHeight = 0; private byte[] imageBuffer = null; public JOGLTexture() { // Loads the image we are going to use in this example. loadImage(nonSquareImageFileName); // Specify the Frame window title and initial size. setTitle("gluScaleImage bug"); // Create a listener object that will cause the application // to exit when the user dismisses the Frame window. this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); // Use the default capabilities. GLCapabilities capabilities = new GLCapabilities(); GLCanvas canvas = new GLCanvas(capabilities); canvas.addGLEventListener(this); this.add(canvas); } /** * Loads the specified image from file. * @param fileName The string filename for the image. */ private void loadImage(String fileName) { File input = new File(fileName); Image image = null; try { image = ImageIO.read(input); } catch (Throwable e) { System.out.println("Failed to load image file: " + e.getMessage()); } ImageProducer imageSource = image.getSource(); imageSource.startProduction(this); } /** * Gets a new width and height based on a power of 2. * @param width The original image width * @param height The original image height * @return An in array with two values. The zeroth element containing the new width and the first * element the new height. */ private int[] newImageSize(int width, int height) { int nN=1; while((width >> nN)>0) { nN++; } width = (width == (1<<(nN-1))) ? width : (1<<nN); nN = 1; while((height >> nN)>0) { nN++; } height = (height == (1<<(nN-1))) ? height : (1<<nN); int[] newDims = new int[2]; newDims[0] = width; newDims[1] = height; return newDims; } /** * Gets a new texture name * @param gl The gl context to get the name from. * @return An int value containing the texture name. */ private int getTextureName(GL gl) { int[] result = new int[1]; gl.glGenTextures(1, result, 0); return result[0]; } /** * Loads an image into opengl to be used as a texture. * @param gl The gl context into which to load the texture * @param width The width of the image. * @param height The height of the image. * @param texture The image. */ private int loadTexture(GL gl , int width, int height, byte []texture) { int nComp = 4; int nAlign = 4; int textureName = getTextureName(gl); int[] newDims = newImageSize(width, height); int[] nOldAlign = new int[1]; gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, nOldAlign,0); gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, nAlign); gl.glBindTexture(GL.GL_TEXTURE_2D, textureName); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE); gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); int nSize = nComp*(int) newDims[0] * newDims[1]; byte[] newTexture = new byte [nSize]; ByteBuffer bufferIn = ByteBuffer.wrap(texture); ByteBuffer bufferOut = ByteBuffer.wrap(newTexture); glu.gluScaleImage(GL.GL_RGBA, width, height, GL.GL_UNSIGNED_BYTE, bufferIn, newDims[0], newDims[1], GL.GL_UNSIGNED_BYTE, bufferOut); gl.glBindTexture(GL.GL_TEXTURE_2D, textureName); ByteBuffer pixelBuffer = ByteBuffer.wrap(newTexture); gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, nComp, newDims[0], newDims[1], 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer); gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, nOldAlign[0]); return textureName; } /** * Implementation of GLEventListener.display * Draws a simple textured quad. */ public void display(GLAutoDrawable arg0) { GL gl = arg0.getGL(); Color col = Color.white; float red = col.getRed()/255.0f; float green = col.getGreen()/255.0f; float blue = col.getBlue()/255.0f; gl.glColor3f(red, green, blue); gl.glEnable(GL.GL_TEXTURE_2D); gl.glBindTexture(GL.GL_TEXTURE_2D, textureName); gl.glBegin(GL.GL_QUADS); gl.glTexCoord2f(0.0f,1.0f); gl.glVertex3f(-1.0f, 1.0f, 0.0f); gl.glTexCoord2f(1.0f,1.0f); gl.glVertex3f(1.0f, 1.0f, 0.0f); gl.glTexCoord2f(1.0f,0.0f); gl.glVertex3f(1.0f, -1.0f, 0.0f); gl.glTexCoord2f(0.0f,0.0f); gl.glVertex3f(-1.0f, -1.0f, 0.0f); gl.glEnd(); } public void init(GLAutoDrawable arg0) { GL gl = arg0.getGL(); if (imageComplete == false) throw new RuntimeException("Image has not been loaded"); // Load the texture to be used when displaying the textured quad. textureName = loadTexture(gl, imageWidth, imageHeight, imageBuffer); } public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3, int arg4) { } public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) { } // // Implementation of ImageConsumer // public synchronized final void imageComplete(int status) { imageComplete = true; } public synchronized final void setDimensions(int width, int height) { imageWidth = width; imageHeight = height; imageBuffer = new byte[4*width*height]; } public synchronized final void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) { if (w == 0 || h == 0) return; int srcRowIndex = off; int dstRowIndex = ((imageHeight - 1) - y) * imageWidth + x; for (int row = 0; row < h; row++) { int srcIndex = srcRowIndex; int dstIndex = dstRowIndex; for (int col = 0; col < w; col++) { int pixel = pixels[srcIndex++]; int color = model.getRGB(pixel); imageBuffer[dstIndex*4 + 0] = (byte) (color & 0x000000ff); imageBuffer[dstIndex*4 + 1] = (byte)((color & 0x0000ff00) >> 8); imageBuffer[dstIndex*4 + 2] = (byte)((color & 0x00ff0000) >> 16); imageBuffer[dstIndex*4 + 3] = (byte) 0xff; dstIndex++; } srcRowIndex += scansize; dstRowIndex += imageWidth; } } public synchronized final void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) { // ignore this version } public synchronized final void setHints(int hintflags) {} public synchronized final void setColorModel(ColorModel model) {} public synchronized final void setProperties(Hashtable props) {} /** * The main() method is called when the Java Virtual Machine starts up. It * just creates and displays an instance of the application. */ public static void main(String args[]) { JOGLTexture app = new JOGLTexture(); app.pack(); app.setSize(300, 300); app.setVisible(true); } } ---- Additional Comments From alang 2007-04-12 04:03:13 ---- Created an attachment Example application showing issue ---- Additional Comments From alang 2007-04-12 04:03:59 ---- Created an attachment Example non sqaure image used by example application ---- Additional Comments From alang 2007-04-17 13:16:21 ---- none ---- Additional Comments From kbr 2007-04-18 00:33:03 ---- This is being investigated. It isn't necessary to adjust the priority. If you would like to help figure out what is going on, you can compare the Java sources for Mipmap.java, Image.java and ScaleImage.java to the relevant C GLU sources in the OpenGL sample implementation and see if you can find the bug. This is what we are doing internally. ---- Additional Comments From kbr 2007-04-18 00:33:27 ---- _ ---- Additional Comments From kbr 2007-04-18 23:36:09 ---- Conversion scale factors for x and y dimensions were flipped. Also adjusted Image.fill_image() so code does not assert. Fix will be present in JOGL nightly builds dated 4/19 and later, and in the forthcoming 1.1.0-rc4 and 1.1.0 final release. ---- Additional Comments From alang 2007-04-19 08:31:31 ---- Can confirm fix resolves issue for me. Thanks for such a prompt response. Regards Alan --- Bug imported by sgothel@jausoft.com 2010-03-24 07:50 EDT --- This bug was previously known as _bug_ 292 at https://jogl.dev.java.net/bugs/show_bug.cgi?id=292 Imported an attachment (id=98) Imported an attachment (id=99) The original submitter of attachment 98 [details] is unknown. Reassigning to the person who moved it here: sgothel@jausoft.com. The original submitter of attachment 99 [details] is unknown. Reassigning to the person who moved it here: sgothel@jausoft.com.