summaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java252
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java139
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java21
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;