diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util/texture')
20 files changed, 1304 insertions, 683 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java index a94b1f827..584cacf8c 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -1,21 +1,22 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. @@ -44,24 +45,39 @@ import javax.media.nativewindow.NativeWindowFactory; import jogamp.opengl.*; +import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.texture.spi.*; /** * Represents an OpenGL texture object. Contains convenience routines * for enabling/disabling OpenGL texture state, binding this texture, * and computing texture coordinates for both the entire image as well - * as a sub-image. - * + * as a sub-image. + * + * <a name="textureCallOrder"><h5>Order of Texture Commands</h5></a> + * <p> + * Due to many confusions w/ texture usage, following list described the order + * and semantics of texture unit selection, binding and enabling. + * <ul> + * <li><i>Optional:</i> Set active textureUnit via <code>gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit)</code>, <code>0</code> is default.</li> + * <li>Bind <code>textureId</code> -> active <code>textureUnit</code>'s <code>textureTarget</code> via <code>gl.glBindTexture(textureTarget, textureId)</code></li> + * <li><i>Compatible Context Only:</i> Enable active <code>textureUnit</code>'s <code>textureTarget</code> via <code>glEnable(textureTarget)</code>. + * <li><i>Optional:</i> Fiddle with the texture parameters and/or environment settings.</li> + * <li>GLSL: Use <code>textureUnit</code> in your shader program, enable shader program.</li> + * <li>Issue draw commands</li> + * </ul> + * </p> + * * <p><a name="nonpow2"><b>Non-power-of-two restrictions</b></a> * <br> When creating an OpenGL texture object, the Texture class will - * attempt to leverage the <a - * href="http://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt">GL_ARB_texture_non_power_of_two</a> - * and <a - * href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a> - * extensions (in that order) whenever possible. If neither extension - * is available, the Texture class will simply upload a non-pow2-sized + * attempt to use <i>non-power-of-two textures</i> (NPOT) if available, see {@link GL#isNPOTTextureAvailable()}. + * Further more, + * <a href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a> + * (RECT) will be attempted on OSX w/ ATI drivers. + * If NPOT is not available or RECT not chosen, the Texture class will simply upload a non-pow2-sized * image into a standard pow2-sized texture (without any special - * scaling). Since the choice of extension (or whether one is used at + * scaling). + * Since the choice of extension (or whether one is used at * all) depends on the user's machine configuration, developers are * recommended to use {@link #getImageTexCoords} and {@link * #getSubImageTexCoords}, as those methods will calculate the @@ -89,16 +105,24 @@ import com.jogamp.opengl.util.texture.spi.*; * when switching between textures it is necessary to call {@link * #bind}, but when drawing many triangles all using the same texture, * for best performance only one call to {@link #bind} should be made. + * User may also utilize multiple texture units, + * see <a href="#textureCallOrder"> order of texture commands above</a>. * * <p><a name="premult"><b>Alpha premultiplication and blending</b></a> - * <br> The mathematically correct way to perform blending in OpenGL - * (with the SrcOver "source over destination" mode, or any other - * Porter-Duff rule) is to use "premultiplied color components", which - * means the R/G/ B color components have already been multiplied by - * the alpha value. To make things easier for developers, the Texture - * class will automatically convert non-premultiplied image data into - * premultiplied data when storing it into an OpenGL texture. As a - * result, it is important to use the correct blending function; for + * <p> + * <i>Disclaimer: Consider performing alpha premultiplication in shader code, if really desired! Otherwise use RGBA.</i><br/> + * </p> + * <p> + * The Texture class does not convert RGBA image data into + * premultiplied data when storing it into an OpenGL texture. + * </p> + * <p> + * The mathematically correct way to perform blending in OpenGL + * with the SrcOver "source over destination" mode, or any other + * Porter-Duff rule, is to use <i>premultiplied color components</i>, + * which means the R/G/ B color components must have been multiplied by + * the alpha value. If using <i>premultiplied color components</i> + * it is important to use the correct blending function; for * example, the SrcOver rule is expressed as: <pre> gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); @@ -113,7 +137,7 @@ import com.jogamp.opengl.util.texture.spi.*; float g = g * a; float b = b * a; gl.glColor4f(r, g, b, a); -</pre> +</pre> * * For reference, here is a list of the Porter-Duff compositing rules * and the associated OpenGL blend functions (source and destination @@ -136,9 +160,7 @@ import com.jogamp.opengl.util.texture.spi.*; <TR> <TD> AlphaXor <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA </TABLE> </CENTER> - * - * @author Chris Campbell - * @author Kenneth Russell + * @author Chris Campbell, Kenneth Russell, et.al. */ public class Texture { /** The GL target type. */ @@ -166,6 +188,13 @@ public class Texture { /** The texture coordinates corresponding to the entire image. */ private TextureCoords coords; + @Override + public String toString() { + return "Texture[target 0x"+Integer.toHexString(target)+", name "+texID+", "+ + imgWidth+"/"+texWidth+" x "+imgHeight+"/"+texHeight+", y-flip "+mustFlipVertically+ + ", "+estimatedMemorySize+" bytes]"; + } + /** An estimate of the amount of texture memory this texture consumes. */ private int estimatedMemorySize; @@ -205,12 +234,13 @@ public class Texture { * Enables this texture's target (e.g., GL_TEXTURE_2D) in the * given GL context's state. This method is a shorthand equivalent * of the following OpenGL code: - <pre> - gl.glEnable(texture.getTarget()); - </pre> - * + * <pre> + * gl.glEnable(texture.getTarget()); + * </pre> * <p> - * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}. + * Call is ignored if the {@link GL} object's context + * is using a core profile, see {@link GL#isGLcore()}, + * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}. * </p> * <p> * See the <a href="#perftips">performance tips</a> above for hints @@ -222,21 +252,22 @@ public class Texture { * OpenGL-related errors occurred */ public void enable(GL gl) throws GLException { - if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) { + if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target) { gl.glEnable(target); } } - + /** * Disables this texture's target (e.g., GL_TEXTURE_2D) in the * given GL state. This method is a shorthand equivalent * of the following OpenGL code: - <pre> - gl.glDisable(texture.getTarget()); - </pre> - * + * <pre> + * gl.glDisable(texture.getTarget()); + * </pre> * <p> - * Call is ignored if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}. + * Call is ignored if the {@link GL} object's context + * is using a core profile, see {@link GL#isGLcore()}, + * or if {@link #getTarget()} is {@link GLES2#GL_TEXTURE_EXTERNAL_OES}. * </p> * <p> * See the <a href="#perftips">performance tips</a> above for hints @@ -248,11 +279,11 @@ public class Texture { * OpenGL-related errors occurred */ public void disable(GL gl) throws GLException { - if(GLES2.GL_TEXTURE_EXTERNAL_OES != target) { + if( !gl.isGLcore() && GLES2.GL_TEXTURE_EXTERNAL_OES != target ) { gl.glDisable(target); } } - + /** * Binds this texture to the given GL context. This method is a * shorthand equivalent of the following OpenGL code: @@ -262,22 +293,16 @@ public class Texture { * * See the <a href="#perftips">performance tips</a> above for hints * on how to maximize performance when using many Texture objects. - * @param gl TODO * + * @param gl the current GL context * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ public void bind(GL gl) throws GLException { validateTexID(gl, true); - gl.glBindTexture(target, texID); - } - - /** - * @deprecated use {@link #destroy(GL)} - */ - public final void dispose(GL gl) throws GLException { - destroy(gl); + gl.glBindTexture(target, texID); } + /** * Destroys the native resources used by this texture object. * @@ -311,7 +336,7 @@ public class Texture { public int getWidth() { return texWidth; } - + /** * Returns the height of the allocated OpenGL texture in pixels. * Note that the texture height will be greater than or equal to the @@ -321,9 +346,9 @@ public class Texture { */ public int getHeight() { return texHeight; - } - - /** + } + + /** * Returns the width of the image contained within this texture. * Note that for non-power-of-two textures in particular this may * not be equal to the result of {@link #getWidth}. It is @@ -365,7 +390,7 @@ public class Texture { * entire image. If the TextureData indicated that the texture * coordinates must be flipped vertically, the returned * TextureCoords will take that into account. - * + * * @return the texture coordinates corresponding to the entire image */ public TextureCoords getImageTexCoords() { @@ -382,7 +407,7 @@ public class Texture { * flipped vertically, the returned TextureCoords will take that * into account; this should not be handled by the end user in the * specification of the y1 and y2 coordinates. - * + * * @return the texture coordinates corresponding to the specified sub-image */ public TextureCoords getSubImageTexCoords(int x1, int y1, int x2, int y2) { @@ -407,9 +432,9 @@ public class Texture { } /** - * Updates the entire content area of this texture using the data in - * the given image. - * + * Updates the entire content area incl. {@link TextureCoords} + * of this texture using the data in the given image. + * * @throws GLException if any OpenGL-related errors occurred */ public void updateImage(GL gl, TextureData data) throws GLException { @@ -429,10 +454,24 @@ public class Texture { } /** - * Updates the content area of the specified target of this texture + * Change whether the TextureData requires a vertical flip of + * the texture coords. + * <p> + * No-op if no change, otherwise generates new {@link TextureCoords}. + * </p> + */ + public void setMustFlipVertically(boolean v) { + if( v != mustFlipVertically ) { + mustFlipVertically = v; + updateTexCoords(); + } + } + + /** + * Updates the content area incl. {@link TextureCoords} of the specified target of this texture * using the data in the given image. In general this is intended * for construction of cube maps. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void updateImage(GL gl, TextureData data, int targetOverride) throws GLException { @@ -448,12 +487,12 @@ public class Texture { // See whether we have automatic mipmap generation support boolean haveAutoMipmapGeneration = - (gl.isExtensionAvailable("GL_VERSION_1_4") || - gl.isExtensionAvailable("GL_SGIS_generate_mipmap")); + (gl.isExtensionAvailable(GLExtensions.VERSION_1_4) || + gl.isExtensionAvailable(GLExtensions.SGIS_generate_mipmap)); // Indicate to the TextureData what functionality is available - data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); - data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr)); + data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2)); // Indicates whether both width and height are power of two boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight); @@ -646,7 +685,7 @@ public class Texture { int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR); int magFilter = GL.GL_LINEAR; - int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP; + int wrapMode = (gl.isExtensionAvailable(GLExtensions.VERSION_1_2) || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP; // REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) { @@ -753,7 +792,7 @@ public class Texture { * texture's target. This gives control over parameters such as * GL_TEXTURE_MAX_ANISOTROPY_EXT. Causes this texture to be bound to * the current texture state. - * + * * @throws GLException if no OpenGL context was current or if any * OpenGL-related errors occurred */ @@ -767,7 +806,7 @@ public class Texture { * Sets the OpenGL multi-floating-point texture parameter for the * texture's target. Causes this texture to be bound to the current * texture state. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void setTexParameterfv(GL gl, int parameterName, @@ -780,7 +819,7 @@ public class Texture { * Sets the OpenGL multi-floating-point texture parameter for the * texture's target. Causes this texture to be bound to the current * texture state. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void setTexParameterfv(GL gl, int parameterName, @@ -796,7 +835,7 @@ public class Texture { * to GL_CLAMP_TO_EDGE if OpenGL 1.2 is supported on the current * platform and GL_CLAMP if not. Causes this texture to be bound to * the current texture state. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void setTexParameteri(GL gl, int parameterName, @@ -809,7 +848,7 @@ public class Texture { * Sets the OpenGL multi-integer texture parameter for the texture's * target. Causes this texture to be bound to the current texture * state. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void setTexParameteriv(GL gl, int parameterName, @@ -822,7 +861,7 @@ public class Texture { * Sets the OpenGL multi-integer texture parameter for the texture's * target. Causes this texture to be bound to the current texture * state. - * + * * @throws GLException if any OpenGL-related errors occurred */ public void setTexParameteriv(GL gl, int parameterName, @@ -832,15 +871,34 @@ public class Texture { } /** - * Returns the underlying OpenGL texture object for this texture. + * Returns the underlying OpenGL texture object for this texture + * and generates it if not done yet. + * <p> * Most applications will not need to access this, since it is * handled automatically by the bind(GL) and destroy(GL) APIs. + * </p> + * @param gl required to be valid and current in case the texture object has not been generated yet, + * otherwise it may be <code>null</code>. + * @see #getTextureObject() */ public int getTextureObject(GL gl) { validateTexID(gl, false); return texID; } + /** + * Returns the underlying OpenGL texture object for this texture, + * maybe <code>0</code> if not yet generated. + * <p> + * Most applications will not need to access this, since it is + * handled automatically by the bind(GL) and destroy(GL) APIs. + * </p> + * @see #getTextureObject(GL) + */ + public int getTextureObject() { + return texID; + } + /** Returns an estimate of the amount of texture memory in bytes this Texture consumes. It should only be treated as an estimate; most applications should not need to query this but instead let @@ -899,6 +957,9 @@ public class Texture { private void setImageSize(int width, int height, int target) { imgWidth = width; imgHeight = height; + updateTexCoords(); + } + private void updateTexCoords() { if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { if (mustFlipVertically) { coords = new TextureCoords(0, imgHeight, imgWidth, 0); @@ -907,12 +968,17 @@ public class Texture { } } else { if (mustFlipVertically) { - coords = new TextureCoords(0, (float) imgHeight / (float) texHeight, - (float) imgWidth / (float) texWidth, 0); + coords = new TextureCoords(0, // l + (float) imgHeight / (float) texHeight, // b + (float) imgWidth / (float) texWidth, // r + 0 // t + ); } else { - coords = new TextureCoords(0, 0, - (float) imgWidth / (float) texWidth, - (float) imgHeight / (float) texHeight); + coords = new TextureCoords(0, // l + 0, // b + (float) imgWidth / (float) texWidth, // r + (float) imgHeight / (float) texHeight // t + ); } } } @@ -920,8 +986,8 @@ public class Texture { private void updateSubImageImpl(GL gl, TextureData data, int newTarget, int mipmapLevel, int dstx, int dsty, int srcx, int srcy, int width, int height) throws GLException { - data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); - data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + data.setHaveEXTABGR(gl.isExtensionAvailable(GLExtensions.EXT_abgr)); + data.setHaveGL12(gl.isExtensionAvailable(GLExtensions.VERSION_1_2)); Buffer buffer = data.getBuffer(); if (buffer == null && data.getMipmapData() == null) { @@ -1039,8 +1105,8 @@ public class Texture { case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") && - !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) { + if (!gl.isExtensionAvailable(GLExtensions.EXT_texture_compression_s3tc) && + !gl.isExtensionAvailable(GLExtensions.NV_texture_compression_vtc)) { throw new GLException("DXTn compressed textures not supported by this graphics card"); } break; @@ -1076,14 +1142,14 @@ public class Texture { private static boolean haveTexRect(GL gl) { return (!disableTexRect && TextureIO.isTexRectEnabled() && - gl.isExtensionAvailable("GL_ARB_texture_rectangle")); + gl.isExtensionAvailable(GLExtensions.ARB_texture_rectangle)); } private static boolean preferTexRect(GL gl) { // Prefer GL_ARB_texture_rectangle on ATI hardware on Mac OS X // due to software fallbacks - if (NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) { + if (NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { String vendor = gl.glGetString(GL.GL_VENDOR); if (vendor != null && vendor.startsWith("ATI")) { return true; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java index 39647039b..ba59f89c5 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java @@ -1,21 +1,22 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * Copyright (c) 2012 JogAmp Community. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. @@ -76,7 +77,7 @@ public class TextureCoords { d[6+d_off] = right *ss; d[7+d_off] = top *ts; return d; } - + /** Returns the leftmost (x) texture coordinate of this rectangle. */ public float left() { return left; } @@ -92,6 +93,7 @@ public class TextureCoords { /** Returns the topmost (y) texture coordinate of this rectangle. */ public float top() { return top; } - + + @Override public String toString() { return "TexCoord[h: "+left+" - "+right+", v: "+bottom+" - "+top+"]"; } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java index 928f91ce5..5d88a76c0 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -1,21 +1,22 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. @@ -41,6 +42,7 @@ import java.nio.Buffer; import javax.media.opengl.GLProfile; import com.jogamp.opengl.util.GLBuffers; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; /** * Represents the data for an OpenGL texture. This is separated from @@ -54,11 +56,13 @@ import com.jogamp.opengl.util.GLBuffers; */ public class TextureData { + /** ColorSpace of pixel data. */ + public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK }; + protected int width; protected int height; private int border; - protected int pixelFormat; - protected int pixelType; + protected GLPixelAttributes pixelAttributes; protected int internalFormat; // perhaps inferred from pixelFormat? protected boolean mipmap; // indicates whether mipmaps should be generated // (ignored if mipmaps are supplied from the file) @@ -77,8 +81,9 @@ public class TextureData { protected boolean haveEXTABGR; protected boolean haveGL12; protected GLProfile glProfile; + protected ColorSpace pixelCS = ColorSpace.RGB; - /** + /** * Constructs a new TextureData object with the specified parameters * and data contained in the given Buffer. The optional Flusher can * be used to clean up native resources associated with this @@ -118,7 +123,7 @@ public class TextureData { * data were invalid, such as requesting mipmap generation for a * compressed texture */ - public TextureData(GLProfile glp, + public TextureData(GLProfile glp, int internalFormat, int width, int height, @@ -130,6 +135,60 @@ public class TextureData { boolean mustFlipVertically, Buffer buffer, Flusher flusher) throws IllegalArgumentException { + this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType), + mipmap, dataIsCompressed, mustFlipVertically, buffer, flusher); + } + + /** + * Constructs a new TextureData object with the specified parameters + * and data contained in the given Buffer. The optional Flusher can + * be used to clean up native resources associated with this + * TextureData when processing is complete; for example, closing of + * memory-mapped files that might otherwise require a garbage + * collection to reclaim and close. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param internalFormat the OpenGL internal format for the + * resulting texture; must be specified, may + * not be 0 + * @param width the width in pixels of the texture + * @param height the height in pixels of the texture + * @param border the number of pixels of border this texture + * data has (0 or 1) + * @param pixelAttributes the OpenGL pixel format and type for the + * resulting texture; must be specified, may + * not be 0 + * @param mipmap indicates whether mipmaps should be + * autogenerated (using GLU) for the resulting + * texture. Currently if mipmap is true then + * dataIsCompressed may not be true. + * @param dataIsCompressed indicates whether the texture data is in + * compressed form + * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT) + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + * @param buffer the buffer containing the texture data + * @param flusher optional flusher to perform cleanup tasks + * upon call to flush() + * + * @throws IllegalArgumentException if any parameters of the texture + * data were invalid, such as requesting mipmap generation for a + * compressed texture + */ + public TextureData(GLProfile glp, + int internalFormat, + int width, + int height, + int border, + GLPixelAttributes pixelAttributes, + boolean mipmap, + boolean dataIsCompressed, + boolean mustFlipVertically, + Buffer buffer, + Flusher flusher) throws IllegalArgumentException { if (mipmap && dataIsCompressed) { throw new IllegalArgumentException("Can not generate mipmaps for compressed textures"); } @@ -138,8 +197,7 @@ public class TextureData { this.width = width; this.height = height; this.border = border; - this.pixelFormat = pixelFormat; - this.pixelType = pixelType; + this.pixelAttributes = pixelAttributes; this.internalFormat = internalFormat; this.mipmap = mipmap; this.dataIsCompressed = dataIsCompressed; @@ -150,7 +208,7 @@ public class TextureData { estimatedMemorySize = estimatedMemorySize(buffer); } - /** + /** * Constructs a new TextureData object with the specified parameters * and data for multiple mipmap levels contained in the given array * of Buffers. The optional Flusher can be used to clean up native @@ -200,12 +258,63 @@ public class TextureData { boolean mustFlipVertically, Buffer[] mipmapData, Flusher flusher) throws IllegalArgumentException { + this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType), + dataIsCompressed, mustFlipVertically, mipmapData, flusher); + } + + /** + * Constructs a new TextureData object with the specified parameters + * and data for multiple mipmap levels contained in the given array + * of Buffers. The optional Flusher can be used to clean up native + * resources associated with this TextureData when processing is + * complete; for example, closing of memory-mapped files that might + * otherwise require a garbage collection to reclaim and close. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param internalFormat the OpenGL internal format for the + * resulting texture; must be specified, may + * not be 0 + * @param width the width in pixels of the topmost mipmap + * level of the texture + * @param height the height in pixels of the topmost mipmap + * level of the texture + * @param border the number of pixels of border this texture + * data has (0 or 1) + * @param pixelAttributes the OpenGL pixel format and type for the + * resulting texture; must be specified, may + * not be 0 + * @param dataIsCompressed indicates whether the texture data is in + * compressed form + * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT) + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + * @param mipmapData the buffers containing all mipmap levels + * of the texture's data + * @param flusher optional flusher to perform cleanup tasks + * upon call to flush() + * + * @throws IllegalArgumentException if any parameters of the texture + * data were invalid, such as requesting mipmap generation for a + * compressed texture + */ + public TextureData(GLProfile glp, + int internalFormat, + int width, + int height, + int border, + GLPixelAttributes pixelAttributes, + boolean dataIsCompressed, + boolean mustFlipVertically, + Buffer[] mipmapData, + Flusher flusher) throws IllegalArgumentException { this.glProfile = glp; this.width = width; this.height = height; this.border = border; - this.pixelFormat = pixelFormat; - this.pixelType = pixelType; + this.pixelAttributes = pixelAttributes; this.internalFormat = internalFormat; this.dataIsCompressed = dataIsCompressed; this.mustFlipVertically = mustFlipVertically; @@ -217,41 +326,57 @@ public class TextureData { } } + /** + * Returns the color space of the pixel data. + * @see #setColorSpace(ColorSpace) + */ + public ColorSpace getColorSpace() { return pixelCS; } + + /** + * Set the color space of the pixel data, which defaults to {@link ColorSpace#RGB}. + * @see #getColorSpace() + */ + public void setColorSpace(ColorSpace cs) { pixelCS = cs; } + /** Used only by subclasses */ - protected TextureData(GLProfile glp) { this.glProfile = glp; } + protected TextureData(GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; } /** Returns the width in pixels of the texture data. */ public int getWidth() { return width; } /** Returns the height in pixels of the texture data. */ public int getHeight() { return height; } /** Returns the border in pixels of the texture data. */ - public int getBorder() { - return border; + public int getBorder() { + return border; } - /** Returns the intended OpenGL pixel format of the texture data. */ + /** Returns the intended OpenGL {@link GLPixelAttributes} of the texture data, i.e. format and type. */ + public GLPixelAttributes getPixelAttributes() { + return pixelAttributes; + } + /** Returns the intended OpenGL pixel format of the texture data using {@link #getPixelAttributes()}. */ public int getPixelFormat() { - return pixelFormat; + return pixelAttributes.format; } - /** Returns the intended OpenGL pixel type of the texture data. */ + /** Returns the intended OpenGL pixel type of the texture data using {@link #getPixelAttributes()}. */ public int getPixelType() { - return pixelType; + return pixelAttributes.type; } /** Returns the intended OpenGL internal format of the texture data. */ - public int getInternalFormat() { - return internalFormat; + public int getInternalFormat() { + return internalFormat; } /** Returns whether mipmaps should be generated for the texture data. */ - public boolean getMipmap() { - return mipmap; + public boolean getMipmap() { + return mipmap; } /** Indicates whether the texture data is in compressed form. */ - public boolean isDataCompressed() { - return dataIsCompressed; + public boolean isDataCompressed() { + return dataIsCompressed; } /** Indicates whether the texture coordinates must be flipped vertically for proper display. */ - public boolean getMustFlipVertically() { - return mustFlipVertically; + public boolean getMustFlipVertically() { + return mustFlipVertically; } /** Returns the texture data, or null if it is specified as a set of mipmaps. */ public Buffer getBuffer() { @@ -259,18 +384,18 @@ public class TextureData { } /** Returns all mipmap levels for the texture data, or null if it is specified as a single image. */ - public Buffer[] getMipmapData() { - return mipmapData; + public Buffer[] getMipmapData() { + return mipmapData; } /** Returns the required byte alignment for the texture data. */ - public int getAlignment() { - return alignment; + public int getAlignment() { + return alignment; } /** Returns the row length needed for correct GL_UNPACK_ROW_LENGTH specification. This is currently only supported for non-mipmapped, non-compressed textures. */ - public int getRowLength() { - return rowLength; + public int getRowLength() { + return rowLength; } /** Sets the width in pixels of the texture data. */ @@ -280,9 +405,29 @@ public class TextureData { /** Sets the border in pixels of the texture data. */ public void setBorder(int border) { this.border = border; } /** Sets the intended OpenGL pixel format of the texture data. */ - public void setPixelFormat(int pixelFormat) { this.pixelFormat = pixelFormat; } - /** Sets the intended OpenGL pixel type of the texture data. */ - public void setPixelType(int pixelType) { this.pixelType = pixelType; } + public void setPixelAttributes(GLPixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; } + /** + * Sets the intended OpenGL pixel format component of {@link GLPixelAttributes} of the texture data. + * <p> + * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type. + * </p> + */ + public void setPixelFormat(int pixelFormat) { + if( pixelAttributes.format != pixelFormat ) { + pixelAttributes = new GLPixelAttributes(pixelFormat, pixelAttributes.type); + } + } + /** + * Sets the intended OpenGL pixel type component of {@link GLPixelAttributes} of the texture data. + * <p> + * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type. + * </p> + */ + public void setPixelType(int pixelType) { + if( pixelAttributes.type != pixelType) { + pixelAttributes = new GLPixelAttributes(pixelAttributes.format, pixelType); + } + } /** Sets the intended OpenGL internal format of the texture data. */ public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; } /** Sets whether mipmaps should be generated for the texture data. */ @@ -354,8 +499,10 @@ public class TextureData { public void flush(); } + @Override public String toString() { - return "TextureData["+width+"x"+height+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; + return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+ + pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; } //---------------------------------------------------------------------- diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index d72210016..0f64fd007 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2011 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,11 +29,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -41,17 +41,23 @@ package com.jogamp.opengl.util.texture; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.URL; import java.nio.Buffer; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2GL3; @@ -62,9 +68,11 @@ import javax.media.opengl.GLProfile; import jogamp.opengl.Debug; import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.PNGPixelRect; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; import com.jogamp.opengl.util.texture.spi.DDSImage; +import com.jogamp.opengl.util.texture.spi.JPEGImage; import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter; -import com.jogamp.opengl.util.texture.spi.PNGImage; import com.jogamp.opengl.util.texture.spi.SGIImage; import com.jogamp.opengl.util.texture.spi.TGAImage; import com.jogamp.opengl.util.texture.spi.TextureProvider; @@ -155,6 +163,14 @@ public class TextureIO { file. */ public static final String TIFF = "tiff"; + /** Constant which can be used as a file suffix to indicate a PAM + file, NetPbm magic 7 - binary RGB and RGBA. Write support only. */ + public static final String PAM = "pam"; + + /** Constant which can be used as a file suffix to indicate a PAM + file, NetPbm magic 6 - binary RGB. Write support only. */ + public static final String PPM = "ppm"; + private static final boolean DEBUG = Debug.debug("TextureIO"); // For manually disabling the use of the texture rectangle @@ -410,7 +426,7 @@ public class TextureIO { // methods that *do* require a current context // - /** + /** * Creates an OpenGL texture object from the specified TextureData * using the current OpenGL context. * @@ -423,7 +439,7 @@ public class TextureIO { return newTexture(GLContext.getCurrentGL(), data); } - /** + /** * Creates an OpenGL texture object from the specified TextureData * using the given OpenGL context. * @@ -438,8 +454,8 @@ public class TextureIO { } return new Texture(gl, data); } - - /** + + /** * Creates an OpenGL texture object from the specified file using * the current OpenGL context. * @@ -463,7 +479,7 @@ public class TextureIO { return texture; } - /** + /** * Creates an OpenGL texture object from the specified stream using * the current OpenGL context. * @@ -492,7 +508,7 @@ public class TextureIO { return texture; } - /** + /** * Creates an OpenGL texture object from the specified URL using the * current OpenGL context. * @@ -524,13 +540,13 @@ public class TextureIO { return texture; } - /** + /** * Creates an OpenGL texture object associated with the given OpenGL * texture target. The texture has * no initial data. This is used, for example, to construct cube * maps out of multiple TextureData objects. * - * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D, + * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D, * GL.GL_TEXTURE_RECTANGLE_ARB */ public static Texture newTexture(int target) { @@ -545,7 +561,7 @@ public class TextureIO { * undefined results. * * @param textureID the OpenGL texture object to wrap - * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D, + * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D, * GL2.GL_TEXTURE_RECTANGLE * @param texWidth the width of the texture in pixels * @param texHeight the height of the texture in pixels @@ -678,7 +694,7 @@ public class TextureIO { gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows); gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels); gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes); - + data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, fetchedFormat, GL.GL_UNSIGNED_BYTE, false, false, false, res, null); @@ -690,7 +706,7 @@ public class TextureIO { write(data, file); } - + public static void write(TextureData data, File file) throws IOException, GLException { for (Iterator<TextureWriter> iter = textureWriters.iterator(); iter.hasNext(); ) { TextureWriter writer = iter.next(); @@ -701,13 +717,17 @@ public class TextureIO { throw new IOException("No suitable texture writer found for "+file.getAbsolutePath()); } - + //---------------------------------------------------------------------- // SPI support // - /** Adds a TextureProvider to support reading of a new file - format. */ + /** + * Adds a TextureProvider to support reading of a new file format. + * <p> + * The last provider added, will be the first provider to be tested. + * </p> + */ public static void addTextureProvider(TextureProvider provider) { // Must always add at the front so the ImageIO provider is last, // so we don't accidentally use it instead of a user's possibly @@ -715,8 +735,12 @@ public class TextureIO { textureProviders.add(0, provider); } - /** Adds a TextureWriter to support writing of a new file - format. */ + /** + * Adds a TextureWriter to support writing of a new file format. + * <p> + * The last provider added, will be the first provider to be tested. + * </p> + */ public static void addTextureWriter(TextureWriter writer) { // Must always add at the front so the ImageIO writer is last, // so we don't accidentally use it instead of a user's possibly @@ -779,6 +803,7 @@ public class TextureIO { addTextureProvider(new DDSTextureProvider()); addTextureProvider(new SGITextureProvider()); addTextureProvider(new TGATextureProvider()); + addTextureProvider(new JPGTextureProvider()); addTextureProvider(new PNGTextureProvider()); // ImageIO writer, the fall-back, must be the first one added @@ -894,6 +919,7 @@ public class TextureIO { //---------------------------------------------------------------------- // DDS provider -- supports files only for now static class DDSTextureProvider implements TextureProvider { + @Override public TextureData newTextureData(GLProfile glp, File file, int internalFormat, int pixelFormat, @@ -908,6 +934,7 @@ public class TextureIO { return null; } + @Override public TextureData newTextureData(GLProfile glp, InputStream stream, int internalFormat, int pixelFormat, @@ -924,6 +951,7 @@ public class TextureIO { return null; } + @Override public TextureData newTextureData(GLProfile glp, URL url, int internalFormat, int pixelFormat, @@ -979,6 +1007,7 @@ public class TextureIO { } } TextureData.Flusher flusher = new TextureData.Flusher() { + @Override public void flush() { image.close(); } @@ -1022,6 +1051,7 @@ public class TextureIO { //---------------------------------------------------------------------- // Base class for SGI RGB and TGA image providers static abstract class StreamBasedTextureProvider implements TextureProvider { + @Override public TextureData newTextureData(GLProfile glp, File file, int internalFormat, int pixelFormat, @@ -1042,6 +1072,7 @@ public class TextureIO { } } + @Override public TextureData newTextureData(GLProfile glp, URL url, int internalFormat, int pixelFormat, @@ -1059,6 +1090,7 @@ public class TextureIO { //---------------------------------------------------------------------- // SGI RGB image provider static class SGITextureProvider extends StreamBasedTextureProvider { + @Override public TextureData newTextureData(GLProfile glp, InputStream stream, int internalFormat, int pixelFormat, @@ -1094,6 +1126,7 @@ public class TextureIO { //---------------------------------------------------------------------- // TGA (Targa) image provider static class TGATextureProvider extends StreamBasedTextureProvider { + @Override public TextureData newTextureData(GLProfile glp, InputStream stream, int internalFormat, int pixelFormat, @@ -1105,8 +1138,8 @@ public class TextureIO { pixelFormat = image.getGLFormat(); } if (internalFormat == 0) { - if(glp.isGL2GL3()) { - internalFormat = GL.GL_RGBA8; + if(glp.isGL2ES3()) { + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8; } else { internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; } @@ -1131,19 +1164,60 @@ public class TextureIO { //---------------------------------------------------------------------- // PNG image provider static class PNGTextureProvider extends StreamBasedTextureProvider { + @Override public TextureData newTextureData(GLProfile glp, InputStream stream, int internalFormat, int pixelFormat, boolean mipmap, String fileSuffix) throws IOException { if (PNG.equals(fileSuffix)) { - PNGImage image = PNGImage.read(/*glp, */ stream); + final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); + final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp); + if ( 0 == pixelFormat ) { + pixelFormat = glpa.format; + } // else FIXME: Actually not supported w/ preset pixelFormat! + if ( 0 == internalFormat ) { + final boolean hasAlpha = 4 == glpa.bytesPerPixel; + if(glp.isGL2ES3()) { + internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8; + } else { + internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; + } + } + return new TextureData(glp, internalFormat, + image.getSize().getWidth(), + image.getSize().getHeight(), + 0, + pixelFormat, + glpa.type, + mipmap, + false, + false, + image.getPixels(), + null); + } + + return null; + } + } + + //---------------------------------------------------------------------- + // JPEG image provider + static class JPGTextureProvider extends StreamBasedTextureProvider { + @Override + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (JPG.equals(fileSuffix)) { + JPEGImage image = JPEGImage.read(/*glp, */ stream); if (pixelFormat == 0) { pixelFormat = image.getGLFormat(); } if (internalFormat == 0) { - if(glp.isGL2GL3()) { - internalFormat = GL.GL_RGBA8; + if(glp.isGL2ES3()) { + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8; } else { internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; } @@ -1153,7 +1227,7 @@ public class TextureIO { image.getHeight(), 0, pixelFormat, - GL.GL_UNSIGNED_BYTE, + image.getGLType(), mipmap, false, false, @@ -1169,12 +1243,14 @@ public class TextureIO { // DDS texture writer // static class DDSTextureWriter implements TextureWriter { + @Override public boolean write(File file, TextureData data) throws IOException { if (DDS.equals(IOUtil.getFileSuffix(file))) { // See whether the DDS writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if (pixelType != GL.GL_BYTE && pixelType != GL.GL_UNSIGNED_BYTE) { throw new IOException("DDS writer only supports byte / unsigned byte textures"); @@ -1183,15 +1259,15 @@ public class TextureIO { int d3dFormat = 0; // FIXME: some of these are probably not completely correct and would require swizzling switch (pixelFormat) { - case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; - case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; - case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; - case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); - case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; - case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; - default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); + case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; + case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; + default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); } - + ByteBuffer[] mipmaps = null; if (data.getMipmapData() != null) { mipmaps = new ByteBuffer[data.getMipmapData().length]; @@ -1218,14 +1294,16 @@ public class TextureIO { // SGI (rgb) texture writer // static class SGITextureWriter implements TextureWriter { + @Override public boolean write(File file, TextureData data) throws IOException { String fileSuffix = IOUtil.getFileSuffix(file); if (SGI.equals(fileSuffix) || SGI_RGB.equals(fileSuffix)) { // See whether the SGI writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if ((pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA) && (pixelType == GL.GL_BYTE || @@ -1260,28 +1338,30 @@ public class TextureIO { //---------------------------------------------------------------------- // TGA (Targa) texture writer - + static class TGATextureWriter implements TextureWriter { + @Override public boolean write(File file, TextureData data) throws IOException { if (TGA.equals(IOUtil.getFileSuffix(file))) { // See whether the TGA writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; if ((pixelFormat == GL.GL_RGB || - pixelFormat == GL.GL_RGBA || + pixelFormat == GL.GL_RGBA || pixelFormat == GL2.GL_BGR || pixelFormat == GL.GL_BGRA ) && (pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) { - + ByteBuffer buf = (ByteBuffer) data.getBuffer(); if (null == buf) { buf = (ByteBuffer) data.getMipmapData()[0]; } buf.rewind(); - - if( pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA ) { + + if( pixelFormat == GL.GL_RGB || pixelFormat == GL.GL_RGBA ) { // Must reverse order of red and blue channels to get correct results int skip = ((pixelFormat == GL.GL_RGB) ? 3 : 4); for (int i = 0; i < buf.remaining(); i += skip) { @@ -1304,64 +1384,60 @@ public class TextureIO { } return false; - } + } } //---------------------------------------------------------------------- // PNG texture writer - + static class PNGTextureWriter implements TextureWriter { + @Override public boolean write(File file, TextureData data) throws IOException { if (PNG.equals(IOUtil.getFileSuffix(file))) { // See whether the PNG writer can handle this TextureData - int pixelFormat = data.getPixelFormat(); - int pixelType = data.getPixelType(); - boolean reversedChannels; - int bytesPerPixel; - switch(pixelFormat) { - case GL.GL_RGB: - reversedChannels=false; - bytesPerPixel=3; - break; - case GL.GL_RGBA: - reversedChannels=false; - bytesPerPixel=4; - break; - case GL2.GL_BGR: - reversedChannels=true; - bytesPerPixel=3; - break; - case GL.GL_BGRA: - reversedChannels=true; - bytesPerPixel=4; - break; - default: - reversedChannels=false; - bytesPerPixel=-1; - break; - } - if ( 1 < bytesPerPixel && - (pixelType == GL.GL_BYTE || - pixelType == GL.GL_UNSIGNED_BYTE)) { - - ByteBuffer buf = (ByteBuffer) data.getBuffer(); - if (null == buf) { - buf = (ByteBuffer) data.getMipmapData()[0]; + final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); + final int pixelFormat = pixelAttribs.format; + final int pixelType = pixelAttribs.type; + final int bytesPerPixel = pixelAttribs.bytesPerPixel; + final PixelFormat pixFmt = pixelAttribs.getPixelFormat(); + if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) && + ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) { + Buffer buf0 = data.getBuffer(); + if (null == buf0) { + buf0 = data.getMipmapData()[0]; + } + if( null == buf0 ) { + throw new IOException("Pixel storage buffer is null"); + } + final DimensionImmutable size = new Dimension(data.getWidth(), data.getHeight()); + if( buf0 instanceof ByteBuffer ) { + final ByteBuffer buf = (ByteBuffer) buf0; + buf.rewind(); + final PNGPixelRect image = new PNGPixelRect(pixFmt, size, + 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */, + -1f, -1f); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */)); + image.write(outs, true /* close */); + return true; + } else if( buf0 instanceof IntBuffer ) { + final IntBuffer buf = (IntBuffer) buf0; + buf.rewind(); + final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */)); + PNGPixelRect.write(pixFmt, size, + 0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */, + -1f, -1f, outs, true /* closeOutstream */); + return true; + } else { + throw new IOException("PNG writer doesn't support pixel storage buffer of type "+buf0.getClass().getName()); } - buf.rewind(); - - PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f, - bytesPerPixel, reversedChannels, buf); - image.write(file, true); - return true; } throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+ " / type 0x"+Integer.toHexString(pixelFormat)+" (only GL_RGB/A, GL_BGR/A + bytes)"); } return false; - } + } } - + //---------------------------------------------------------------------- // Helper routines // diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java index 5ee2104a3..ab9d1f8f0 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,7 +20,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. @@ -28,30 +28,35 @@ package com.jogamp.opengl.util.texture; import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLRunnable; +import javax.media.opengl.GLEventListener; + +import com.jogamp.opengl.util.TimeFrameI; /** * Protocol for texture sequences, like animations, movies, etc. * <p> - * Ensure to respect the texture coordinates provided by + * Ensure to respect the texture coordinates provided by * {@link TextureFrame}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getImageTexCoords() getImageTexCoords()}. * </p> - * The user's shader shall be fitted for this implementation. + * The user's shader shall be fitted for this implementation. * Assuming we use a base shader code w/o headers using </code>ShaderCode</code>. * (Code copied from unit test / demo <code>TexCubeES2</code>) * <pre> - * + * static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" }; static final String gl2_prelude = "#version 110\n"; static final String shaderBasename = "texsequence_xxx"; // the base shader code w/o headers - static final String myTextureLookupName = "myTexture2D"; // the desired texture lookup function - + static final String myTextureLookupName = "myTexture2D"; // the desired texture lookup function + private void initShader(GL2ES2 gl, TextureSequence texSeq) { // Create & Compile the shader objects - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class, + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TexCubeES2.class, "shader", "shader/bin", shaderBasename, true); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class, + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TexCubeES2.class, "shader", "shader/bin", shaderBasename, true); - + // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ] int rsFpPos; if(gl.isGLES2()) { @@ -68,25 +73,25 @@ import javax.media.opengl.GL; if(gl.isGLES2()) { // insert ES2 default precision declaration rsFpPos = rsFp.insertShaderSource(0, rsFpPos, es2_prelude[1]); - } + } // negotiate the texture lookup function name final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); - - // in case a fixed lookup function is being chosen, replace the name in our code + + // in case a fixed lookup function is being chosen, replace the name in our code rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - - // Cache the TextureSequence shader details in StringBuffer: + + // Cache the TextureSequence shader details in StringBuilder: final StringBuilder sFpIns = new StringBuilder(); - + // .. declaration of the texture sampler using the implementation specific type sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); - + // .. the actual texture lookup function, maybe null in case a built-in function is being used sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl()); - + // Now insert the TextureShader details in our shader after the given tag: rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns); - + // Create & Link the shader program ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -98,41 +103,70 @@ import javax.media.opengl.GL; * </pre> * The above procedure might look complicated, however, it allows most flexibility and * workarounds to also deal with GLSL bugs. - * + * */ public interface TextureSequence { - public static final String GL_OES_EGL_image_external_Required_Prelude = "#extension GL_OES_EGL_image_external : enable\n"; - public static final String GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; public static final String samplerExternalOES = "samplerExternalOES"; public static final String sampler2D = "sampler2D"; - - /** + + /** * Texture holder interface, maybe specialized by implementation - * to associated related data. + * to associated related data. */ - public static class TextureFrame { + public static class TextureFrame extends TimeFrameI { + public TextureFrame(Texture t, int pts, int duration) { + super(pts, duration); + texture = t; + } public TextureFrame(Texture t) { texture = t; } - + public final Texture getTexture() { return texture; } - + + @Override public String toString() { - return "TextureFrame[" + texture + "]"; + return "TextureFrame[pts " + pts + " ms, l " + duration + " ms, texID "+ (null != texture ? texture.getTextureObject() : 0) + "]"; } protected final Texture texture; } + /** + * Event listener to notify users of updates regarding the {@link TextureSequence}. + * <p> + * Implementations sending events down to all listeners, + * while not necessarily making the user's OpenGL context current. + * </p> + * <p> + * Events may be sent from a 3rd-party thread, possibly holding another, maybe shared, OpenGL context current.<br/> + * Hence a user shall not issue <i>any</i> OpenGL, time consuming + * or {@link TextureSequence} operations directly.<br> + * Instead, the user shall: + * <ul> + * <li>off-load complex or {@link TextureSequence} commands on another thread, or</li> + * <li>injecting {@link GLRunnable} objects via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}, or</li> + * <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li> + * </ul> + * </p> + * */ public interface TexSeqEventListener<T extends TextureSequence> { - /** - * Signaling listeners that {@link TextureSequence#getNextTexture(GL, boolean)} is able to deliver a new frame. - * @param ts the event source - * @param when system time in msec. + /** + * Signaling listeners that a new {@link TextureFrame} is available. + * <p> + * User shall utilize {@link TextureSequence#getNextTexture(GL)} to dequeue it to maintain + * a consistent queue. + * </p> + * @param ts the event source + * @param newFrame the newly enqueued frame + * @param when system time in msec. **/ - public void newFrameAvailable(T ts, long when); + public void newFrameAvailable(T ts, TextureFrame newFrame, long when); } - - /** Return the texture unit to be used with this frame. */ + + /** Returns the texture target used by implementation. */ + public int getTextureTarget(); + + /** Return the texture unit used to render the current frame. */ public int getTextureUnit(); public int[] getTextureMinMagFilter(); @@ -143,59 +177,59 @@ public interface TextureSequence { * Returns the last updated texture. * <p> * In case the instance is just initialized, it shall return a <code>TextureFrame</code> - * object with valid attributes. The texture content may be undefined - * until the first call of {@link #getNextTexture(GL, boolean)}.<br> - * </p> + * object with valid attributes. The texture content may be undefined + * until the first call of {@link #getNextTexture(GL)}.<br> + * </p> * Not blocking. - * - * @throws IllegalStateException if instance is not initialized + * + * @throws IllegalStateException if instance is not initialized */ public TextureFrame getLastTexture() throws IllegalStateException ; /** - * Returns the next texture to be rendered. + * Returns the next texture to be rendered. * <p> - * Implementation shall block until next frame is available if <code>blocking</code> is <code>true</code>, - * otherwise it shall return the last frame in case a new frame is not available. + * Implementation shall return the next frame if available, may block if a next frame may arrive <i>soon</i>. + * Otherwise implementation shall return the last frame. * </p> * <p> - * Shall return <code>null</code> in case <i>no</i> frame is available. + * Shall return <code>null</code> in case <i>no</i> next or last frame is available. * </p> - * - * @throws IllegalStateException if instance is not initialized + * + * @throws IllegalStateException if instance is not initialized */ - public TextureFrame getNextTexture(GL gl, boolean blocking) throws IllegalStateException ; - + public TextureFrame getNextTexture(GL gl) throws IllegalStateException ; + /** - * In case a shader extension is required, based on the implementation + * In case a shader extension is required, based on the implementation * and the runtime GL profile, this method returns the preprocessor macros, e.g.: * <pre> * #extension GL_OES_EGL_image_external : enable - * </pre> - * - * @throws IllegalStateException if instance is not initialized + * </pre> + * + * @throws IllegalStateException if instance is not initialized */ public String getRequiredExtensionsShaderStub() throws IllegalStateException ; - - /** + + /** * Returns either <code>sampler2D</code> or <code>samplerExternalOES</code> - * depending on {@link #getLastTexture()}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getTarget() getTarget()}. - * - * @throws IllegalStateException if instance is not initialized + * depending on {@link #getLastTexture()}.{@link TextureFrame#getTexture() getTexture()}.{@link Texture#getTarget() getTarget()}. + * + * @throws IllegalStateException if instance is not initialized **/ public String getTextureSampler2DType() throws IllegalStateException ; - + /** * @param desiredFuncName desired lookup function name. If <code>null</code> or ignored by the implementation, - * a build-in name is returned. + * a build-in name is returned. * @return the final lookup function name - * + * * @see {@link #getTextureLookupFragmentShaderImpl()} - * + * * @throws IllegalStateException if instance is not initialized */ public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException ; - + /** * Returns the complete texture2D lookup function code of type * <pre> @@ -208,14 +242,14 @@ public interface TextureSequence { * <i>funcName</i> can be negotiated and queried via {@link #getTextureLookupFunctionName(String)}. * </p> * Note: This function may return an empty string in case a build-in lookup - * function is being chosen. If the implementation desires so, + * function is being chosen. If the implementation desires so, * {@link #getTextureLookupFunctionName(String)} will ignore the desired function name * and returns the build-in lookup function name. * </p> * @see #getTextureLookupFunctionName(String) * @see #getTextureSampler2DType() - * - * @throws IllegalStateException if instance is not initialized + * + * @throws IllegalStateException if instance is not initialized */ - public String getTextureLookupFragmentShaderImpl() throws IllegalStateException ; -}
\ No newline at end of file + public String getTextureLookupFragmentShaderImpl() throws IllegalStateException ; +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java new file mode 100644 index 000000000..d8320c690 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java @@ -0,0 +1,168 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util.texture; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GL3; +import javax.media.opengl.GLException; + +/** + * Preserves a [ texture-unit, texture-target ] state. + * <p> + * The states keys are the retrieved active texture-unit and the given texture-target + * for which the following states are being queried: + * <pre> + * - texture-object + * - GL.GL_TEXTURE_MAG_FILTER + * - GL.GL_TEXTURE_MIN_FILTER + * - GL.GL_TEXTURE_WRAP_S + * - GL.GL_TEXTURE_WRAP_T + * </pre> + */ +public class TextureState { + /** + * Returns the <code>pname</code> to query the <code>textureTarget</code> currently bound to the active texture-unit. + * <p> + * Returns <code>0</code> is <code>textureTarget</code> is not supported. + * </p> + */ + public static final int getTextureTargetQueryName(int textureTarget) { + final int texBindQName; + switch(textureTarget) { + case GL.GL_TEXTURE_2D: texBindQName = GL.GL_TEXTURE_BINDING_2D; break; + case GL.GL_TEXTURE_CUBE_MAP: texBindQName = GL.GL_TEXTURE_BINDING_CUBE_MAP; break; + case GL2ES2.GL_TEXTURE_3D: texBindQName = GL2ES2.GL_TEXTURE_BINDING_3D; break; + case GL2GL3.GL_TEXTURE_1D: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D; break; + case GL2GL3.GL_TEXTURE_1D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D_ARRAY; break; + case GL2GL3.GL_TEXTURE_2D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_2D_ARRAY; break; + case GL2GL3.GL_TEXTURE_RECTANGLE: texBindQName = GL2GL3.GL_TEXTURE_BINDING_RECTANGLE; break; + case GL2GL3.GL_TEXTURE_BUFFER: texBindQName = GL2GL3.GL_TEXTURE_BINDING_BUFFER; break; + case GL3.GL_TEXTURE_2D_MULTISAMPLE: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE; break; + case GL3.GL_TEXTURE_2D_MULTISAMPLE_ARRAY: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; break; + default: texBindQName = 0; + } + return texBindQName; + } + + private final int target; + /** + * <pre> + * 0 - unit + * 1 - texture object + * 2 - GL.GL_TEXTURE_MAG_FILTER + * 3 - GL.GL_TEXTURE_MIN_FILTER + * 4 - GL.GL_TEXTURE_WRAP_S + * 5 - GL.GL_TEXTURE_WRAP_T + * </pre> + */ + private final int[] state = new int[] { 0, 0, 0, 0, 0, 0 }; + + private static final String toHexString(int i) { return "0x"+Integer.toHexString(i); } + + private static final int activeTexture(GL gl) { + final int[] vi = { 0 }; + gl.glGetIntegerv(GL.GL_ACTIVE_TEXTURE, vi, 0); + return vi[0]; + } + + /** + * Creates a texture state for the retrieved active texture-unit and the given texture-target. + * See {@link TextureState}. + * @param gl current GL context's GL object + * @param textureTarget + * @throws GLException if textureTarget is not supported + */ + public TextureState(GL gl, int textureTarget) throws GLException { + this(gl, activeTexture(gl), textureTarget); + } + + /** + * Creates a texture state for the given active texture-unit and the given texture-target. + * See {@link TextureState}. + * @param gl current GL context's GL object + * @param textureUnit of range [ {@link GL#GL_TEXTURE0}.. ] + * @param textureTarget + * @throws GLException if textureTarget is not supported + */ + public TextureState(GL gl, int textureUnit, int textureTarget) throws GLException { + target = textureTarget; + state[0] = textureUnit; + final int texBindQName = getTextureTargetQueryName(textureTarget); + if( 0 == texBindQName ) { + throw new GLException("Unsupported textureTarget "+toHexString(textureTarget)); + } + gl.glGetIntegerv(texBindQName, state, 1); + gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MAG_FILTER, state, 2); + gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MIN_FILTER, state, 3); + gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_S, state, 4); + gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_T, state, 5); + } + + /** + * Restores the texture-unit's texture-target state. + * <p> + * First the texture-unit is activated, then all states are restored. + * </p> + * @param gl current GL context's GL object + */ + public final void restore(GL gl) { + gl.glActiveTexture(state[0]); + gl.glBindTexture(target, state[1]); + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, state[2]); + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, state[3]); + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, state[4]); + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, state[5]); + } + + /** Returns the texture-unit of this state, key value. Unit is of range [ {@link GL#GL_TEXTURE0}.. ]. */ + public final int getUnit() { return state[0]; } + /** Returns the texture-target of this state, key value. */ + public final int getTarget() { return target; } + + /** Returns the state's texture-object. */ + public final int getObject() { return state[1]; } + /** Returns the state's mag-filter param. */ + public final int getMagFilter() { return state[2]; } + /** Returns the state's min-filter param. */ + public final int getMinFilter() { return state[3]; } + /** Returns the state's wrap-s param. */ + public final int getWrapS() { return state[4]; } + /** Returns the state's wrap-t param. */ + public final int getWrapT() { return state[5]; } + + + @Override + public final String toString() { + return "TextureState[unit "+(state[0] - GL.GL_TEXTURE0)+", target "+toHexString(target)+ + ": obj "+toHexString(state[1])+ + ", filter[mag "+toHexString(state[2])+", min "+toHexString(state[3])+"], "+ + ": wrap[s "+toHexString(state[4])+", t "+toHexString(state[5])+"]]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java index ad96a9939..202c08e4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java @@ -1,21 +1,22 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * Copyright (c) 2010 JogAmp Community. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. @@ -37,15 +38,36 @@ package com.jogamp.opengl.util.texture.awt; import java.awt.AlphaComposite; -import java.awt.Color; import java.awt.Graphics2D; import java.awt.Transparency; -import java.awt.color.*; -import java.awt.image.*; -import java.nio.*; +import java.awt.image.BufferedImage; +import java.awt.image.ComponentColorModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferDouble; +import java.awt.image.DataBufferFloat; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.DataBufferUShort; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; -import javax.media.opengl.*; -import com.jogamp.opengl.util.texture.*; +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; public class AWTTextureData extends TextureData { // Mechanism for lazily converting input BufferedImages with custom @@ -56,19 +78,19 @@ public class AWTTextureData extends TextureData { private boolean expectingEXTABGR; private boolean expectingGL12; - private static final ColorModel rgbaColorModel = - new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), - new int[] {8, 8, 8, 8}, true, true, + private static final java.awt.image.ColorModel rgbaColorModel = + new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB), + new int[] {8, 8, 8, 8}, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); - private static final ColorModel rgbColorModel = - new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + private static final java.awt.image.ColorModel rgbColorModel = + new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB), new int[] {8, 8, 8, 0}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); - /** + /** * Constructs a new TextureData object with the specified parameters * and data contained in the given BufferedImage. The resulting * TextureData "wraps" the contents of the BufferedImage, so if a @@ -91,7 +113,7 @@ public class AWTTextureData extends TextureData { * texture * @param image the image containing the texture data */ - public AWTTextureData(GLProfile glp, + public AWTTextureData(GLProfile glp, int internalFormat, int pixelFormat, boolean mipmap, @@ -114,33 +136,38 @@ public class AWTTextureData extends TextureData { } } - /** Returns the intended OpenGL pixel format of the texture data. */ - public int getPixelFormat() { + private void validatePixelAttributes() { if (imageForLazyCustomConversion != null) { if (!((expectingEXTABGR && haveEXTABGR) || (expectingGL12 && haveGL12))) { - revertPixelFormatAndType(); + revertPixelAttributes(); } } - return pixelFormat; } - /** Returns the intended OpenGL pixel type of the texture data. */ + + @Override + public GLPixelAttributes getPixelAttributes() { + validatePixelAttributes(); + return super.getPixelAttributes(); + } + + @Override + public int getPixelFormat() { + validatePixelAttributes(); + return super.getPixelFormat(); + } + @Override public int getPixelType() { - if (imageForLazyCustomConversion != null) { - if (!((expectingEXTABGR && haveEXTABGR) || - (expectingGL12 && haveGL12))) { - revertPixelFormatAndType(); - } - } - return pixelType; + validatePixelAttributes(); + return super.getPixelType(); } - /** Returns the texture data, or null if it is specified as a set of mipmaps. */ + @Override public Buffer getBuffer() { if (imageForLazyCustomConversion != null) { if (!((expectingEXTABGR && haveEXTABGR) || (expectingGL12 && haveGL12))) { - revertPixelFormatAndType(); + revertPixelAttributes(); // Must present the illusion to the end user that we are simply // wrapping the input BufferedImage createFromCustom(imageForLazyCustomConversion); @@ -150,7 +177,7 @@ public class AWTTextureData extends TextureData { } private void createFromImage(GLProfile glp, BufferedImage image) { - pixelType = 0; // Determine from image + pixelAttributes = GLPixelAttributes.UNDEF; // Determine from image mustFlipVertically = true; width = image.getWidth(); @@ -180,24 +207,21 @@ public class AWTTextureData extends TextureData { if (glp.isGL2GL3()) { switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: - pixelFormat = GL.GL_BGRA; - pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV); rowLength = scanlineStride; alignment = 4; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_INT_ARGB_PRE: - pixelFormat = GL.GL_BGRA; - pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV); rowLength = scanlineStride; alignment = 4; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_INT_BGR: - pixelFormat = GL.GL_RGBA; - pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV); rowLength = scanlineStride; alignment = 4; expectingGL12 = true; @@ -208,8 +232,7 @@ public class AWTTextureData extends TextureData { // we can pass the image data directly to OpenGL only if // we have an integral number of pixels in each scanline if ((scanlineStride % 3) == 0) { - pixelFormat = GL2GL3.GL_BGR; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 3; alignment = 1; } else { @@ -223,17 +246,16 @@ public class AWTTextureData extends TextureData { // we can pass the image data directly to OpenGL only if // we have an integral number of pixels in each scanline // and only if the GL_EXT_abgr extension is present - + // NOTE: disabling this code path for now as it appears it's // buggy at least on some NVidia drivers and doesn't perform // the necessary byte swapping (FIXME: needs more // investigation) if ((scanlineStride % 4) == 0 && glp.isGL2() && false) { - pixelFormat = GL2.GL_ABGR_EXT; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; alignment = 4; - + // Store a reference to the original image for later in // case it turns out that we don't have GL_EXT_abgr at the // time we're going to do the texture upload to OpenGL @@ -246,30 +268,26 @@ public class AWTTextureData extends TextureData { } } case BufferedImage.TYPE_USHORT_565_RGB: - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_SHORT_5_6_5; + pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5); rowLength = scanlineStride; alignment = 2; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_USHORT_555_RGB: - pixelFormat = GL.GL_BGRA; - pixelType = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV; + pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV); rowLength = scanlineStride; alignment = 2; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_BYTE_GRAY: - pixelFormat = GL.GL_LUMINANCE; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride; alignment = 1; break; case BufferedImage.TYPE_USHORT_GRAY: - pixelFormat = GL.GL_LUMINANCE; - pixelType = GL.GL_UNSIGNED_SHORT; + pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT); rowLength = scanlineStride; alignment = 2; break; @@ -282,15 +300,13 @@ public class AWTTextureData extends TextureData { case BufferedImage.TYPE_BYTE_INDEXED: case BufferedImage.TYPE_CUSTOM: default: - ColorModel cm = image.getColorModel(); + java.awt.image.ColorModel cm = image.getColorModel(); if (cm.equals(rgbColorModel)) { - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 3; alignment = 1; } else if (cm.equals(rgbaColorModel)) { - pixelFormat = GL.GL_RGBA; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; // FIXME: correct? alignment = 4; } else { @@ -302,8 +318,7 @@ public class AWTTextureData extends TextureData { } else { switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride; alignment = 3; expectingGL12 = true; @@ -318,24 +333,21 @@ public class AWTTextureData extends TextureData { case BufferedImage.TYPE_4BYTE_ABGR_PRE: throw new GLException("INT_BGR n.a."); case BufferedImage.TYPE_USHORT_565_RGB: - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_SHORT_5_6_5; + pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5); rowLength = scanlineStride; alignment = 2; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_USHORT_555_RGB: - pixelFormat = GL.GL_RGBA; - pixelType = GL.GL_UNSIGNED_SHORT_5_5_5_1; + pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1); rowLength = scanlineStride; alignment = 2; expectingGL12 = true; setupLazyCustomConversion(image); break; case BufferedImage.TYPE_BYTE_GRAY: - pixelFormat = GL.GL_LUMINANCE; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride; alignment = 1; break; @@ -350,15 +362,13 @@ public class AWTTextureData extends TextureData { case BufferedImage.TYPE_BYTE_INDEXED: case BufferedImage.TYPE_CUSTOM: default: - ColorModel cm = image.getColorModel(); + java.awt.image.ColorModel cm = image.getColorModel(); if (cm.equals(rgbColorModel)) { - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 3; alignment = 1; } else if (cm.equals(rgbaColorModel)) { - pixelFormat = GL.GL_RGBA; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; // FIXME: correct? alignment = 4; } else { @@ -375,6 +385,8 @@ public class AWTTextureData extends TextureData { private void setupLazyCustomConversion(BufferedImage image) { imageForLazyCustomConversion = image; boolean hasAlpha = image.getColorModel().hasAlpha(); + int pixelFormat = pixelAttributes.format; + int pixelType = pixelAttributes.type; if (pixelFormat == 0) { pixelFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; } @@ -401,6 +413,7 @@ public class AWTTextureData extends TextureData { } else { throw new RuntimeException("Unexpected DataBuffer type?"); } + pixelAttributes = new GLPixelAttributes(pixelFormat, pixelType); } private void createFromCustom(BufferedImage image) { @@ -409,7 +422,7 @@ public class AWTTextureData extends TextureData { // create a temporary image that is compatible with OpenGL boolean hasAlpha = image.getColorModel().hasAlpha(); - ColorModel cm = null; + java.awt.image.ColorModel cm = null; int dataBufferType = image.getRaster().getDataBuffer().getDataType(); // Don't use integer components for packed int images if (isPackedInt(image)) { @@ -419,12 +432,12 @@ public class AWTTextureData extends TextureData { cm = hasAlpha ? rgbaColorModel : rgbColorModel; } else { if (hasAlpha) { - cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB), null, true, true, Transparency.TRANSLUCENT, dataBufferType); } else { - cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB), null, false, false, Transparency.OPAQUE, dataBufferType); @@ -454,13 +467,12 @@ public class AWTTextureData extends TextureData { imgType == BufferedImage.TYPE_INT_ARGB_PRE); } - private void revertPixelFormatAndType() { + private void revertPixelAttributes() { // Knowing we don't have e.g. OpenGL 1.2 functionality available, // and knowing we're in the process of doing the fallback code // path, re-infer a vanilla pixel format and type compatible with // OpenGL 1.1 - pixelFormat = 0; - pixelType = 0; + pixelAttributes = GLPixelAttributes.UNDEF; setupLazyCustomConversion(imageForLazyCustomConversion); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java index fdd1365f7..c70f5d0f3 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -100,7 +100,7 @@ public class AWTTextureIO extends TextureIO { return newTextureDataImpl(glp, image, internalFormat, pixelFormat, mipmap); } - /** + /** * Creates an OpenGL texture object from the specified BufferedImage * using the current OpenGL context. * @@ -119,7 +119,7 @@ public class AWTTextureIO extends TextureIO { return texture; } - private static TextureData newTextureDataImpl(GLProfile glp, + private static TextureData newTextureDataImpl(GLProfile glp, BufferedImage image, int internalFormat, int pixelFormat, diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java index 3f91ae966..7311f20b3 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -166,7 +166,7 @@ public class DDSImage { public static DDSImage read(String filename) throws IOException { return read(new File(filename)); } - + /** Reads a DirectDraw surface from the specified file, returning the resulting DDSImage. @@ -212,7 +212,7 @@ public class DDSImage { } } - /** + /** * Creates a new DDSImage from data supplied by the user. The * resulting DDSImage can be written to disk using the write() * method. @@ -763,9 +763,11 @@ public class DDSImage { default: throw new IllegalArgumentException("d3dFormat must be one of the known formats"); } - + // Now check the mipmaps against this size int curSize = topmostMipmapSize; + int mipmapWidth = width; + int mipmapHeight = height; int totalSize = 0; for (int i = 0; i < mipmapData.length; i++) { if (mipmapData[i].remaining() != curSize) { @@ -773,7 +775,10 @@ public class DDSImage { " didn't match expected data size (expected " + curSize + ", got " + mipmapData[i].remaining() + ")"); } - curSize /= 4; + // Compute next mipmap size + if (mipmapWidth > 1) mipmapWidth /= 2; + if (mipmapHeight > 1) mipmapHeight /= 2; + curSize = computeBlockSize(mipmapWidth, mipmapHeight, 1, d3dFormat); totalSize += mipmapData[i].remaining(); } @@ -785,7 +790,7 @@ public class DDSImage { buf.put(mipmapData[i]); } this.buf = buf; - + // Allocate and initialize a Header header = new Header(); header.size = Header.size(); @@ -852,6 +857,32 @@ public class DDSImage { return blockSize; } + private static int computeBlockSize(int width, + int height, + int depth, + int pixelFormat) { + int blocksize; + switch (pixelFormat) { + case D3DFMT_R8G8B8: + blocksize = width*height*3; + break; + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + blocksize = width*height*4; + break; + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + blocksize = computeCompressedBlockSize(width, height, 1, pixelFormat); + break; + default: + throw new IllegalArgumentException("d3dFormat must be one of the known formats"); + } + return blocksize; + } + private int mipMapWidth(int map) { int width = getWidth(); for (int i = 0; i < map; i++) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java new file mode 100644 index 000000000..2081788ba --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java @@ -0,0 +1,177 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util.texture.spi; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import javax.media.opengl.GL; + +import jogamp.opengl.Debug; +import jogamp.opengl.util.jpeg.JPEGDecoder; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.util.texture.TextureData.ColorSpace; + +public class JPEGImage { + private static final boolean DEBUG = Debug.debug("JPEGImage"); + + + /** + * Reads a JPEG image from the specified InputStream, using the given color space for storage. + * + * @param in + * @param cs Storage color space, either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception! + * @return + * @throws IOException + */ + public static JPEGImage read(InputStream in, ColorSpace cs) throws IOException { + return new JPEGImage(in, cs); + } + + /** Reads a JPEG image from the specified InputStream, using the {@link ColorSpace#RGB}. */ + public static JPEGImage read(InputStream in) throws IOException { + return new JPEGImage(in, ColorSpace.RGB); + } + + private static class JPEGColorSink implements JPEGDecoder.ColorSink { + int width=0, height=0; + int sourceComponents=0; + ColorSpace sourceCS = ColorSpace.YCbCr; + int storageComponents; + final ColorSpace storageCS; + ByteBuffer data = null; + + JPEGColorSink(ColorSpace storageCM) { + this.storageCS = storageCM; + switch(storageCS) { + case RGB: + case YCbCr: + storageComponents = 3; + break; + default: + throw new IllegalArgumentException("Unsupported storage color-space: "+storageCS); + } + } + + @Override + public final ColorSpace allocate(int width, int height, ColorSpace sourceCM, int sourceComponents) throws RuntimeException { + this.width = width; + this.height = height; + this.sourceComponents = sourceComponents; + this.sourceCS = sourceCM; + this.data = Buffers.newDirectByteBuffer(width * height * storageComponents); + return storageCS; + } + + @Override + public final void storeRGB(int x, int y, byte r, byte g, byte b) { + int i = ( ( height - y - 1 ) * width + x ) * storageComponents; + data.put(i++, r); + data.put(i++, g); + data.put(i++, b); + // data.put(i++, (byte)0xff); + } + + @Override + public final void store2(int x, int y, byte c1, byte c2) { + throw new RuntimeException("not supported yet"); + } + + @Override + public final void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr) { + int i = ( ( height - y - 1 ) * width + x ) * storageComponents; + data.put(i++, Y); + data.put(i++, Cb); + data.put(i++, Cr); + } + + @Override + public String toString() { + return "JPEGPixels["+width+"x"+height+", sourceComp "+sourceComponents+", sourceCS "+sourceCS+", storageCS "+storageCS+", storageComp "+storageComponents+"]"; + } + }; + + private JPEGImage(InputStream in, ColorSpace cs) throws IOException { + pixelStorage = new JPEGColorSink(cs); + final JPEGDecoder decoder = new JPEGDecoder(); + decoder.parse(in); + pixelWidth = decoder.getWidth(); + pixelHeight = decoder.getHeight(); + decoder.getPixel(pixelStorage, pixelWidth, pixelHeight); + data = pixelStorage.data; + final boolean hasAlpha = false; + + bytesPerPixel = 3; + glFormat = GL.GL_RGB; + reversedChannels = false; // RGB[A] + if(DEBUG) { + System.err.println("JPEGImage: alpha "+hasAlpha+", bytesPerPixel "+bytesPerPixel+ + ", pixels "+pixelWidth+"x"+pixelHeight+", glFormat 0x"+Integer.toHexString(glFormat)); + System.err.println("JPEGImage: "+decoder); + System.err.println("JPEGImage: "+pixelStorage); + } + decoder.clear(null); + } + private JPEGColorSink pixelStorage; + private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel; + private boolean reversedChannels; + private final ByteBuffer data; + + /** Returns the color space of the pixel data */ + public ColorSpace getColorSpace() { return pixelStorage.storageCS; } + + /** Returns the number of components of the pixel data */ + public int getComponentCount() { return pixelStorage.storageComponents; } + + /** Returns the width of the image. */ + public int getWidth() { return pixelWidth; } + + /** Returns the height of the image. */ + public int getHeight() { return pixelHeight; } + + /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */ + public boolean getHasReversedChannels() { return reversedChannels; } + + /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */ + public int getGLFormat() { return glFormat; } + + /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */ + public int getGLType() { return GL.GL_UNSIGNED_BYTE; } + + /** Returns the bytes per pixel */ + public int getBytesPerPixel() { return bytesPerPixel; } + + /** Returns the raw data for this texture in the correct + (bottom-to-top) order for calls to glTexImage2D. */ + public ByteBuffer getData() { return data; } + + @Override + public String toString() { return "JPEGImage["+pixelWidth+"x"+pixelHeight+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+pixelStorage+", "+data+"]"; } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java index 37dbc54df..3c90d96e4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -82,38 +82,45 @@ public class LEDataInputStream extends FilterInputStream implements DataInput dataIn = new DataInputStream(in); } + @Override public void close() throws IOException { dataIn.close(); // better close as we create it. // this will close underlying as well. } + @Override public synchronized final int read(byte b[]) throws IOException { return dataIn.read(b, 0, b.length); } + @Override public synchronized final int read(byte b[], int off, int len) throws IOException { int rl = dataIn.read(b, off, len); return rl; } + @Override public final void readFully(byte b[]) throws IOException { dataIn.readFully(b, 0, b.length); } + @Override public final void readFully(byte b[], int off, int len) throws IOException { dataIn.readFully(b, off, len); } + @Override public final int skipBytes(int n) throws IOException { return dataIn.skipBytes(n); } + @Override public final boolean readBoolean() throws IOException { int ch = dataIn.read(); @@ -122,6 +129,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return (ch != 0); } + @Override public final byte readByte() throws IOException { int ch = dataIn.read(); @@ -130,6 +138,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return (byte)(ch); } + @Override public final int readUnsignedByte() throws IOException { int ch = dataIn.read(); @@ -138,6 +147,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return ch; } + @Override public final short readShort() throws IOException { int ch1 = dataIn.read(); @@ -147,8 +157,9 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return (short)((ch1 << 0) + (ch2 << 8)); } + @Override public final int readUnsignedShort() throws IOException - { + { int ch1 = dataIn.read(); int ch2 = dataIn.read(); if ((ch1 | ch2) < 0) @@ -156,6 +167,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return (ch1 << 0) + (ch2 << 8); } + @Override public final char readChar() throws IOException { int ch1 = dataIn.read(); @@ -165,6 +177,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return (char)((ch1 << 0) + (ch2 << 8)); } + @Override public final int readInt() throws IOException { int ch1 = dataIn.read(); @@ -176,18 +189,21 @@ public class LEDataInputStream extends FilterInputStream implements DataInput return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24)); } + @Override public final long readLong() throws IOException { int i1 = readInt(); int i2 = readInt(); - return ((long)(i1) & 0xFFFFFFFFL) + (i2 << 32); + return ((long)i1 & 0xFFFFFFFFL) + ((long)i2 << 32); } + @Override public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } + @Override public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); @@ -195,8 +211,9 @@ public class LEDataInputStream extends FilterInputStream implements DataInput /** * dont call this it is not implemented. - * @return empty new string + * @return empty new string **/ + @Override public final String readLine() throws IOException { return new String(); @@ -204,8 +221,9 @@ public class LEDataInputStream extends FilterInputStream implements DataInput /** * dont call this it is not implemented - * @return empty new string + * @return empty new string **/ + @Override public final String readUTF() throws IOException { return new String(); @@ -213,7 +231,7 @@ public class LEDataInputStream extends FilterInputStream implements DataInput /** * dont call this it is not implemented - * @return empty new string + * @return empty new string **/ public final static String readUTF(DataInput in) throws IOException { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java index e1e1ca924..93b097500 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -78,43 +78,51 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput dataOut = new DataOutputStream(out); } + @Override public void close() throws IOException { dataOut.close(); // better close as we create it. // this will close underlying as well. } + @Override public synchronized final void write(byte b[]) throws IOException { dataOut.write(b, 0, b.length); } + @Override public synchronized final void write(byte b[], int off, int len) throws IOException { dataOut.write(b, off, len); } + @Override public final void write(int b) throws IOException { dataOut.write(b); } + @Override public final void writeBoolean(boolean v) throws IOException { dataOut.writeBoolean(v); } + @Override public final void writeByte(int v) throws IOException { dataOut.writeByte(v); } /** Don't call this -- not implemented */ + @Override public final void writeBytes(String s) throws IOException { throw new UnsupportedOperationException(); } + @Override public final void writeChar(int v) throws IOException { dataOut.writeChar(((v >> 8) & 0xff) | @@ -122,21 +130,25 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput } /** Don't call this -- not implemented */ + @Override public final void writeChars(String s) throws IOException { throw new UnsupportedOperationException(); } + @Override public final void writeDouble(double v) throws IOException { writeLong(Double.doubleToRawLongBits(v)); } + @Override public final void writeFloat(float v) throws IOException { writeInt(Float.floatToRawIntBits(v)); } + @Override public final void writeInt(int v) throws IOException { dataOut.writeInt((v >>> 24) | @@ -145,12 +157,14 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput (v << 24)); } + @Override public final void writeLong(long v) throws IOException { writeInt((int) v); writeInt((int) (v >>> 32)); } + @Override public final void writeShort(int v) throws IOException { dataOut.writeShort(((v >> 8) & 0xff) | @@ -158,6 +172,7 @@ public class LEDataOutputStream extends FilterOutputStream implements DataOutput } /** Don't call this -- not implemented */ + @Override public final void writeUTF(String s) throws IOException { throw new UnsupportedOperationException(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java index c2b131b97..cabf4ebc5 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -77,16 +77,19 @@ public class NetPbmTextureWriter implements TextureWriter { public int getMagic() { return magic; } - public static final String PPM = "ppm"; - public static final String PAM = "pam"; + /** @see TextureIO#PPM */ + public static final String PPM = TextureIO.PPM; + /** @see TextureIO#PAM */ + public static final String PAM = TextureIO.PAM; public String getSuffix() { return (magic==6)?PPM:PAM; } + @Override public boolean write(File file, TextureData data) throws IOException { boolean res; final int magic_old = magic; - - // file suffix selection + + // file suffix selection if (0==magic) { if (PPM.equals(IOUtil.getFileSuffix(file))) { magic = 6; @@ -95,7 +98,7 @@ public class NetPbmTextureWriter implements TextureWriter { } else { return false; } - } + } try { res = writeImpl(file, data); } finally { @@ -103,7 +106,7 @@ public class NetPbmTextureWriter implements TextureWriter { } return res; } - + private boolean writeImpl(File file, TextureData data) throws IOException { int pixelFormat = data.getPixelFormat(); final int pixelType = data.getPixelType(); @@ -113,16 +116,16 @@ public class NetPbmTextureWriter implements TextureWriter { pixelFormat == GL.GL_BGRA ) && (pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) { - + ByteBuffer buf = (ByteBuffer) data.getBuffer(); if (null == buf ) { buf = (ByteBuffer) data.getMipmapData()[0]; } buf.rewind(); - + int comps = ( pixelFormat == GL.GL_RGBA || pixelFormat == GL.GL_BGRA ) ? 4 : 3 ; - - if( pixelFormat == GL2.GL_BGR || pixelFormat == GL.GL_BGRA ) { + + if( pixelFormat == GL2.GL_BGR || pixelFormat == GL.GL_BGRA ) { // Must reverse order of red and blue channels to get correct results for (int i = 0; i < buf.remaining(); i += comps) { byte red = buf.get(i + 0); @@ -139,7 +142,7 @@ public class NetPbmTextureWriter implements TextureWriter { } FileOutputStream fos = IOUtil.getFileOutputStream(file, true); - + StringBuilder header = new StringBuilder(); header.append("P"); header.append(magic); @@ -169,7 +172,7 @@ public class NetPbmTextureWriter implements TextureWriter { } fos.write(header.toString().getBytes()); - + FileChannel fosc = fos.getChannel(); fosc.write(buf); fosc.force(true); @@ -178,7 +181,7 @@ public class NetPbmTextureWriter implements TextureWriter { buf.rewind(); return true; - } + } throw new IOException("NetPbmTextureWriter writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java deleted file mode 100644 index a89418f84..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.jogamp.opengl.util.texture.spi; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -import javax.media.opengl.GL; - -import jogamp.opengl.util.pngj.ImageInfo; -import jogamp.opengl.util.pngj.ImageLine; -import jogamp.opengl.util.pngj.PngReader; -import jogamp.opengl.util.pngj.PngWriter; -import jogamp.opengl.util.pngj.chunks.PngChunkTextVar; - -import com.jogamp.common.nio.Buffers; -import com.jogamp.common.util.IOUtil; - - -public class PNGImage { - /** Creates a PNGImage from data supplied by the end user. Shares - data with the passed ByteBuffer. Assumes the data is already in - the correct byte order for writing to disk, i.e., RGB or RGBA bottom-to-top (OpenGL coord). */ - public static PNGImage createFromData(int width, int height, double dpiX, double dpiY, - int bytesPerPixel, boolean reversedChannels, ByteBuffer data) { - return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, data); - } - - /** Reads a PNG image from the specified InputStream. */ - public static PNGImage read(InputStream in) throws IOException { - return new PNGImage(in); - } - - /** Reverse read and store, implicitly flip image to GL coords. */ - private static final int getPixelRGBA8(ByteBuffer d, int dOff, ImageLine line, int lineOff, boolean hasAlpha) { - if(hasAlpha) { - d.put(dOff--, (byte)line.scanline[lineOff + 3]); // A - } - d.put(dOff--, (byte)line.scanline[lineOff + 2]); // B - d.put(dOff--, (byte)line.scanline[lineOff + 1]); // G - d.put(dOff--, (byte)line.scanline[lineOff ]); // R - return dOff; - } - /** Reverse read and store, implicitly flip image from GL coords. */ - private static int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha, boolean reversedChannels) { - if(reversedChannels) { - line.scanline[lineOff ] = d.get(dOff--); // R, A - line.scanline[lineOff + 1] = d.get(dOff--); // G, B - line.scanline[lineOff + 2] = d.get(dOff--); // B, G - if(hasAlpha) { - line.scanline[lineOff + 3] = d.get(dOff--);// R - } - } else { - if(hasAlpha) { - line.scanline[lineOff + 3] = d.get(dOff--); // A - } - line.scanline[lineOff + 2] = d.get(dOff--); // B - line.scanline[lineOff + 1] = d.get(dOff--); // G - line.scanline[lineOff ] = d.get(dOff--); // R - } - return dOff; - } - - private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, ByteBuffer data) { - pixelWidth=width; - pixelHeight=height; - dpi = new double[] { dpiX, dpiY }; - if(4 == bytesPerPixel) { - glFormat = GL.GL_RGBA; - } else if (3 == bytesPerPixel) { - glFormat = GL.GL_RGB; - } else { - throw new InternalError("XXX: bytesPerPixel "+bytesPerPixel); - } - this.bytesPerPixel = bytesPerPixel; - this.reversedChannels = reversedChannels; - this.data = data; - } - - private PNGImage(InputStream in) { - final PngReader pngr = new PngReader(new BufferedInputStream(in), null); - final int channels = pngr.imgInfo.channels; - if (3 > channels || channels > 4 ) { - throw new RuntimeException("PNGImage can only handle RGB/RGBA images for now. Channels "+channels); - } - bytesPerPixel=pngr.imgInfo.bytesPixel; - if (3 > bytesPerPixel || bytesPerPixel > 4 ) { - throw new RuntimeException("PNGImage can only handle RGB/RGBA images for now. BytesPerPixel "+bytesPerPixel); - } - pixelWidth=pngr.imgInfo.cols; - pixelHeight=pngr.imgInfo.rows; - dpi = new double[2]; - { - final double[] dpi2 = pngr.getMetadata().getDpi(); - dpi[0]=dpi2[0]; - dpi[1]=dpi2[1]; - } - glFormat= ( 4 == bytesPerPixel ) ? GL.GL_RGBA : GL.GL_RGB; - data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight); - reversedChannels = false; // RGB[A] - final boolean hasAlpha = 4 == bytesPerPixel; - int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store - for (int row = 0; row < pixelHeight; row++) { - final ImageLine l1 = pngr.readRow(row); - int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = getPixelRGBA8(data, dataOff, l1, lineOff, hasAlpha); - lineOff -= bytesPerPixel; - } - } - pngr.end(); - } - private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel; - private boolean reversedChannels; - private final double[] dpi; - private final ByteBuffer data; - - /** Returns the width of the image. */ - public int getWidth() { return pixelWidth; } - - /** Returns the height of the image. */ - public int getHeight() { return pixelHeight; } - - /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */ - public boolean getHasReversedChannels() { return reversedChannels; } - - /** Returns the dpi of the image. */ - public double[] getDpi() { return dpi; } - - /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ - public int getGLFormat() { return glFormat; } - - /** Returns the bytes per pixel */ - public int getBytesPerPixel() { return bytesPerPixel; } - - /** Returns the raw data for this texture in the correct - (bottom-to-top) order for calls to glTexImage2D. */ - public ByteBuffer getData() { return data; } - - public void write(File out, boolean allowOverwrite) throws IOException { - final ImageInfo imi = new ImageInfo(pixelWidth, pixelHeight, 8, (4 == bytesPerPixel) ? true : false); // 8 bits per channel, no alpha - // open image for writing to a output stream - final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out, allowOverwrite)); - try { - final PngWriter png = new PngWriter(outs, imi); - // add some optional metadata (chunks) - png.getMetadata().setDpi(dpi[0], dpi[1]); - png.getMetadata().setTimeNow(0); // 0 seconds fron now = now - png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGImage"); - // png.getMetadata().setText("my key", "my text"); - final boolean hasAlpha = 4 == bytesPerPixel; - final ImageLine l1 = new ImageLine(imi); - int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse read - for (int row = 0; row < pixelHeight; row++) { - int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels); - lineOff -= bytesPerPixel; - } - png.writeRow(l1, row); - } - png.end(); - } finally { - IOUtil.close(outs, false); - } - } - - public String toString() { return "PNGImage["+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+" x "+dpi[1]+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+data+"]"; } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java index d35330f58..cbc8e652f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java @@ -1,21 +1,21 @@ /* * Portions Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -72,15 +72,15 @@ public class SGIImage { byte storage; // Storage format // 0 for uncompressed // 1 for RLE compression - byte bpc; // Number of bytes per pixel channel + byte bpc; // Number of bytes per pixel channel // Legally 1 or 2 short dimension; // Number of dimensions // Legally 1, 2, or 3 // 1 means a single row, XSIZE long // 2 means a single 2D image // 3 means multiple 2D images - short xsize; // X size in pixels - short ysize; // Y size in pixels + short xsize; // X size in pixels + short ysize; // Y size in pixels short zsize; // Number of channels // 1 indicates greyscale // 3 indicates RGB @@ -126,6 +126,7 @@ public class SGIImage { in.read(tmp); } + @Override public String toString() { return ("magic: " + magic + " storage: " + (int) storage + @@ -226,6 +227,7 @@ public class SGIImage { (bottom-to-top) order for calls to glTexImage2D. */ public byte[] getData() { return data; } + @Override public String toString() { return header.toString(); } @@ -233,7 +235,7 @@ public class SGIImage { //---------------------------------------------------------------------- // Internals only below this point // - + private void decodeImage(DataInputStream in) throws IOException { if (header.storage == 1) { // Read RLE compression data; row starts and sizes @@ -478,7 +480,7 @@ public class SGIImage { for (int z = 0; z < zsize; z++) { for (int y = ystart; y != yend; y += yincr) { // RLE-compress each row. - + int x = 0; byte count = 0; boolean repeat_mode = false; @@ -486,7 +488,7 @@ public class SGIImage { int start_ptr = ptr; int num_ptr = ptr++; byte repeat_val = 0; - + while (x < xsize) { // see if we should switch modes should_switch = false; @@ -503,7 +505,7 @@ public class SGIImage { if (DEBUG) System.err.println("left side was " + ((int) imgref(data, x, y, z, xsize, ysize, zsize)) + ", right side was " + (int)imgref(data, x+i, y, z, xsize, ysize, zsize)); - + if (imgref(data, x, y, z, xsize, ysize, zsize) != imgref(data, x+i, y, z, xsize, ysize, zsize)) should_switch = false; @@ -531,7 +533,7 @@ public class SGIImage { repeat_mode = true; repeat_val = imgref(data, x, y, z, xsize, ysize, zsize); } - + if (x > 0) { // reset the number pointer num_ptr = ptr++; @@ -539,7 +541,7 @@ public class SGIImage { count = 0; } } - + // if not in repeat mode, copy element to ptr if (!repeat_mode) { rlebuf[ptr++] = imgref(data, x, y, z, xsize, ysize, zsize); @@ -581,8 +583,8 @@ public class SGIImage { // Now we have the offset tables computed, as well as the RLE data. // Output this information to the file. total_size = ptr; - - if (DEBUG) + + if (DEBUG) System.err.println("total_size was " + total_size); DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(IOUtil.getFileOutputStream(file, true))); @@ -604,7 +606,7 @@ public class SGIImage { byte[] dest = new byte[16384]; int pos = 0; int numRead = 0; - + boolean done = false; do { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java index e202c59b7..15cd63eb3 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -146,9 +146,9 @@ public class TGAImage { tgaType = TYPE_OLD; // dont try and get footer. // initial header fields - idLength = in.readUnsignedByte(); + idLength = in.readUnsignedByte(); colorMapType = in.readUnsignedByte(); - imageType = in.readUnsignedByte(); + imageType = in.readUnsignedByte(); // color map header fields firstEntryIndex = in.readUnsignedShort(); @@ -199,6 +199,7 @@ public class TGAImage { public byte[] imageIDbuf() { return imageIDbuf; } public String imageID() { return imageID; } + @Override public String toString() { return "TGA Header " + " id length: " + idLength + @@ -273,21 +274,32 @@ public class TGAImage { throw new IOException("TGADecoder Compressed Colormapped images not supported"); case Header.TRUECOLOR: - throw new IOException("TGADecoder Compressed True Color images not supported"); + switch (header.pixelDepth) { + case 16: + throw new IOException("TGADecoder Compressed 16-bit True Color images not supported"); + + case 24: + case 32: + decodeRGBImageRLE24_32(glp, dIn); + break; + } + break; case Header.BLACKWHITE: throw new IOException("TGADecoder Compressed Grayscale images not supported"); } } - + /** * This assumes that the body is for a 24 bit or 32 bit for a * RGB or ARGB image respectively. */ private void decodeRGBImageU24_32(GLProfile glp, LEDataInputStream dIn) throws IOException { + setupImage24_32(glp); + int i; // row index int y; // output row index - int rawWidth = header.width() * (header.pixelDepth() / 8); + int rawWidth = header.width() * bpp; byte[] rawBuf = new byte[rawWidth]; byte[] tmpData = new byte[rawWidth * header.height()]; @@ -302,31 +314,57 @@ public class TGAImage { System.arraycopy(rawBuf, 0, tmpData, y * rawWidth, rawBuf.length); } - if (header.pixelDepth() == 24) { - bpp=3; - if(glp.isGL2GL3()) { - format = GL2GL3.GL_BGR; - } else { - format = GL.GL_RGB; - swapBGR(tmpData, rawWidth, header.height(), bpp); - } - } else { - assert header.pixelDepth() == 32; - bpp=4; + if(format == GL.GL_RGB || format == GL.GL_RGBA) + swapBGR(tmpData, rawWidth, header.height(), bpp); + data = ByteBuffer.wrap(tmpData); + } + + /** + * This assumes that the body is for a 24 bit or 32 bit for a + * RGB or ARGB image respectively. + */ + private void decodeRGBImageRLE24_32(GLProfile glp, LEDataInputStream dIn) throws IOException { + setupImage24_32(glp); + + byte[] pixel = new byte[bpp]; + int rawWidth = header.width() * bpp; + byte[] tmpData = new byte[rawWidth * header.height()]; + int i = 0, j; + int packet, len; + while (i < tmpData.length) { + packet = dIn.readUnsignedByte(); + len = (packet & 0x7F) + 1; + if ((packet & 0x80) != 0) { + dIn.read(pixel); + for (j = 0; j < len; ++j) + System.arraycopy(pixel, 0, tmpData, i + j * bpp, bpp); + } else + dIn.read(tmpData, i, len * bpp); + i += bpp * len; + } + + if(format == GL.GL_RGB || format == GL.GL_RGBA) + swapBGR(tmpData, rawWidth, header.height(), bpp); + data = ByteBuffer.wrap(tmpData); + } + + private void setupImage24_32(GLProfile glp) { + bpp = header.pixelDepth / 8; + switch (header.pixelDepth) { + case 24: + format = glp.isGL2GL3() ? GL2GL3.GL_BGR : GL.GL_RGB; + break; + case 32: boolean useBGRA = glp.isGL2GL3(); if(!useBGRA) { final GLContext ctx = GLContext.getCurrent(); useBGRA = null != ctx && ctx.isTextureFormatBGRA8888Available(); } - if( useBGRA ) { - format = GL.GL_BGRA; - } else { - format = GL.GL_RGBA; - swapBGR(tmpData, rawWidth, header.height(), bpp); - } + format = useBGRA ? GL.GL_BGRA : GL.GL_RGBA; + break; + default: + assert false; } - - data = ByteBuffer.wrap(tmpData); } private static void swapBGR(byte[] data, int bWidth, int height, int bpp) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java index 88018edbe..0299531b1 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java index 55527cef5..35b8efa72 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java index 6e2f1b992..18ad429d2 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -54,6 +54,7 @@ import com.jogamp.opengl.util.texture.spi.*; public class IIOTextureProvider implements TextureProvider { private static final boolean DEBUG = Debug.debug("TextureIO"); + @Override public TextureData newTextureData(GLProfile glp, File file, int internalFormat, int pixelFormat, @@ -70,6 +71,7 @@ public class IIOTextureProvider implements TextureProvider { return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); } + @Override public TextureData newTextureData(GLProfile glp, InputStream stream, int internalFormat, int pixelFormat, @@ -86,6 +88,7 @@ public class IIOTextureProvider implements TextureProvider { return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); } + @Override public TextureData newTextureData(GLProfile glp, URL url, int internalFormat, int pixelFormat, diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java index 89d0d20a1..be82e4fb8 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,11 +28,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -53,6 +53,7 @@ import com.jogamp.opengl.util.texture.*; import com.jogamp.opengl.util.texture.spi.*; public class IIOTextureWriter implements TextureWriter { + @Override public boolean write(File file, TextureData data) throws IOException { int pixelFormat = data.getPixelFormat(); @@ -113,7 +114,7 @@ public class IIOTextureWriter implements TextureWriter { return ImageIO.write(image, IOUtil.getFileSuffix(file), file); } - + throw new IOException("ImageIO writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); } } |