diff options
Diffstat (limited to 'src/jogl/classes')
4 files changed, 331 insertions, 84 deletions
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 15b8930bb..66fba98fe 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -1,5 +1,6 @@ /* * 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 @@ -37,9 +38,13 @@ package com.jogamp.opengl.util.texture; import java.nio.Buffer; +import java.nio.ByteBuffer; +import javax.media.opengl.GL; +import javax.media.opengl.GLContext; import javax.media.opengl.GLProfile; +import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.GLBuffers; /** @@ -54,28 +59,92 @@ import com.jogamp.opengl.util.GLBuffers; */ public class TextureData { - public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK }; + /** ColorSpace of pixel data. */ + public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK }; - public static interface ColorSink { + /** Pixel data attributes. */ + public static class PixelAttributes { + /** Undefinded instance of {@link PixelAttributes}, having format:=0 and type:= 0. */ + public static final PixelAttributes UNDEF = new PixelAttributes(0, 0); + + /** The OpenGL pixel data format */ + public final int format; + /** The OpenGL pixel data type */ + public final int type; + public PixelAttributes(int dataFormat, int dataType) { + this.format = dataFormat; + this.type = dataType; + } + public String toString() { + return "PixelAttributes[fFmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+"]"; + } + } + /** Allows user to interface with another toolkit to define {@link PixelAttributes} and memory buffer to produce {@link TextureData}. */ + public static interface PixelBufferProvider { + /** Called first to determine {@link PixelAttributes}. */ + PixelAttributes getAttributes(GL gl, int componentCount); + + /** + * Returns true, if implementation requires a new buffer based on the new size + * and previous aquired {@link #getAttributes(GL, int) attributes} due to pixel alignment, otherwise false. + * @see #allocate(int, int, int) + */ + boolean requiresNewBuffer(int width, int height); + + /** + * Called after {@link #getAttributes(GL, int)} to retrieve the NIO or array backed pixel {@link Buffer}. + * <p> + * Being called to gather the initial {@link Buffer}, if the existing {@link Buffer} size is not sufficient, + * or if {@link #requiresNewBuffer(int, int)} returns false. + * </p> + * <p> + * Number of components was passed via {@link #getAttributes(GL, int)}. + * </p> + * <p> + * The returned buffer must have at least <code>minByteSize</code> {@link Buffer#remaining() remaining}. + * </p> + */ + Buffer allocate(int width, int height, int minByteSize); + } + /** + * Default {@link PixelBufferProvider} utilizing best match for {@link PixelAttributes} + * and {@link #allocate(int, int, int) allocating} a {@link ByteBuffer}. + */ + public static class DefPixelBufferProvider implements PixelBufferProvider { + @Override + public PixelAttributes getAttributes(GL gl, int componentCount) { + final GLContext ctx = gl.getContext(); + final int dFormat, dType; + + if(gl.isGL2GL3() && 3 == componentCount) { + dFormat = GL.GL_RGB; + dType = GL.GL_UNSIGNED_BYTE; + } else { + dFormat = ctx.getDefaultPixelDataFormat(); + dType = ctx.getDefaultPixelDataType(); + } + return new TextureData.PixelAttributes(dFormat, dType); + } + @Override + public boolean requiresNewBuffer(int width, int height) { + return false; + } /** - * @param width - * @param height - * @param sourceCS the color-space of the decoded JPEG - * @param sourceComponents number of components used for the given source color-space - * @return Either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception! - * @throws RuntimeException + * {@inheritDoc} + * <p> + * Returns an NIO {@link ByteBuffer} of <code>minByteSize</code>. + * </p> */ - public ColorSpace allocate(int width, int height, ColorSpace sourceCS, int sourceComponents) throws RuntimeException; - public void store2(int x, int y, byte c1, byte c2); - public void storeRGB(int x, int y, byte r, byte g, byte b); - public void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr); + @Override + public final Buffer allocate(int width, int height, int minByteSize) { + return Buffers.newDirectByteBuffer(minByteSize); + } } protected int width; protected int height; private int border; - protected int pixelFormat; - protected int pixelType; + protected PixelAttributes 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) @@ -148,6 +217,60 @@ public class TextureData { boolean mustFlipVertically, Buffer buffer, Flusher flusher) throws IllegalArgumentException { + this(glp, internalFormat, width, height, border, new PixelAttributes(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, + PixelAttributes 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"); } @@ -156,8 +279,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; @@ -167,7 +289,7 @@ public class TextureData { alignment = 1; // FIXME: is this correct enough in all situations? estimatedMemorySize = estimatedMemorySize(buffer); } - + /** * Constructs a new TextureData object with the specified parameters * and data for multiple mipmap levels contained in the given array @@ -218,12 +340,63 @@ public class TextureData { boolean mustFlipVertically, Buffer[] mipmapData, Flusher flusher) throws IllegalArgumentException { + this(glp, internalFormat, width, height, border, new PixelAttributes(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, + PixelAttributes 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; @@ -234,7 +407,7 @@ public class TextureData { estimatedMemorySize += estimatedMemorySize(mipmapData[i]); } } - + /** * Returns the color space of the pixel data. * @see #setColorSpace(ColorSpace) @@ -248,7 +421,7 @@ public class TextureData { 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 = PixelAttributes.UNDEF; } /** Returns the width in pixels of the texture data. */ public int getWidth() { return width; } @@ -258,13 +431,17 @@ public class TextureData { public int getBorder() { return border; } + /** Returns the intended OpenGL {@link PixelAttributes} of the texture data, i.e. format and type. */ + public PixelAttributes getPixelAttributes() { + return pixelAttributes; + } /** Returns the intended OpenGL pixel format of the texture data. */ public int getPixelFormat() { - return pixelFormat; + return pixelAttributes.format; } /** Returns the intended OpenGL pixel type of the texture data. */ public int getPixelType() { - return pixelType; + return pixelAttributes.type; } /** Returns the intended OpenGL internal format of the texture data. */ public int getInternalFormat() { @@ -310,9 +487,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(PixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; } + /** + * Sets the intended OpenGL pixel format component of {@link PixelAttributes} of the texture data. + * <p> + * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type. + * </p> + */ + public void setPixelFormat(int pixelFormat) { + if( pixelAttributes.format != pixelFormat ) { + pixelAttributes = new PixelAttributes(pixelFormat, pixelAttributes.type); + } + } + /** + * Sets the intended OpenGL pixel type component of {@link PixelAttributes} of the texture data. + * <p> + * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type. + * </p> + */ + public void setPixelType(int pixelType) { + if( pixelAttributes.type != pixelType) { + pixelAttributes = new PixelAttributes(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. */ @@ -385,7 +582,8 @@ public class TextureData { } public String toString() { - return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", 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/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java index 3b90fad65..d77bd835e 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,5 +1,6 @@ /* * 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 @@ -65,9 +66,51 @@ import javax.media.opengl.GL2GL3; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureData.PixelBufferProvider; public class AWTTextureData extends TextureData { + public static final PixelAttributes awtPixelAttributesIntRGB = new PixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE); + + /** + * AWT {@link PixelBufferProvider} backed by a {@link BufferedImage} of type + * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB} + * and {@link #allocate(int, int, int) allocating} am array backed {@link IntBuffer}. + */ + public static final class AWTPixelBufferProviderInt implements PixelBufferProvider { + private BufferedImage image = null; + private int componentCount = 0; + + @Override + public PixelAttributes getAttributes(GL gl, int componentCount) { + this.componentCount = componentCount; + return awtPixelAttributesIntRGB; + } + @Override + public boolean requiresNewBuffer(int width, int height) { + return null == image || image.getWidth() != width || image.getHeight() != height; + } + /** + * {@inheritDoc} + * <p> + * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>. + * </p> + */ + @Override + public Buffer allocate(int width, int height, int minByteSize) { + image = new BufferedImage(width, height, 4 == componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); + final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + return IntBuffer.wrap( readBackIntBuffer ); + } + + /** Returns the number source components being used as indicated at {@link #allocate(int, int, int)}. */ + public int getComponentCount() { return componentCount; } + + /** Returns the underlying {@link BufferedImage} as allocated via {@link #allocate(int, int, int)}. */ + public BufferedImage getImage() { return image; } + } + // Mechanism for lazily converting input BufferedImages with custom // ColorModels to standard ones for uploading to OpenGL, as well as // backing off from the optimizations of hoping that either @@ -134,33 +177,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 PixelAttributes 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); @@ -170,7 +218,7 @@ public class AWTTextureData extends TextureData { } private void createFromImage(GLProfile glp, BufferedImage image) { - pixelType = 0; // Determine from image + pixelAttributes = PixelAttributes.UNDEF; // Determine from image mustFlipVertically = true; width = image.getWidth(); @@ -200,24 +248,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 PixelAttributes(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 PixelAttributes(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 PixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV); rowLength = scanlineStride; alignment = 4; expectingGL12 = true; @@ -228,8 +273,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 PixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 3; alignment = 1; } else { @@ -249,8 +293,7 @@ public class AWTTextureData extends TextureData { // 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 PixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; alignment = 4; @@ -266,30 +309,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 PixelAttributes(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 PixelAttributes(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 PixelAttributes(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 PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT); rowLength = scanlineStride; alignment = 2; break; @@ -304,13 +343,11 @@ public class AWTTextureData extends TextureData { default: java.awt.image.ColorModel cm = image.getColorModel(); if (cm.equals(rgbColorModel)) { - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new PixelAttributes(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 PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; // FIXME: correct? alignment = 4; } else { @@ -322,8 +359,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 PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride; alignment = 3; expectingGL12 = true; @@ -338,24 +374,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 PixelAttributes(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 PixelAttributes(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 PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride; alignment = 1; break; @@ -372,13 +405,11 @@ public class AWTTextureData extends TextureData { default: java.awt.image.ColorModel cm = image.getColorModel(); if (cm.equals(rgbColorModel)) { - pixelFormat = GL.GL_RGB; - pixelType = GL.GL_UNSIGNED_BYTE; + pixelAttributes = new PixelAttributes(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 PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); rowLength = scanlineStride / 4; // FIXME: correct? alignment = 4; } else { @@ -395,6 +426,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; } @@ -421,6 +454,7 @@ public class AWTTextureData extends TextureData { } else { throw new RuntimeException("Unexpected DataBuffer type?"); } + pixelAttributes = new PixelAttributes(pixelFormat, pixelType); } private void createFromCustom(BufferedImage image) { @@ -474,13 +508,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 = PixelAttributes.UNDEF; setupLazyCustomConversion(imageForLazyCustomConversion); } 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 index 14253e4af..4d3d088ba 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java @@ -38,7 +38,6 @@ import jogamp.opengl.util.jpeg.JPEGDecoder; import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.util.texture.TextureData.ColorSpace; -import com.jogamp.opengl.util.texture.TextureData.ColorSink; public class JPEGImage { private static final boolean DEBUG = Debug.debug("JPEGImage"); @@ -61,7 +60,7 @@ public class JPEGImage { return new JPEGImage(in, ColorSpace.RGB); } - private static class JPEGColorSink implements ColorSink { + private static class JPEGColorSink implements JPEGDecoder.ColorSink { int width=0, height=0; int sourceComponents=0; ColorSpace sourceCS = ColorSpace.YCbCr; diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java index 8df147405..251291a14 100644 --- a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java +++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java @@ -66,8 +66,8 @@ import jogamp.opengl.Debug; import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.VersionNumber; +import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureData.ColorSpace; -import com.jogamp.opengl.util.texture.TextureData.ColorSink; /** * @@ -89,6 +89,22 @@ public class JPEGDecoder { private static final boolean DEBUG = Debug.debug("JPEGImage"); private static final boolean DEBUG_IN = false; + /** Allows user to hook a {@link ColorSink} to another toolkit to produce {@link TextureData}. */ + public static interface ColorSink { + /** + * @param width + * @param height + * @param sourceCS the color-space of the decoded JPEG + * @param sourceComponents number of components used for the given source color-space + * @return Either {@link TextureData.ColorSpace#RGB} or {@link TextureData.ColorSpace#YCbCr}. {@link TextureData.ColorSpace#YCCK} and {@link TextureData.ColorSpace#CMYK} will throw an exception! + * @throws RuntimeException + */ + public TextureData.ColorSpace allocate(int width, int height, TextureData.ColorSpace sourceCS, int sourceComponents) throws RuntimeException; + public void store2(int x, int y, byte c1, byte c2); + public void storeRGB(int x, int y, byte r, byte g, byte b); + public void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr); + } + public static class JFIF { final VersionNumber version; final int densityUnits; @@ -1312,6 +1328,7 @@ public class JPEGDecoder { decoder.decode(component, component.getBlock(blockRow, blockCol)); } } + private final Decoder decoder = new Decoder(); /** wrong color space .. @@ -1333,7 +1350,7 @@ public class JPEGDecoder { pixelStorage.storeRGB(x, y, (byte)R, (byte)G, (byte)B); } */ - public synchronized void getPixel(ColorSink pixelStorage, int width, int height) { + public synchronized void getPixel(JPEGDecoder.ColorSink pixelStorage, int width, int height) { final int scaleX = this.width / width, scaleY = this.height / height; final int componentCount = this.components.length; |