diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util')
22 files changed, 1927 insertions, 871 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java index 76d64963f..9e9cc8e44 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java @@ -56,7 +56,7 @@ import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException; class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl { // For efficient rendering of Swing components, in particular when // they overlap one another - private final List<JComponent> lightweights = new ArrayList<JComponent>(); + private final List<JComponent> lightweights = new ArrayList<JComponent>(); private final Map<RepaintManager,RepaintManager> repaintManagers = new IdentityHashMap<RepaintManager,RepaintManager>(); private final Map<JComponent,Rectangle> dirtyRegions = new IdentityHashMap<JComponent,Rectangle>(); @@ -64,34 +64,40 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl { public void display(final ArrayList<GLAutoDrawable> drawables, final boolean ignoreExceptions, final boolean printExceptions) throws UncaughtAnimatorException { - for (int i=0; i<drawables.size(); i++) { - final GLAutoDrawable drawable = drawables.get(i); - if (drawable instanceof JComponent) { - // Lightweight components need a more efficient drawing - // scheme than simply forcing repainting of each one in - // turn since drawing one can force another one to be - // drawn in turn - lightweights.add((JComponent)drawable); - } else { - try { + boolean hasException = false; + for (int i=0; !hasException && i<drawables.size(); i++) { + GLAutoDrawable drawable = null; + boolean catch1 = true; + try { + drawable = drawables.get(i); + catch1 = false; + if (drawable instanceof JComponent) { + // Lightweight components need a more efficient drawing + // scheme than simply forcing repainting of each one in + // turn since drawing one can force another one to be + // drawn in turn + lightweights.add((JComponent)drawable); + } else { drawable.display(); - } catch (final Throwable t) { - if (ignoreExceptions) { - if (printExceptions) { - t.printStackTrace(); - } - } else { - throw new UncaughtAnimatorException(drawable, t); + } + } catch (final Throwable t) { + if( catch1 && t instanceof IndexOutOfBoundsException ) { + // concurrent pulling of GLAutoDrawables .. + hasException = true; + } else if ( ignoreExceptions ) { + if ( printExceptions ) { + t.printStackTrace(); } + } else { + throw new UncaughtAnimatorException(drawable, t); } } } - if (lightweights.size() > 0) { try { SwingUtilities.invokeAndWait(drawWithRepaintManagerRunnable); - } catch (final Exception e) { - e.printStackTrace(); + } catch (final Throwable t) { + t.printStackTrace(); } lightweights.clear(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index 066709316..10b0b6b5a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -40,6 +40,9 @@ package com.jogamp.opengl.util; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.common.util.SourcedInterruptedException; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLException; @@ -174,6 +177,9 @@ public class Animator extends AnimatorBase { try { Animator.this.wait(); } catch (final InterruptedException e) { + caughtException = new UncaughtAnimatorException(null, SourcedInterruptedException.wrap(e)); + stopIssued = true; + break; // end pause loop } if (wasPaused) { // resume from pause -> reset counter @@ -209,8 +215,7 @@ public class Animator extends AnimatorBase { } } catch(final ThreadDeath td) { if(DEBUG) { - System.err.println("Animator caught: "+td.getClass().getName()+": "+td.getMessage()); - td.printStackTrace(); + ExceptionUtils.dumpThrowable("", td); } caughtThreadDeath = td; } @@ -222,8 +227,7 @@ public class Animator extends AnimatorBase { if( null == caughtException ) { caughtException = dre; } else { - System.err.println("Animator.setExclusiveContextThread: caught: "+dre.getMessage()); - dre.printStackTrace(); + ExceptionUtils.dumpThrowable("(setExclusiveContextThread)", dre); } } } @@ -233,8 +237,7 @@ public class Animator extends AnimatorBase { if(DEBUG) { System.err.println("Animator stop on " + animThread.getName() + ": " + toString()); if( null != caughtException ) { - System.err.println("Animator caught: "+caughtException.getMessage()); - caughtException.printStackTrace(); + ExceptionUtils.dumpThrowable("", caughtException); } } stopIssued = false; @@ -291,13 +294,7 @@ public class Animator extends AnimatorBase { runnable = new MainLoop(); } fpsCounter.resetFPSCounter(); - final String threadName = getThreadName()+"-"+baseName; - Thread thread; - if(null==threadGroup) { - thread = new Thread(runnable, threadName); - } else { - thread = new Thread(threadGroup, runnable, threadName); - } + final Thread thread = new InterruptSource.Thread(threadGroup, runnable, getThreadName()+"-"+baseName); thread.setDaemon(false); // force to be non daemon, regardless of parent thread if(DEBUG) { final Thread ct = Thread.currentThread(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java index aafdf63f8..c2da68cd9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java @@ -33,6 +33,7 @@ import jogamp.opengl.FPSCounterImpl; import java.io.PrintStream; import java.util.ArrayList; +import java.util.Locale; import com.jogamp.opengl.GLAnimatorControl; import com.jogamp.opengl.GLAutoDrawable; @@ -40,6 +41,7 @@ import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLProfile; import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.util.InterruptedRuntimeException; /** * Base implementation of GLAnimatorControl<br> @@ -150,7 +152,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { */ protected final synchronized void initImpl(final boolean force) { if( force || null == impl ) { - final String seqSuffix = String.format("#%02d", seqInstanceNumber++); + final String seqSuffix = String.format((Locale)null, "#%02d", seqInstanceNumber++); if( useAWTAnimatorImpl( modeBits ) ) { try { impl = (AnimatorImpl) awtAnimatorImplClazz.newInstance(); @@ -596,7 +598,9 @@ public abstract class AnimatorBase implements GLAnimatorControl { notifyAll(); try { wait(pollPeriod); - } catch (final InterruptedException ie) { } + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } remaining -= System.currentTimeMillis() - t1 ; nok = waitCondition.eval(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java index 6cded29d9..d8c8465d9 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java @@ -48,12 +48,19 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl { public void display(final ArrayList<GLAutoDrawable> drawables, final boolean ignoreExceptions, final boolean printExceptions) throws UncaughtAnimatorException { - for (int i=0; i<drawables.size(); i++) { - final GLAutoDrawable drawable = drawables.get(i); + boolean hasException = false; + for (int i=0; !hasException && i<drawables.size(); i++) { + boolean catch1 = true; + GLAutoDrawable drawable = null; try { + drawable = drawables.get(i); + catch1 = false; drawable.display(); } catch (final Throwable t) { - if (ignoreExceptions) { + if( catch1 && t instanceof IndexOutOfBoundsException ) { + // concurrent pulling of GLAutoDrawables .. + hasException = true; + } else if (ignoreExceptions) { if (printExceptions) { t.printStackTrace(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java index c82f63898..0e3497bd4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java @@ -262,6 +262,8 @@ public class GLPixelBuffer { case GL.GL_UNSIGNED_SHORT_5_5_5_1: pixFmt = PixelFormat.ABGR1555; break; + case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV: + // fall through intended case GL.GL_UNSIGNED_BYTE: pixFmt = PixelFormat.RGBA8888; break; @@ -280,6 +282,8 @@ public class GLPixelBuffer { case GL2GL3.GL_UNSIGNED_INT_8_8_8_8: pixFmt = PixelFormat.ARGB8888; break; + case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV: + // fall through intended case GL.GL_UNSIGNED_BYTE: pixFmt = PixelFormat.BGRA8888; break; diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java index cc3462f99..3fa856a47 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java @@ -245,8 +245,8 @@ public class GLReadBufferUtil { readTexture.updateImage(gl, readTextureData); } else { readTexture.updateSubImage(gl, readTextureData, 0, - 0, 0, // src offset - 0, 0, // dst offset + inX, inY, // dst offset + 0, 0, // src offset width, height); } readPixelBuffer.rewind(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index 196acf9ab..5383f91be 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -920,7 +920,6 @@ public final class PMVMatrix implements GLMatrixFunc { * or {@link #glGetFrustum() Frustum get} methods. * </p> * - * @deprecated Function is exposed for debugging purposes only. * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW * @see #DIRTY_FRUSTUM @@ -941,7 +940,6 @@ public final class PMVMatrix implements GLMatrixFunc { * or {@link #glGetFrustum() Frustum get} methods. * </p> * - * @deprecated Function is exposed for debugging purposes only. * @see #clearAllUpdateRequests() * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java index f28774afa..1dded7882 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java @@ -78,7 +78,8 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect { public static PNGPixelRect read(final InputStream in, final PixelFormat ddestFmt, final boolean destDirectBuffer, final int destMinStrideInBytes, final boolean destIsGLOriented) throws IOException { - final PngReader pngr = new PngReader(new BufferedInputStream(in), null); + final BufferedInputStream bin = (in instanceof BufferedInputStream) ? (BufferedInputStream)in : new BufferedInputStream(in); + final PngReader pngr = new PngReader(bin, null); final ImageInfo imgInfo = pngr.imgInfo; final PngChunkPLTE plte = pngr.getMetadata().getPLTE(); final PngChunkTRNS trns = pngr.getMetadata().getTRNS(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java index 662cf74b7..c2de32372 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -205,22 +205,29 @@ public interface GLMediaPlayer extends TextureSequence { * {@link Uri#scheme Uri scheme} name {@value} for camera input. E.g. <code>camera:/0</code> * for the 1st camera device. * <p> - * The {@link Uri#path Uri path} is being used to identify the camera (<i>ID</i>), + * The {@link Uri#path Uri path} is being used to identify the camera (<i><id></i>), * where the root fwd-slash is being cut-off. * </p> * <p> - * The <i>ID</i> is usually an integer value indexing the camera + * The <i><id></i> is usually an integer value indexing the camera * ranging from [0..<i>max-number</i>]. * </p> * <p> + * The <i><somewhere></i> is usually empty, since it would imply a networking camera protocol. + * </p> + * <p> * The {@link Uri#query Uri query} is used to pass options to the camera * using <i>;</i> as the separator. The latter avoids trouble w/ escaping. * </p> * <pre> - * camera:/<id> - * camera://somewhere/<id> - * camera://somewhere/<id>?width=640;height=480;rate=15 - * camera://somewhere/<id>?size=640x480;rate=15 + * camera:/<id> + * camera:/<id>?width=640;height=480;rate=15 + * camera:/<id>?size=640x480;rate=15 + * camera://<somewhere>/<id> + * camera://<somewhere>/<id>?width=640;height=480;rate=15 + * camera://<somewhere>/<id>?size=640x480;rate=15 + * camera:///<id>?width=640;height=480;rate=15 + * camera:///<id>?size=640x480;rate=15 * </pre> * <pre> * Uri: [scheme:][//authority][path][?query][#fragment] diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java index e6f5aaa2e..38bac06cc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java @@ -40,6 +40,7 @@ package com.jogamp.opengl.util.awt; import com.jogamp.common.nio.Buffers; +import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.*; @@ -915,7 +916,7 @@ public class TextRenderer { // Run this on another thread than the AWT event queue to // make sure the call to Animator.stop() completes before // exiting - new Thread(new Runnable() { + new InterruptSource.Thread(null, new Runnable() { @Override public void run() { anim.stop(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java index e5ef3b268..532db3a7a 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java @@ -148,9 +148,9 @@ public class ShaderCode { switch (type) { case GL2ES2.GL_VERTEX_SHADER: case GL2ES2.GL_FRAGMENT_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: case GL3ES3.GL_COMPUTE_SHADER: break; default: @@ -179,9 +179,9 @@ public class ShaderCode { switch (type) { case GL2ES2.GL_VERTEX_SHADER: case GL2ES2.GL_FRAGMENT_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: case GL3ES3.GL_COMPUTE_SHADER: break; default: @@ -386,11 +386,11 @@ public class ShaderCode { return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE; case GL2ES2.GL_FRAGMENT_SHADER: return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE; - case GL3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: return binary?SUFFIX_GEOMETRY_BINARY:SUFFIX_GEOMETRY_SOURCE; - case GL3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: return binary?SUFFIX_TESS_CONTROL_BINARY:SUFFIX_TESS_CONTROL_SOURCE; - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: return binary?SUFFIX_TESS_EVALUATION_BINARY:SUFFIX_TESS_EVALUATION_SOURCE; case GL3ES3.GL_COMPUTE_SHADER: return binary?SUFFIX_COMPUTE_BINARY:SUFFIX_COMPUTE_SOURCE; @@ -785,11 +785,11 @@ public class ShaderCode { return "VERTEX_SHADER"; case GL2ES2.GL_FRAGMENT_SHADER: return "FRAGMENT_SHADER"; - case GL3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: return "GEOMETRY_SHADER"; - case GL3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: return "TESS_CONTROL_SHADER"; - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: return "TESS_EVALUATION_SHADER"; case GL3ES3.GL_COMPUTE_SHADER: return "COMPUTE_SHADER"; @@ -1098,7 +1098,15 @@ public class ShaderCode { while ((line = reader.readLine()) != null) { lineno++; if (line.startsWith("#include ")) { - final String includeFile = line.substring(9).trim(); + final String includeFile; + { + String s = line.substring(9).trim(); + // Bug 1283: Remove shader include filename quotes if exists at start and end only + if( s.startsWith("\"") && s.endsWith("\"")) { + s = s.substring(1, s.length()-1); + } + includeFile = s; + } URLConnection nextConn = null; // Try relative of current shader location @@ -1106,7 +1114,7 @@ public class ShaderCode { nextConn = IOUtil.openURL(relUri.toURL(), "ShaderCode.relativeOf "); if (nextConn == null) { // Try relative of class and absolute - nextConn = IOUtil.getResource(context, includeFile); + nextConn = IOUtil.getResource(includeFile, context.getClassLoader(), context); } if (nextConn == null) { // Fail @@ -1158,7 +1166,7 @@ public class ShaderCode { * @see IOUtil#getResource(Class, String) */ public static CharSequence readShaderSource(final Class<?> context, final String path, final boolean mutableStringBuilder) throws IOException { - final URLConnection conn = IOUtil.getResource(context, path); + final URLConnection conn = IOUtil.getResource(path, context.getClassLoader(), context); if (conn == null) { return null; } @@ -1204,7 +1212,7 @@ public class ShaderCode { * @see IOUtil#getResource(Class, String) */ public static ByteBuffer readShaderBinary(final Class<?> context, final String path) throws IOException { - final URLConnection conn = IOUtil.getResource(context, path); + final URLConnection conn = IOUtil.getResource(path, context.getClassLoader(), context); if (conn == null) { return null; } @@ -1330,9 +1338,9 @@ public class ShaderCode { // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision! switch ( shaderType ) { case GL2ES2.GL_VERTEX_SHADER: - case GL3.GL_GEOMETRY_SHADER: - case GL3.GL_TESS_CONTROL_SHADER: - case GL3.GL_TESS_EVALUATION_SHADER: + case GL3ES3.GL_GEOMETRY_SHADER: + case GL3ES3.GL_TESS_CONTROL_SHADER: + case GL3ES3.GL_TESS_EVALUATION_SHADER: defaultPrecision = gl3_default_precision_vp_gp; break; case GL2ES2.GL_FRAGMENT_SHADER: defaultPrecision = gl3_default_precision_fp; break; diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java index f5dec1cab..376afb8ce 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java @@ -52,7 +52,7 @@ public abstract class CompileShader { final String justName = basename(resourceName); outName = justName.substring(0, justName.length() - suffixLen) + ShaderCode.getFileSuffix(true, type); - final URL resourceURL = IOUtil.getResource(null, resourceName).getURL(); + final URL resourceURL = IOUtil.getResource(resourceName, this.getClass().getClassLoader(), null).getURL(); final String dirName = dirname(resourceURL.getPath()); outName = dirName + File.separator + "bin" + File.separator + @@ -64,7 +64,7 @@ public abstract class CompileShader { public void processOneShader(final String resourceName, final String outName, final int type) throws IOException, UnsupportedEncodingException, InterruptedException { - final URL resourceURL = IOUtil.getResource(null, resourceName).getURL(); + final URL resourceURL = IOUtil.getResource(resourceName, this.getClass().getClassLoader(), null).getURL(); final String dirName = dirname(resourceURL.getPath()); final CharSequence shader = ShaderCode.readShaderSource(null, resourceName, false); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java deleted file mode 100644 index 12cb13b10..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageIOUtil.java +++ /dev/null @@ -1,445 +0,0 @@ -/** - * Copyright 2014 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 java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Utilities for image input and output - * - */ -public class ImageIOUtil { - - /** - * Determines the file suffix (i.e the image format) of the given InputStream. The given - * InputStream must return true from markSupported() and support a minimum of 32 bytes - * of read-ahead. - * - * @param stream stream to check - * @return the file suffix if any, otherwise <code>null</code> - * @throws java.io.IOException if an I/O exception occurred - */ - public static String getFileSuffix(InputStream stream) throws IOException { - if (stream == null) { - throw new IOException("Stream was null"); - } - if (!(stream instanceof BufferedInputStream)) { - stream = new BufferedInputStream(stream); - } - if (!stream.markSupported()) { - throw new IOException("Can not get non-destructively the image format"); - } - if (stream.available() < 32) { - throw new IOException("Not enough bytes to read in order to get the image format"); - } - try { - stream.mark(32); - final byte[] b = new byte[32]; - stream.read(b); - return getFileSuffix(b); - } finally { - stream.reset(); - } - - } - - /** - * Determines the file suffix (i.e the image format) of the given bytes from the header - * of a file. - * - * @param stream stream to check - * @return the file suffix if any, otherwise <code>null</code> - * @throws java.io.IOException if an I/O exception occurred - */ - public static String getFileSuffix(final byte[] b) { - /** - * http://www.faqs.org/faqs/jpeg-faq/part1/ - * http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=54989 - */ - if ( (b[0] == 0xff && b[1] == 0xd8 /* && b[2] == 0xff */) || - (b[0] == 0x4A && b[1] == 0x46 && b[2] == 0x49 && b[3] == 0x46)/* JFIF */ || - (b[0] == 0x45 && b[1] == 0x78 && b[2] == 0x69 && b[3] == 0x66)/* EXIF */) { - return TextureIO.JPG; - } - /** - * http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html#R.PNG-file-signature - */ - if (b[0] == 0x89 && b[1] == 0x50 && b[2] == 0x4E && b[3] == 0x47 && /* 'P' 'N' 'G', ascii code */ - b[4] == 0x0D && b[5] == 0x0A && b[6] == 0x1A && b[7] == 0x0A) { - return TextureIO.PNG; - } - /** - * Apple Icon Image - * - * 'i' 'c' 'n' 's' ascii code - */ - if (b[0] == 0x69 && b[1] == 0x63 && b[2] == 0x6E && b[3] == 0x73) { - return "icns"; - } - /** - * http://www.w3.org/Graphics/GIF/spec-gif87a.txt http://www.w3.org/Graphics/GIF/spec-gif89a.txt - * - * GIF87A or GIF89A ascii code - */ - if (b[0] == 0x47 && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x38 && (b[4] == 0x37 || b[4] == 0x39) && - b[5] == 0x61) { - return TextureIO.GIF; - } - /** - * http://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htm - * - * BM ascii code - */ - if (b[0] == 0x42 && b[1] == 0x4d) { - return "bmp"; - } - if (b[0] == 0x3A && b[1] == 0xDE && b[2] == 0x68 && b[3] == 0xB1) { - return "dcx"; - } - if (b[0] == 0x0A && b[1] == 0x05 && b[2] == 0x01 && b[3] == 0x08) { - return "pcx"; - } - /** - * http://netpbm.sourceforge.net/doc/ppm.html - */ - if (b[0] == 0x50 && (b[1] == 0x33 /* plain */|| b[1] == 0x36)) { - return TextureIO.PPM; - } - if (b[0] == 0x38 && b[1] == 0x42 && b[2] == 0x50 && b[3] == 0x53 && b[4] == 0x00 && b[5] == 0x01 && - b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x00 && b[9] == 0x00) { - // Adobe PhotoShop - return "psd"; - } - /** - * http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf - * - * intentionally detects only the little endian tiff images ("II" in the spec) - */ - if (b[0] == 0x49 && b[1] == 0x49 && b[2] == 0x2A && b[3] == 0x00) { - return TextureIO.TIFF; - } - /** - * http://paulbourke.net/dataformats/sgirgb/sgiversion.html - * - * "474 saved as a short" 474 = 0x01DA - */ - if (b[0] == 0x01 && b[1] == 0xDA /* && b[2] == 0x01 && b[3] == 0x01 && b[4] == 0x00 && b[5] == 0x03 */) { - return TextureIO.SGI_RGB; - } - /** - * 'D' 'D' 'S' ' ' ascii code - */ - if (b[0] == 0x44 && b[1] == 0x44 && b[2] == 0x53 && b[3] == 0x20) { - return TextureIO.DDS; - } - /** - * http://netpbm.sourceforge.net/doc/pam.html - */ - if (b[0] == 0x50 && b[1] == 0x37) { - return TextureIO.PAM; - } - /** - * http://netpbm.sourceforge.net/doc/pgm.html - */ - if (b[0] == 0x50 && (b[1] == 0x32 /* plain */|| b[1] == 0x35)) { - return "pgm"; - } - /** - * http://netpbm.sourceforge.net/doc/pbm.html - */ - if (b[0] == 0x50 && (b[1] == 0x31 /* plain */|| b[1] == 0x34)) { - return "pbm"; - } - if (b[0] == 0x3D && b[1] == 0x02) { - return "3d2"; - } - if (b[0] == 0x33 && b[1] == 0x44 && b[2] == 0x4D && b[3] == 0x46) { - return "3dmf"; - } - if (b[0] == 0x2A && b[1] == 0x2A && b[2] == 0x54 && b[3] == 0x49 && b[4] == 0x39 && b[5] == 0x32 && - b[6] == 0x2A && b[7] == 0x2A && b[8] == 0x01 && b[9] == 0x00 && b[10] == 0x58 && - b[11] == 0x6E && b[12] == 0x56 && b[13] == 0x69) { - return "92i"; - } - if (b[0] == 0x41 && b[1] == 0x4D && b[2] == 0x46 && b[3] == 0x46) { - return "amff"; - } - if (b[0] == 0x4A && b[1] == 0x47 && (b[2] == 0x03 || b[2] == 0x04) && b[3] == 0x0E && b[4] == 0x00 && - b[5] == 0x00 && b[6] == 0x00) { - return "art"; - } - if (b[0] == 0x73 && b[1] == 0x72 && b[2] == 0x63 && b[3] == 0x64 && b[4] == 0x6F && b[5] == 0x63 && - b[6] == 0x69 && b[7] == 0x64 && b[8] == 0x3A) { - return "cals"; - } - if (b[0] == 0x07 && b[1] == 0x20 && b[2] == 0x4D && b[3] == 0x4D) { - return "cam"; - } - if (b[0] == 0x20 && b[1] == 0x77 && b[2] == 0x00 && b[3] == 0x02) { - return "cbd"; - } - if (b[0] == 0x45 && b[1] == 0x59 && b[2] == 0x45 && b[3] == 0x53) { - return "ce2"; - } - if (b[0] == 0x80 && b[1] == 0x2A && b[2] == 0x5F && b[3] == 0xD7 && b[4] == 0x00 && b[5] == 0x00 && - b[6] == 0x08 && b[7] == 0x00 && b[8] == 0x00 && b[9] == 0x00 && b[10] == 0x04 && - b[11] == 0x00 && b[12] == 0x00 && b[13] == 0x00) { - return "cin"; - } - if (b[0] == 0x43 && b[1] == 0x61 && b[2] == 0x6C && b[3] == 0x69 && b[4] == 0x67 && b[5] == 0x61 && - b[6] == 0x72 && b[7] == 0x69) { - return "cob"; - } - if (b[0] == 0x43 && b[1] == 0x50 && b[2] == 0x54 && b[3] == 0x46 && b[4] == 0x49 && b[5] == 0x4C && - b[6] == 0x45) { - return "cpt"; - } - if (b[0] == 0x43 && b[1] == 0x41 && b[2] == 0x4C && b[3] == 0x41 && b[4] == 0x4D && b[5] == 0x55 && - b[6] == 0x53 && b[7] == 0x43 && b[8] == 0x56 && b[9] == 0x47) { - return "cvg"; - } - if (b[0] == 0x56 && b[1] == 0x69 && b[2] == 0x73 && b[3] == 0x74 && b[4] == 0x61 && b[5] == 0x20 && - b[6] == 0x44 && b[7] == 0x45 && b[8] == 0x4D && b[9] == 0x20 && b[10] == 0x46 && - b[11] == 0x69 && b[12] == 0x6C && b[13] == 0x65) { - return "dem"; - } - if (b[0] == 0x42 && b[1] == 0x4D && b[2] == 0x36) { - return "dib"; - } - if (b[0] == 0x53 && b[1] == 0x44 && b[2] == 0x50 && b[3] == 0x58) { - return "dpx"; - } - if (b[0] == 0x01 && b[1] == 0xFF && b[2] == 0x02 && b[3] == 0x04 && b[4] == 0x03 && b[5] == 0x02) { - return "drw"; - } - if (b[0] == 0x41 && b[1] == 0x43 && b[2] == 0x31 && b[3] == 0x30) { - return "dwg"; - } - if (b[0] == 0x65 && b[1] == 0x02 && b[2] == 0x01 && b[3] == 0x02) { - return "ecw"; - } - if (b[0] == 0x01 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x00 && b[4] == 0x58 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00) { - return "emf"; - } - if (b[0] == 0xD0 && b[1] == 0xCF && b[2] == 0x11 && b[3] == 0xE0 && b[4] == 0xA1 && b[5] == 0xB1 && - b[6] == 0x1A && b[7] == 0xE1 && b[8] == 0x00) { - return "fpx"; - } - if (b[0] == 0x53 && b[1] == 0x49 && b[2] == 0x4D && b[3] == 0x50 && b[4] == 0x4C && b[5] == 0x45 && - b[6] == 0x20 && b[7] == 0x20 && b[8] == 0x3D) { - return "fts"; - } - if (b[0] == 0x48 && b[1] == 0x50 && b[2] == 0x48 && b[3] == 0x50 && b[4] == 0x34 && b[5] == 0x38 && - b[6] == 0x2D && b[7] == 0x45 && b[8] == 0x1E && b[9] == 0x2B) { - return "gro"; - } - if (b[0] == 0x6E && b[1] == 0x63 && b[2] == 0x6F && b[3] == 0x6C && b[4] == 0x73) { - return "hdr"; - } - if (b[0] == 0x35 && b[1] == 0x4B && b[2] == 0x50 && b[3] == 0x35 && b[4] == 0x31 && b[5] == 0x5D && - b[6] == 0x2A && b[7] == 0x67 && b[8] == 0x72 && b[9] == 0x72 && b[10] == 0x80 && - b[11] == 0x83 && b[12] == 0x85 && b[13] == 0x63) { - return "hru"; - } - if (b[0] == 0xEB && b[1] == 0x3C && b[2] == 0x90 && b[3] == 0x2A) { - return "img"; - } - if (b[0] == 0x65 && b[1] == 0x6C && b[2] == 0x6D && b[3] == 0x6F) { - return "infini-d"; - } - if (b[0] == 0x49 && b[1] == 0x57 && b[2] == 0x43 && b[3] == 0x01) { - return "iwc"; - } - if (b[0] == 0x80 && b[1] == 0x3E && b[2] == 0x44 && b[3] == 0x53 && b[4] == 0x43 && b[5] == 0x49 && - b[6] == 0x4D) { - return "j6i"; - } - if (b[0] == 0x4A && b[1] == 0x49 && b[2] == 0x46 && b[3] == 0x39 && b[4] == 0x39 && b[5] == 0x61) { - return "jif"; - } - if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x0C && b[4] == 0x6A && b[5] == 0x50 && - b[6] == 0x20 && b[7] == 0x20 && b[8] == 0x0D && b[9] == 0x0A && b[10] == 0x87 && - b[11] == 0x0A) { - return "jp2"; - } - if (b[0] == 0x4D && b[1] == 0x4D && b[2] == 0x00 && b[3] == 0x2A) { - return "kdc"; - } - if (b[0] == 0x36 && b[1] == 0x34 && b[2] == 0x4C && b[3] == 0x41 && b[4] == 0x4E && b[5] == 0x20 && - b[6] == 0x49 && b[7] == 0x44 && b[8] == 0x42 && b[9] == 0x4C && b[10] == 0x4F && - b[11] == 0x43 && b[12] == 0x4B) { - return "l64"; - } - if (b[0] == 0x46 && b[1] == 0x4F && b[2] == 0x52 && b[3] == 0x4D) { - return "lbm"; - } - if (b[0] == 0x49 && b[1] == 0x49 && b[2] == 0x2A && b[3] == 0x00 && b[4] == 0x08 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00 && b[8] == 0x0E && b[9] == 0x00 && b[10] == 0x00 && - b[11] == 0x01 && b[12] == 0x04 && b[13] == 0x00) { - return "ldf"; - } - if (b[0] == 0x57 && b[1] == 0x56 && b[2] == 0x02 && b[3] == 0x00 && b[4] == 0x47 && b[5] == 0x45 && - b[6] == 0x00 && b[7] == 0x0E) { - return "lwf"; - } - if (b[0] == 0x37 && b[1] == 0x00 && b[2] == 0x00 && b[3] == 0x10 && b[4] == 0x42 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x10 && b[8] == 0x00 && b[9] == 0x00 && b[10] == 0x00 && - b[11] == 0x00 && b[12] == 0x39 && b[13] == 0x64) { - return "mbm"; - } - if (b[0] == 0x4D && b[1] == 0x47 && b[2] == 0x4C) { - return "mgl"; - } - if (b[0] == 0x7B && b[1] == 0x0A && b[2] == 0x20 && b[3] == 0x20 && b[4] == 0x43 && b[5] == 0x72 && - b[6] == 0x65 && b[7] == 0x61 && b[8] == 0x74 && b[9] == 0x65 && b[10] == 0x64) { - return "mif"; - } - if (b[0] == 0x8A && b[1] == 0x4D && b[2] == 0x4E && b[3] == 0x47 && b[4] == 0x0D && b[5] == 0x0A && - b[6] == 0x1A && b[7] == 0x0A) { - return "mng"; - } - if (b[0] == 0x4D && b[1] == 0x50 && b[2] == 0x46) { - return "mpw"; - } - if (b[0] == 0x44 && b[1] == 0x61 && b[2] == 0x6E && b[3] == 0x4D) { - return "msp"; - } - if (b[0] == 0x43 && b[1] == 0x36 && b[2] == 0x34) { - return "n64"; - } - if (b[0] == 0x6E && b[1] == 0x6E && b[2] == 0x0A && b[3] == 0x00 && b[4] == 0x5E && b[5] == 0x00) { - return "ncr"; - } - if (b[0] == 0x6E && b[1] == 0x66 && b[2] == 0x66) { - return "nff"; - } - if (b[0] == 0x4E && b[1] == 0x47 && b[2] == 0x47 && b[3] == 0x00 && b[4] == 0x01 && b[5] == 0x00) { - return "ngg"; - } - if (b[0] == 0x4E && b[1] == 0x4C && b[2] == 0x4D && b[3] == 0x20 && b[4] == 0x01 && b[5] == 0x02 && - b[6] == 0x00) { - return "nlm"; - } - if (b[0] == 0x4E && b[1] == 0x4F && b[2] == 0x4C && b[3] == 0x00 && b[4] == 0x01 && b[5] == 0x00 && - b[6] == 0x06 && b[7] == 0x01 && b[8] == 0x03 && b[9] == 0x00) { - return "nol"; - } - if (b[0] == 0x41 && b[1] == 0x48) { - return "pal"; - } - if (b[0] == 0x50 && b[1] == 0x41 && b[2] == 0x58) { - return "pax"; - } - if (b[0] == 0x63 && b[1] == 0x52 && b[2] == 0x01 && b[3] == 0x01 && b[4] == 0x38 && b[5] == 0x09 && - b[6] == 0x3D && b[7] == 0x00) { - return "pcd"; - } - if (b[0] == 0x1B && b[1] == 0x45 && b[2] == 0x1B && b[3] == 0x26 && b[4] == 0x6C && b[5] == 0x30 && - b[6] == 0x4F && b[7] == 0x1B && b[8] == 0x26 && b[9] == 0x6C && b[10] == 0x30 && - b[11] == 0x45 && b[12] == 0x1B && b[13] == 0x26) { - return "pcl"; - } - if (b[0] == 0x50 && b[1] == 0x49 && b[2] == 0x58 && b[3] == 0x20) { - return "pix"; - } - if (b[0] == 0x50 && b[1] == 0x4F && b[2] == 0x4C && b[3] == 0x20 && b[4] == 0x46 && b[5] == 0x6F && - b[6] == 0x72 && b[7] == 0x6D && b[8] == 0x61 && b[9] == 0x74) { - return "pol"; - } - // Paint Shop Pro - if (b[0] == 0x7E && b[1] == 0x42 && b[2] == 0x4B && b[3] == 0x00) { - return "psp"; - } - if (b[0] == 0x50 && b[1] == 0x61 && b[2] == 0x69 && b[3] == 0x6E && b[4] == 0x74 && b[5] == 0x20 && - b[6] == 0x53 && b[7] == 0x68 && b[8] == 0x6F && b[9] == 0x70 && b[10] == 0x20 && - b[11] == 0x50 && b[12] == 0x72 && b[13] == 0x6F && b[14] == 0x20 && b[15] == 0x49 && - b[16] == 0x6D && b[17] == 0x61 && b[18] == 0x67 && b[19] == 0x65 && b[20] == 0x20 && - b[21] == 0x46 && b[22] == 0x69 && b[23] == 0x6C && b[24] == 0x65) { - return "psp"; - } - if (b[0] == 0x51 && b[1] == 0x4C && b[2] == 0x49 && b[3] == 0x49 && b[4] == 0x46 && b[5] == 0x41 && - b[6] == 0x58) { - return "qfx"; - } - if (b[0] == 0x6D && b[1] == 0x6F && b[2] == 0x6F && b[3] == 0x76) { - return "qtm"; - } - if (b[0] == 0x46 && b[1] == 0x4F && b[2] == 0x52 && b[3] == 0x4D && b[4] == 0x41 && b[5] == 0x54 && - b[6] == 0x3D) { - return "rad"; - } - if (b[0] == 0x59 && b[1] == 0xA6 && b[2] == 0x6A && b[3] == 0x95) { - return "ras"; - } - if (b[0] == 0x52 && b[1] == 0x49 && b[2] == 0x58 && b[3] == 0x33) { - return "rix"; - } - if (b[0] == 0x23 && b[1] == 0x20 && b[2] == 0x24 && b[3] == 0x49 && b[4] == 0x64 && b[5] == 0x3A && - b[6] == 0x20) { - return "sid"; - } - if (b[0] == 0x41 && b[1] == 0x75 && b[2] == 0x74 && b[3] == 0x6F && b[4] == 0x43 && b[5] == 0x41 && - b[6] == 0x44 && b[7] == 0x20 && b[8] == 0x53 && b[9] == 0x6C && b[10] == 0x69 && - b[11] == 0x64 && b[12] == 0x65) { - return "sld"; - } - if (b[0] == 0x53 && b[1] == 0x74 && b[2] == 0x6F && b[3] == 0x72 && b[4] == 0x6D && b[5] == 0x33 && - b[6] == 0x44) { - return "sod"; - } - if (b[0] == 0xFA && b[1] == 0xDE && b[2] == 0xBA && b[3] == 0xBE && b[4] == 0x01 && b[5] == 0x01) { - return "wic"; - } - if (b[0] == 0xD3 && b[1] == 0x23 && b[2] == 0x00 && b[3] == 0x00 && b[4] == 0x03 && b[5] == 0x00 && - b[6] == 0x00 && b[7] == 0x00) { - return "wlm"; - } - if (b[0] == 0xD7 && b[1] == 0xCD && b[2] == 0xC6 && b[3] == 0x9A) { - return "wmf"; - } - if (b[0] == 0xFF && b[1] == 0x57 && b[2] == 0x50 && b[3] == 0x43 && b[4] == 0x10) { - return "wpg"; - } - if (b[0] == 0x23 && b[1] == 0x56 && b[2] == 0x52 && b[3] == 0x4D && b[4] == 0x4C && b[5] == 0x20 && - b[6] == 0x56 && b[7] == 0x32 && b[8] == 0x2E && b[9] == 0x30) { - return "wrl"; - } - if (b[0] == 0x23 && b[1] == 0x64 && b[2] == 0x65 && b[3] == 0x66 && b[4] == 0x69 && b[5] == 0x6E && - b[6] == 0x65) { - return "xbm"; - } - if (b[0] == 0x2F && b[1] == 0x2A && b[2] == 0x20 && b[3] == 0x58 && b[4] == 0x50 && b[5] == 0x4D && - b[6] == 0x20 && b[7] == 0x2A && b[8] == 0x2F) { - return "xpm"; - } - return null; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java index 0f51c2e14..e485e5452 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java @@ -77,7 +77,7 @@ public class ImageSequence implements TextureSequence { } public final void addFrame(final GL gl, final Class<?> context, final String imageResourcePath, final String imageSuffix) throws IOException { - final URLConnection urlConn = IOUtil.getResource(context, imageResourcePath); + final URLConnection urlConn = IOUtil.getResource(imageResourcePath, context.getClassLoader(), context); if(null != urlConn) { final TextureData texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, imageSuffix); final Texture tex = new Texture(getTextureTarget()); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java new file mode 100644 index 000000000..8a3bae554 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageType.java @@ -0,0 +1,1579 @@ +/** + * Copyright 2014 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 java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Image type classification. + * <p> + * Allows to classify the {@link ImageType} of an {@link InputStream} via {@link #ImageType(InputStream)} + * or to simply define one {@link ImageType} via {@link #ImageType(String)}. + * </p> + * @since 2.3.2 + */ +public class ImageType { + /** + * Minimum number of bytes to determine the image data type, i.e. {@value} bytes. + */ + public static final int MAGIC_MAX_SIZE = 25; + + /** + * Constant which can be used as a file suffix to indicate a JPEG stream, value {@value}. + * <ul> + * <li>{@code http://www.faqs.org/faqs/jpeg-faq/part1/}</li> + * <li>{@code http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=54989}</li> + * </ul> + */ + public static final String T_JPG = "jpg"; + + /** + * Constant which can be used as a file suffix to indicate a PNG stream, value {@value}. + * <ul> + * <li>{@code http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html#R.PNG-file-signature}</li> + * </ul> + */ + public static final String T_PNG = "png"; + + /** + * Constant which can be used as a file suffix to indicate an Apple Icon Image stream, value {@value}. + * <p> + * {@code 'i' 'c' 'n' 's' ascii code} + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ICNS = "icns"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Icon stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code https://msdn.microsoft.com/en-us/library/ms997538.aspx}</li> + * </ul> + */ + public static final String T_ICO = "ico"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Cursor stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CUR = "cur"; + + /** + * Constant which can be used as a file suffix to indicate a GIF stream, value {@value}. + * <p> + * {@code GIF87A or GIF89A ascii code} + * </p> + * <ul> + * <li>{@code http://www.w3.org/Graphics/GIF/spec-gif87a.txt http://www.w3.org/Graphics/GIF/spec-gif89a.txt}</li> + * </ul> + */ + public static final String T_GIF = "gif"; + + /** + * Constant which can be used as a file suffix to indicate a GIF stream, value {@value}. + * <p> + * {@code BM ascii code} + * </p> + * <p> + * FIXME: Collision or supertype of {@link #T_DIB}? + * </p> + * <ul> + * <li>{@code http://www.fileformat.info/format/bmp/spec/e27073c25463436f8a64fa789c886d9c/view.htm}</li> + * </ul> + */ + public static final String T_BMP = "bmp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_BMP}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DIB = "dib"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DCX = "dcx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCX = "pcx"; + + /** + * Constant which can be used as a file suffix to indicate a PAM stream, NetPbm magic 6 - binary RGB. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/ppm.html}</li> + * </ul> + */ + public static final String T_PPM = "ppm"; + + /** + * Constant which can be used as a file suffix to indicate a Adobe PhotoShop stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PSD = "psd"; + + /** + * Constant which can be used as a file suffix to indicate a TIFF stream, value {@value}. + * <p> + * Intentionally detects only the little endian tiff images ("II" in the spec). + * </p> + * <p> + * FIXME: Collision or supertype of {@link #T_LDF}? + * </p> + * <ul> + * <li>{@code http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf}</li> + * </ul> + */ + public static final String T_TIFF = "tiff"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_TIFF}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LDF = "ldf"; + + /** + * Constant which can be used as a file suffix to indicate an SGI RGB stream, value {@value}. + * <p> + * "474 saved as a short" 474 = 0x01DA + * </p> + * <ul> + * <li>{@code http://paulbourke.net/dataformats/sgirgb/sgiversion.html}</li> + * </ul> + */ + public static final String T_SGI_RGB = "rgb"; + + /** + * Constant which can be used as a file suffix to indicate a DirectDraw Surface stream, value {@value}. + * <p> + * 'D' 'D' 'S' ' ' ascii code + * </p> + * <ul> + * <li>{@code https://msdn.microsoft.com/en-us/library/windows/desktop/bb943991%28v=vs.85%29.aspx#File_Layout1}</li> + * </ul> + */ + public static final String T_DDS = "dds"; + + /** + * Constant which can be used as a file suffix to indicate a Portable Arbitrary Map stream, NetPbm magic 7 - binary RGB and RGBA. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pam.html}</li> + * </ul> + */ + public static final String T_PAM = "pam"; + + /** + * Constant which can be used as a file suffix to indicate a PGM stream, NetPbm magic 5 - binary grayscale. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pgm.html}</li> + * </ul> + */ + public static final String T_PGM = "pgm"; + + /** + * Constant which can be used as a file suffix to indicate a PGM stream, NetPbm magic 4 - binary monochrome. + * <ul> + * <li>{@code http://netpbm.sourceforge.net/doc/pbm.html}</li> + * </ul> + */ + public static final String T_PBM = "pbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_3D2 = "3d2"; + + /** + * Constant which can be used as a file suffix to indicate an Apple QuickDraw 3D 3DMF stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_3DMF = "3dmf"; + + /** + * Constant which can be used as a file suffix to indicate a Texas Instruments TI-92 Bitmap stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_92I = "92i"; + + /** + * Constant which can be used as a file suffix to indicate an Amiga metafile stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_AMFF = "amff"; + + /** + * Constant which can be used as a file suffix to indicate an America Online Art stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ART = "art"; + + /** + * Constant which can be used as a file suffix to indicate a United States Department of Defence Continuous Acquisition and Life-cycle Support Raster stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://www.fileformat.info/format/cals/egff.htm}</li> + * </ul> + */ + public static final String T_CALS = "cals"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CAM = "cam"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CBD = "cbd"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CE2 = "ce2"; + + /** + * Constant which can be used as a file suffix to indicate a Kodak Cineon System stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://www.cineon.com/ff_draft.php}</li> + * </ul> + */ + public static final String T_CIN = "cin"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_COB = "cob"; + + /** + * Constant which can be used as a file suffix to indicate a Corel Photo Paint stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CPT = "cpt"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_CVG = "cvg"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DEM = "dem"; + + /** + * Constant which can be used as a file suffix to indicate a Digital Picture Exchange stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DPX = "dpx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DRW = "drw"; + + /** + * Constant which can be used as a file suffix to indicate a Autocad drawing stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_DWG = "dwg"; + + /** + * Constant which can be used as a file suffix to indicate a Hexagon Geospatial Enhanced Compression Wavelet stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_ECW = "ecw"; + + /** + * Constant which can be used as a file suffix to indicate a Microsoft Windows Enhanced metafile stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_EMF = "emf"; + + /** + * Constant which can be used as a file suffix to indicate a FlashPix stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_FPX = "fpx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_FTS = "fts"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_GRO = "gro"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_HDR = "hdr"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_HRU = "hru"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_IMG = "img"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_INFINI_D = "infini-d"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_IWC = "iwc"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_J6I = "j6i"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_JIF = "jif"; + + /** + * Constant which can be used as a file suffix to indicate a JPEG-2000 stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_JP2 = "jp2"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_KDC = "kdc"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_L64 = "l64"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or supertype of {@link #T_RAD}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LBM = "lbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * FIXME: Collision or subtype of {@link #T_LBM}? + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RAD = "rad"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_LWF = "lwf"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MBM = "mbm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MGL = "mgl"; + + /** + * Constant which can be used as a file suffix to indicate an Imagemagick stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MIF = "mif"; + + /** + * Constant which can be used as a file suffix to indicate a Multiple-image Network Graphics stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MNG = "mng"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MPW = "mpw"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_MSP = "msp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_N64 = "n64"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NCR = "ncr"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NFF = "nff"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NGG = "ngg"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NLM = "nlm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_NOL = "nol"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PAL = "pal"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PAX = "pax"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCD = "pcd"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PCL = "pcl"; + + /** + * Constant which can be used as a file suffix to indicate a Softimage pic stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code http://paulbourke.net/dataformats/softimagepic/}</li> + * </ul> + */ + public static final String T_PIC = "pic"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PIX = "pix"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_POL = "pol"; + + /** + * Constant which can be used as a file suffix to indicate a PaintShop Pro stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_PSP = "psp"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_QFX = "qfx"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_QTM = "qtm"; + + /** + * Constant which can be used as a file suffix to indicate a Sun Raster stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RAS = "ras"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_RIX = "rix"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SID = "sid"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SLD = "sld"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_SOD = "sod"; + + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WIC = "wic"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WLM = "wlm"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WMF = "wmf"; + + /** + * Constant which can be used as a file suffix to indicate a Wordperfect Graphics vectors stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WPG = "wpg"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_WRL = "wrl"; + + /** + * Constant which can be used as a file suffix to indicate a {@code TBD} stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_XBM = "xbm"; + + /** + * Constant which can be used as a file suffix to indicate a X PixMap stream, value {@value}. + * <p> + * TODO + * </p> + * <ul> + * <li>{@code TODO}</li> + * </ul> + */ + public static final String T_XPM = "xpm"; + + /** + * Constant which can be used as a file suffix to indicate a Targa stream, value {@value}. + * <ul> + * <li>{@code }</li> + * </ul> + */ + public static final String T_TGA = "tga"; + + /** + * The determined unique type, e.g. {@link #T_PNG}, {@link #T_JPG}, etc. + * <p> + * Maybe {@code null} if undetermined, i.e. {@link #isDefined()} returns {@code false}. + * </p> + */ + public final String type; + + /** + * The optionally read header of size {@link #MAGIC_MAX_SIZE} bytes as used to determine the {@link #type}, + * i.e. {@link #ImageType(InputStream)}. + * <p> + * May be {@code null}, if {@link #type} has been determined otherwise, i.e {@link #ImageType(String)}. + * </p> + * <p> + * The header is <i>not</i> being used for {@link #hashCode()} and {@link #equals(Object)}! + * </p> + */ + public final byte[] header; + + private final int hash; + + /** + * Creates instance based on given stream. + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @throws java.io.IOException if an I/O exception occurred + */ + public ImageType(final InputStream stream) throws IOException { + final byte[] _header = new byte[MAGIC_MAX_SIZE]; + type = Util.getFileSuffix(stream, _header); + this.header = _header; + this.hash = null != this.type ? this.type.hashCode() : 0; + } + /** + * Creates instance based on the given type. + * @param type must be one of {@link #T_PNG}, {@link #T_JPG}, etc. + */ + public ImageType(final String type) { + this.header = null; + this.type = type; + this.hash = this.type.hashCode(); + } + /** Returns {@code true} if {@link #type} is determined, i.e. not {@code null}, otherwise {@code false}. */ + public final boolean isDefined() { return null != type; } + + @Override + public final int hashCode() { + return hash; + } + @Override + public boolean equals(final Object o) { + if( o == this ) { + return true; + } else if( o instanceof ImageType ) { + final ImageType t = (ImageType)o; + return this.type.equals(t.type); + } else { + return false; + } + } + @Override + public String toString() { return "ImageType["+type+"]"; } + + /** + * Static utility functions for {@link ImageType} + * to determine the {@link ImageType#type}. + * @since 2.3.2 + */ + public static class Util { + /** + * Determines the file suffix (i.e the image format) of the given InputStream. The given + * InputStream must return true from markSupported() and support a minimum of {@link #MAGIC_MAX_SIZE} bytes + * of read-ahead. + * + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(final InputStream stream) throws IOException { + return getFileSuffix(stream, new byte[MAGIC_MAX_SIZE]); + } + /** + * Determines the file suffix (i.e the image format) of the given InputStream. The given + * InputStream must return true from markSupported() and support a minimum of {@link #MAGIC_MAX_SIZE} bytes + * of read-ahead. + * + * @param stream stream to parse, {@link InputStream#available()} must be ≥ {@link #MAGIC_MAX_SIZE} + * @param b byte array sink, size must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(InputStream stream, final byte[] b) throws IOException { + if (stream == null) { + throw new IOException("Stream was null"); + } + if (!(stream instanceof BufferedInputStream)) { + stream = new BufferedInputStream(stream); + } + if (!stream.markSupported()) { + throw new IOException("Mark not supported"); + } + if (stream.available() < MAGIC_MAX_SIZE) { + throw new IOException("Requires "+MAGIC_MAX_SIZE+" bytes, has "+stream.available()+" bytes"); + } + try { + stream.mark(MAGIC_MAX_SIZE); + final int bytesRead = stream.read(b); + if( MAGIC_MAX_SIZE > bytesRead ) { + throw new IOException("Could not read "+MAGIC_MAX_SIZE+" bytes, read "+bytesRead+" bytes"); + } + return getFileSuffix(b); + } finally { + stream.reset(); + } + + } + + /** + * Determines the file suffix (i.e the image format) of the given bytes from the header + * of a file. + * + * @param b byte array to parse, size must be ≥ {@link #MAGIC_MAX_SIZE} + * @return the file suffix if any, otherwise <code>null</code> + * @throws java.io.IOException if an I/O exception occurred + */ + public static String getFileSuffix(final byte[] b) { + if( b.length < MAGIC_MAX_SIZE ) { + throw new IllegalArgumentException("byte array must be >= "+MAGIC_MAX_SIZE+", has "+b.length); + } + final byte b0 = b[0]; + final byte b1 = b[1]; + final byte b2 = b[2]; + final byte b3 = b[3]; + final byte b4 = b[4]; + final byte b5 = b[5]; + + // T_TGA: NO Signature! + + if (b0 == (byte)0x00) { + if (b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x0C && + b4 == (byte)0x6A && b5 == (byte)0x50 && + b[6] == (byte)0x20 && b[7] == (byte)0x20 && b[8] == (byte)0x0D && b[9] == (byte)0x0A && b[10] == (byte)0x87 && + b[11] == (byte)0x0A) { + return T_JP2; + } + else if (b1 == (byte)0x01) { + return T_ICO; + } + else if (b1 == (byte)0x02) { + return T_CUR; + } + } + else if (b0 == (byte)0x01) { + if (b1 == (byte)0xDA /* && b2 == (byte)0x01 && b3 == (byte)0x01 && b4 == (byte)0x00 && b5 == (byte)0x03 */) { + return T_SGI_RGB; + } + else if (b1 == (byte)0xFF && b2 == (byte)0x02 && b3 == (byte)0x04 && + b4 == (byte)0x03 && b5 == (byte)0x02) { + return T_DRW; + } + else if (b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x00 && + b4 == (byte)0x58 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00) { + return T_EMF; + } + } + else if (b0 == (byte)0x07 && b1 == (byte)0x20 && b2 == (byte)0x4D && b3 == (byte)0x4D) { + return T_CAM; + } + else if (b0 == (byte)0x0A && b1 == (byte)0x05 && b2 == (byte)0x01 && b3 == (byte)0x08) { + return T_PCX; + } + else if (b0 == (byte)0x1B && b1 == (byte)0x45 && b2 == (byte)0x1B && b3 == (byte)0x26 && + b4 == (byte)0x6C && b5 == (byte)0x30 && + b[6] == (byte)0x4F && b[7] == (byte)0x1B && b[8] == (byte)0x26 && b[9] == (byte)0x6C && b[10] == (byte)0x30 && + b[11] == (byte)0x45 && b[12] == (byte)0x1B && b[13] == (byte)0x26) { + return T_PCL; + } + else if (b0 == (byte)0x20 && b1 == (byte)0x77 && b2 == (byte)0x00 && b3 == (byte)0x02) { + return T_CBD; + } + else if (b0 == (byte)0x23) { + if (b1 == (byte)0x20 && b2 == (byte)0x24 && b3 == (byte)0x49 && + b4 == (byte)0x64 && b5 == (byte)0x3A && + b[6] == (byte)0x20) { + return T_SID; + } + else if (b1 == (byte)0x56 && b2 == (byte)0x52 && b3 == (byte)0x4D && + b4 == (byte)0x4C && b5 == (byte)0x20 && + b[6] == (byte)0x56 && b[7] == (byte)0x32 && b[8] == (byte)0x2E && b[9] == (byte)0x30) { + return T_WRL; + } + else if (b1 == (byte)0x64 && b2 == (byte)0x65 && b3 == (byte)0x66 && + b4 == (byte)0x69 && b5 == (byte)0x6E && + b[6] == (byte)0x65) { + return T_XBM; + } + } + else if (b0 == (byte)0x2A && b1 == (byte)0x2A && b2 == (byte)0x54 && b3 == (byte)0x49 && + b4 == (byte)0x39 && b5 == (byte)0x32 && + b[6] == (byte)0x2A && b[7] == (byte)0x2A && b[8] == (byte)0x01 && b[9] == (byte)0x00 && b[10] == (byte)0x58 && + b[11] == (byte)0x6E && b[12] == (byte)0x56 && b[13] == (byte)0x69) { + return T_92I; + } + else if (b0 == (byte)0x2F && b1 == (byte)0x2A && b2 == (byte)0x20 && b3 == (byte)0x58 && + b4 == (byte)0x50 && b5 == (byte)0x4D && + b[6] == (byte)0x20 && b[7] == (byte)0x2A && b[8] == (byte)0x2F) { + return T_XPM; + } + else if (b0 == (byte)0x33 && b1 == (byte)0x44 && b2 == (byte)0x4D && b3 == (byte)0x46) { + return T_3DMF; + } + else if (b0 == (byte)0x35 && b1 == (byte)0x4B && b2 == (byte)0x50 && b3 == (byte)0x35 && + b4 == (byte)0x31 && b5 == (byte)0x5D && + b[6] == (byte)0x2A && b[7] == (byte)0x67 && b[8] == (byte)0x72 && b[9] == (byte)0x72 && b[10] == (byte)0x80 && + b[11] == (byte)0x83 && b[12] == (byte)0x85 && b[13] == (byte)0x63) { + return T_HRU; + } + else if (b0 == (byte)0x36 && b1 == (byte)0x34 && b2 == (byte)0x4C && b3 == (byte)0x41 && + b4 == (byte)0x4E && b5 == (byte)0x20 && + b[6] == (byte)0x49 && b[7] == (byte)0x44 && b[8] == (byte)0x42 && b[9] == (byte)0x4C && b[10] == (byte)0x4F && + b[11] == (byte)0x43 && b[12] == (byte)0x4B) { + return T_L64; + } + else if (b0 == (byte)0x37 && b1 == (byte)0x00 && b2 == (byte)0x00 && b3 == (byte)0x10 && + b4 == (byte)0x42 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x10 && b[8] == (byte)0x00 && b[9] == (byte)0x00 && b[10] == (byte)0x00 && + b[11] == (byte)0x00 && b[12] == (byte)0x39 && b[13] == (byte)0x64) { + return T_MBM; + } + else if (b0 == (byte)0x38 && b1 == (byte)0x42 && b2 == (byte)0x50 && b3 == (byte)0x53 && + b4 == (byte)0x00 && b5 == (byte)0x01 && + b[6] == (byte)0x00 && b[7] == (byte)0x00 && b[8] == (byte)0x00 && b[9] == (byte)0x00) { + return T_PSD; + } + else if (b0 == (byte)0x3A && b1 == (byte)0xDE && b2 == (byte)0x68 && b3 == (byte)0xB1) { + return T_DCX; + } + else if (b0 == (byte)0x3D && b1 == (byte)0x02) { + return T_3D2; + } + else if (b0 == (byte)0x41) { + if (b1 == (byte)0x43 && b2 == (byte)0x31 && b3 == (byte)0x30) { + return T_DWG; + } + else if (b1 == (byte)0x48) { + return T_PAL; + } + else if (b1 == (byte)0x4D && b2 == (byte)0x46 && b3 == (byte)0x46) { + return T_AMFF; + } + else if (b1 == (byte)0x75 && b2 == (byte)0x74 && b3 == (byte)0x6F && + b4 == (byte)0x43 && b5 == (byte)0x41 && + b[6] == (byte)0x44 && b[7] == (byte)0x20 && b[8] == (byte)0x53 && b[9] == (byte)0x6C && b[10] == (byte)0x69 && + b[11] == (byte)0x64 && b[12] == (byte)0x65) { + return T_SLD; + } + } + else if (b0 == (byte)0x42 && b1 == (byte)0x4D) { + if (b2 == (byte)0x36) { + // FIXME: Collision or subtype of T_BMP? + return T_DIB; + } else { + return T_BMP; + } + } + else if (b0 == (byte)0x43) { + if (b1 == (byte)0x36 && b2 == (byte)0x34) { + return T_N64; + } + else if (b1 == (byte)0x41 && b2 == (byte)0x4C && b3 == (byte)0x41 && + b4 == (byte)0x4D && b5 == (byte)0x55 && + b[6] == (byte)0x53 && b[7] == (byte)0x43 && b[8] == (byte)0x56 && b[9] == (byte)0x47) { + return T_CVG; + } + else if (b1 == (byte)0x50 && b2 == (byte)0x54 && b3 == (byte)0x46 && + b4 == (byte)0x49 && b5 == (byte)0x4C && + b[6] == (byte)0x45) { + return T_CPT; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x6C && b3 == (byte)0x69 && + b4 == (byte)0x67 && b5 == (byte)0x61 && + b[6] == (byte)0x72 && b[7] == (byte)0x69) { + return T_COB; + } + } + else if (b0 == (byte)0x44) { + if (b1 == (byte)0x44 && b2 == (byte)0x53 && b3 == (byte)0x20) { + return T_DDS; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x6E && b3 == (byte)0x4D) { + return T_MSP; + } + } + else if (b0 == (byte)0x45) { + if (b1 == (byte)0x59 && b2 == (byte)0x45 && b3 == (byte)0x53) { + return T_CE2; + } + else if (b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) { /* EXIF */ + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + } + else if (b0 == (byte)0x46 && b1 == (byte)0x4F && b2 == (byte)0x52 && b3 == (byte)0x4D) { + if (b4 == (byte)0x41 && b5 == (byte)0x54 && b[6] == (byte)0x3D) { + // FIXME: Collision or subtype of T_LBM? + return T_RAD; + } else { + return T_LBM; + } + } + else if (b0 == (byte)0x47 && b1 == (byte)0x49 && b2 == (byte)0x46 && b3 == (byte)0x38 && + (b4 == (byte)0x37 || b4 == (byte)0x39) && b5 == (byte)0x61) { + return T_GIF; + } + else if (b0 == (byte)0x48 && b1 == (byte)0x50 && b2 == (byte)0x48 && b3 == (byte)0x50 && + b4 == (byte)0x34 && b5 == (byte)0x38 && + b[6] == (byte)0x2D && b[7] == (byte)0x45 && b[8] == (byte)0x1E && b[9] == (byte)0x2B) { + return T_GRO; + } + else if (b0 == (byte)0x49) { + if (b1 == (byte)0x49 && b2 == (byte)0x2A && b3 == (byte)0x00) { + if (b4 == (byte)0x08 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00 && b[8] == (byte)0x0E && b[9] == (byte)0x00 && b[10] == (byte)0x00 && + b[11] == (byte)0x01 && b[12] == (byte)0x04 && b[13] == (byte)0x00) { + // FIXME: Collision or subtype of T_TIFF? + return T_LDF; + } else { + return T_TIFF; + } + } + else if (b1 == (byte)0x57 && b2 == (byte)0x43 && b3 == (byte)0x01) { + return T_IWC; + } + } + else if (b0 == (byte)0x4A) { + if (b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) { /* JFIF */ + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + else if (b1 == (byte)0x47 && (b2 == (byte)0x03 || b2 == (byte)0x04) && b3 == (byte)0x0E && + b4 == (byte)0x00 && b5 == (byte)0x00 && + b[6] == (byte)0x00) { + return T_ART; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x46 && b3 == (byte)0x39 && + b4 == (byte)0x39 && b5 == (byte)0x61) { + return T_JIF; + } + } + else if (b0 == (byte)0x4D) { + if (b1 == (byte)0x47 && b2 == (byte)0x4C) { + return T_MGL; + } + else if (b1 == (byte)0x4D && b2 == (byte)0x00 && b3 == (byte)0x2A) { + return T_KDC; + } + else if (b1 == (byte)0x50 && b2 == (byte)0x46) { + return T_MPW; + } + } + else if (b0 == (byte)0x4E) { + if (b1 == (byte)0x47 && b2 == (byte)0x47 && b3 == (byte)0x00 && + b4 == (byte)0x01 && b5 == (byte)0x00) { + return T_NGG; + } + else if (b1 == (byte)0x4C && b2 == (byte)0x4D && b3 == (byte)0x20 && + b4 == (byte)0x01 && b5 == (byte)0x02 && + b[6] == (byte)0x00) { + return T_NLM; + } + else if (b1 == (byte)0x4F && b2 == (byte)0x4C && b3 == (byte)0x00 && + b4 == (byte)0x01 && b5 == (byte)0x00 && + b[6] == (byte)0x06 && b[7] == (byte)0x01 && b[8] == (byte)0x03 && b[9] == (byte)0x00) { + return T_NOL; + } + } + else if (b0 == (byte)0x50) { + if (b1 == (byte)0x31 /* plain */|| b1 == (byte)0x34) { + return T_PBM; + } + else if (b1 == (byte)0x32 /* plain */|| b1 == (byte)0x35) { + return T_PGM; + } + else if (b1 == (byte)0x33 /* plain */|| b1 == (byte)0x36) { + return T_PPM; + } + else if (b1 == (byte)0x37) { + return T_PAM; + } + else if (b1 == (byte)0x41 && b2 == (byte)0x58) { + return T_PAX; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x58 && b3 == (byte)0x20) { + return T_PIX; + } + else if (b1 == (byte)0x4F && b2 == (byte)0x4C && b3 == (byte)0x20 && + b4 == (byte)0x46 && b5 == (byte)0x6F && + b[6] == (byte)0x72 && b[7] == (byte)0x6D && b[8] == (byte)0x61 && b[9] == (byte)0x74) { + return T_POL; + } + else if (b1 == (byte)0x61 && b2 == (byte)0x69 && b3 == (byte)0x6E && + b4 == (byte)0x74 && b5 == (byte)0x20 && + b[6] == (byte)0x53 && b[7] == (byte)0x68 && b[8] == (byte)0x6F && b[9] == (byte)0x70 && b[10] == (byte)0x20 && + b[11] == (byte)0x50 && b[12] == (byte)0x72 && b[13] == (byte)0x6F && b[14] == (byte)0x20 && b[15] == (byte)0x49 && + b[16] == (byte)0x6D && b[17] == (byte)0x61 && b[18] == (byte)0x67 && b[19] == (byte)0x65 && b[20] == (byte)0x20 && + b[21] == (byte)0x46 && b[22] == (byte)0x69 && b[23] == (byte)0x6C && b[24] == (byte)0x65) { + return T_PSP; + } + } + else if (b0 == (byte)0x51 && b1 == (byte)0x4C && b2 == (byte)0x49 && b3 == (byte)0x49 && + b4 == (byte)0x46 && b5 == (byte)0x41 && + b[6] == (byte)0x58) { + return T_QFX; + } + else if (b0 == (byte)0x52 && b1 == (byte)0x49 && b2 == (byte)0x58 && b3 == (byte)0x33) { + return T_RIX; + } + else if (b0 == (byte)0x53) { + if (b1 == (byte)0x44 && b2 == (byte)0x50 && b3 == (byte)0x58) { + return T_DPX; + } + else if (b1 == (byte)0x49 && b2 == (byte)0x4D && b3 == (byte)0x50 && + b4 == (byte)0x4C && b5 == (byte)0x45 && + b[6] == (byte)0x20 && b[7] == (byte)0x20 && b[8] == (byte)0x3D) { + return T_FTS; + } + else if (b1 == (byte)0x74 && b2 == (byte)0x6F && b3 == (byte)0x72 && + b4 == (byte)0x6D && b5 == (byte)0x33 && + b[6] == (byte)0x44) { + return T_SOD; + } + else if (b1 == (byte)0x80 && b2 == (byte)0xf6 && b3 == (byte)0x34) { + return T_PIC; + } + } + else if (b0 == (byte)0x56 && b1 == (byte)0x69 && b2 == (byte)0x73 && b3 == (byte)0x74 && + b4 == (byte)0x61 && b5 == (byte)0x20 && + b[6] == (byte)0x44 && b[7] == (byte)0x45 && b[8] == (byte)0x4D && b[9] == (byte)0x20 && b[10] == (byte)0x46 && + b[11] == (byte)0x69 && b[12] == (byte)0x6C && b[13] == (byte)0x65) { + return T_DEM; + } + else if (b0 == (byte)0x57 && b1 == (byte)0x56 && b2 == (byte)0x02 && b3 == (byte)0x00 && + b4 == (byte)0x47 && b5 == (byte)0x45 && + b[6] == (byte)0x00 && b[7] == (byte)0x0E) { + return T_LWF; + } + else if (b0 == (byte)0x59 && b1 == (byte)0xA6 && b2 == (byte)0x6A && b3 == (byte)0x95) { + return T_RAS; + } + else if (b0 == (byte)0x63 && b1 == (byte)0x52 && b2 == (byte)0x01 && b3 == (byte)0x01 && + b4 == (byte)0x38 && b5 == (byte)0x09 && + b[6] == (byte)0x3D && b[7] == (byte)0x00) { + return T_PCD; + } + else if (b0 == (byte)0x65) { + if (b1 == (byte)0x02 && b2 == (byte)0x01 && b3 == (byte)0x02) { + return T_ECW; + } + else if (b1 == (byte)0x6C && b2 == (byte)0x6D && b3 == (byte)0x6F) { + return T_INFINI_D; + } + } + else if (b0 == (byte)0x69 && b1 == (byte)0x63 && b2 == (byte)0x6E && b3 == (byte)0x73) { + return T_ICNS; + } + else if (b0 == (byte)0x6D && b1 == (byte)0x6F && b2 == (byte)0x6F && b3 == (byte)0x76) { + return T_QTM; + } + else if (b0 == (byte)0x6E) { + if (b1 == (byte)0x63 && b2 == (byte)0x6F && b3 == (byte)0x6C && + b4 == (byte)0x73) { + return T_HDR; + } + else if (b1 == (byte)0x66 && b2 == (byte)0x66) { + return T_NFF; + } + else if (b1 == (byte)0x6E && b2 == (byte)0x0A && b3 == (byte)0x00 && + b4 == (byte)0x5E && b5 == (byte)0x00) { + return T_NCR; + } + } + else if (b0 == (byte)0x73 && b1 == (byte)0x72 && b2 == (byte)0x63 && b3 == (byte)0x64 && + b4 == (byte)0x6F && b5 == (byte)0x63 && + b[6] == (byte)0x69 && b[7] == (byte)0x64 && b[8] == (byte)0x3A) { + return T_CALS; + } + else if (b0 == (byte)0x7B && b1 == (byte)0x0A && b2 == (byte)0x20 && b3 == (byte)0x20 && + b4 == (byte)0x43 && b5 == (byte)0x72 && + b[6] == (byte)0x65 && b[7] == (byte)0x61 && b[8] == (byte)0x74 && b[9] == (byte)0x65 && b[10] == (byte)0x64) { + return T_MIF; + } + else if (b0 == (byte)0x7E && b1 == (byte)0x42 && b2 == (byte)0x4B && b3 == (byte)0x00) { + return T_PSP; + } + else if (b0 == (byte)0x80) { + if (b1 == (byte)0x2A && b2 == (byte)0x5F && b3 == (byte)0xD7 && + b4 == (byte)0x00 && b5 == (byte)0x00 && + b[6] == (byte)0x08 && b[7] == (byte)0x00 && b[8] == (byte)0x00 && b[9] == (byte)0x00 && b[10] == (byte)0x04 && + b[11] == (byte)0x00 && b[12] == (byte)0x00 && b[13] == (byte)0x00) { + return T_CIN; + } + else if (b1 == (byte)0x3E && b2 == (byte)0x44 && b3 == (byte)0x53 && + b4 == (byte)0x43 && b5 == (byte)0x49 && + b[6] == (byte)0x4D) { + return T_J6I; + } + } + else if (b0 == (byte)0x89 && b1 == (byte)0x50 && b2 == (byte)0x4E && b3 == (byte)0x47 && /* 'P' 'N' 'G', ascii code */ + b4 == (byte)0x0D && b5 == (byte)0x0A && b[6] == (byte)0x1A && b[7] == (byte)0x0A) { + // -119, 80, 78, 71, 13, 10, 26, 10 + return T_PNG; + } + else if (b0 == (byte)0x8A && b1 == (byte)0x4D && b2 == (byte)0x4E && b3 == (byte)0x47 && + b4 == (byte)0x0D && b5 == (byte)0x0A && + b[6] == (byte)0x1A && b[7] == (byte)0x0A) { + return T_MNG; + } + else if (b0 == (byte)0xD0 && b1 == (byte)0xCF && b2 == (byte)0x11 && b3 == (byte)0xE0 && + b4 == (byte)0xA1 && b5 == (byte)0xB1 && + b[6] == (byte)0x1A && b[7] == (byte)0xE1 && b[8] == (byte)0x00) { + return T_FPX; + } + else if (b0 == (byte)0xD3 && b1 == (byte)0x23 && b2 == (byte)0x00 && b3 == (byte)0x00 && + b4 == (byte)0x03 && b5 == (byte)0x00 && + b[6] == (byte)0x00 && b[7] == (byte)0x00) { + return T_WLM; + } + else if (b0 == (byte)0xD7 && b1 == (byte)0xCD && b2 == (byte)0xC6 && b3 == (byte)0x9A) { + return T_WMF; + } + else if (b0 == (byte)0xEB && b1 == (byte)0x3C && b2 == (byte)0x90 && b3 == (byte)0x2A) { + return T_IMG; + } + else if (b0 == (byte)0xFA && b1 == (byte)0xDE && b2 == (byte)0xBA && b3 == (byte)0xBE && + b4 == (byte)0x01 && b5 == (byte)0x01) { + return T_WIC; + } + else if (b0 == (byte)0xFF) { + if (b1 == (byte)0xD8 /* && b2 == (byte)0xff */) { + /** + * (b0 == (byte)0x45 && b1 == (byte)0x78 && b2 == (byte)0x69 && b3 == (byte)0x66) || // EXIF + * (b0 == (byte)0x4A && b1 == (byte)0x46 && b2 == (byte)0x49 && b3 == (byte)0x46) || // JFIF + * (b0 == (byte)0xff && b1 == (byte)0xd8 ) // && b2 == (byte)0xff + */ + return T_JPG; + } + else if (b1 == (byte)0x57 && b2 == (byte)0x50 && b3 == (byte)0x43 && b4 == (byte)0x10) { + return T_WPG; + } + } + return null; + } + } +} 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 18a7527b6..bdaa2d792 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -163,8 +163,10 @@ import com.jogamp.opengl.util.texture.spi.*; * @author Chris Campbell, Kenneth Russell, et.al. */ public class Texture { - /** The GL target type. */ + /** The GL target type for this texture. */ private int target; + /** The image GL target type for this texture, or its sub-components if cubemap. */ + private int imageTarget; /** The GL texture ID. */ private int texID; /** The width of the texture. */ @@ -190,7 +192,8 @@ public class Texture { @Override public String toString() { - return "Texture[target 0x"+Integer.toHexString(target)+", name "+texID+", "+ + final String targetS = target == imageTarget ? Integer.toHexString(target) : Integer.toHexString(target) + " - image "+Integer.toHexString(imageTarget); + return "Texture[target "+targetS+", name "+texID+", "+ imgWidth+"/"+texWidth+" x "+imgHeight+"/"+texHeight+", y-flip "+mustFlipVertically+ ", "+estimatedMemorySize+" bytes]"; } @@ -206,7 +209,9 @@ public class Texture { private static final boolean disableTexRect = Debug.isPropertyDefined("jogl.texture.notexrect", true); public Texture(final GL gl, final TextureData data) throws GLException { - texID = 0; + this.texID = 0; + this.target = 0; + this.imageTarget = 0; updateImage(gl, data); } @@ -217,8 +222,9 @@ public class Texture { * GL2.GL_TEXTURE_RECTANGLE */ public Texture(final int target) { - texID = 0; + this.texID = 0; this.target = target; + this.imageTarget = target; } /** @@ -250,11 +256,14 @@ public class Texture { final boolean mustFlipVertically) { this.texID = textureID; this.target = target; + this.imageTarget = target; this.mustFlipVertically = mustFlipVertically; this.texWidth = texWidth; this.texHeight = texHeight; - aspectRatio = (float) imgWidth / (float) imgHeight; - setImageSize(imgWidth, imgHeight, target); + this.aspectRatio = (float) imgWidth / (float) imgHeight; + this.imgWidth = imgWidth; + this.imgHeight = imgHeight; + this.updateTexCoords(); } /** @@ -344,8 +353,6 @@ public class Texture { /** * Returns the OpenGL "target" of this texture. - * - * @return the OpenGL target of this texture * @see com.jogamp.opengl.GL#GL_TEXTURE_2D * @see com.jogamp.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB */ @@ -354,6 +361,15 @@ public class Texture { } /** + * Returns the image OpenGL "target" of this texture, or its sub-components if cubemap. + * @see com.jogamp.opengl.GL#GL_TEXTURE_2D + * @see com.jogamp.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB + */ + public int getImageTarget() { + return imageTarget; + } + + /** * Returns the width of the allocated OpenGL texture in pixels. * Note that the texture width will be greater than or equal to the * width of the image contained within. @@ -438,7 +454,7 @@ public class Texture { * @return the texture coordinates corresponding to the specified sub-image */ public TextureCoords getSubImageTexCoords(final int x1, final int y1, final int x2, final int y2) { - if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if (GL2.GL_TEXTURE_RECTANGLE_ARB == imageTarget) { if (mustFlipVertically) { return new TextureCoords(x1, texHeight - y1, x2, texHeight - y2); } else { @@ -616,17 +632,17 @@ public class Texture { texHeight = nextPowerOfTwo(imgHeight); texTarget = GL.GL_TEXTURE_2D; } - texParamTarget = texTarget; - setImageSize(imgWidth, imgHeight, texTarget); + imageTarget = texTarget; + updateTexCoords(); if (targetOverride != 0) { // Allow user to override auto detection and skip bind step (for // cubemap construction) - texTarget = targetOverride; if (this.target == 0) { throw new GLException("Override of target failed; no target specified yet"); } + texTarget = targetOverride; texParamTarget = this.target; gl.glBindTexture(texParamTarget, texID); } else { @@ -977,17 +993,8 @@ public class Texture { return ret; } - /** - * Updates the actual image dimensions; usually only called from - * <code>updateImage</code>. - */ - private void setImageSize(final int width, final int height, final int target) { - imgWidth = width; - imgHeight = height; - updateTexCoords(); - } private void updateTexCoords() { - if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if ( GL2.GL_TEXTURE_RECTANGLE_ARB == imageTarget ) { if (mustFlipVertically) { coords = new TextureCoords(0, imgHeight, imgWidth, 0); } else { 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 615d8c24f..5799f95a6 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -83,6 +83,9 @@ public class TextureData { protected GLProfile glProfile; protected ColorSpace pixelCS = ColorSpace.RGB; + // TODO: final, and set via ctor for 2.4.X + /* pp */ ImageType srcImageType; + /** * Constructs a new TextureData object with the specified parameters * and data contained in the given Buffer. The optional Flusher can @@ -341,6 +344,14 @@ public class TextureData { /** Used only by subclasses */ protected TextureData(final GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; } + /** + * Returns the source {@link ImageType} if applicable and known, otherwise {@code null}. + * @since 2.3.2 + */ + public final ImageType getSourceImageType() { + return srcImageType; + } + /** Returns the width in pixels of the texture data. */ public int getWidth() { return width; } /** Returns the height in pixels of the texture data. */ @@ -501,8 +512,9 @@ public class TextureData { @Override public String toString() { + final String optImageType = null != srcImageType ? ", "+srcImageType : ""; return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+ - pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; + pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength+optImageType; } //---------------------------------------------------------------------- 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 80b195642..2ac7c796d 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -52,8 +52,10 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import com.jogamp.nativewindow.util.Dimension; import com.jogamp.nativewindow.util.DimensionImmutable; @@ -72,6 +74,7 @@ import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.util.GLPixelStorageModes; import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.ImageType; import com.jogamp.opengl.util.texture.spi.DDSImage; import com.jogamp.opengl.util.texture.spi.JPEGImage; import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter; @@ -134,44 +137,60 @@ import com.jogamp.opengl.util.texture.spi.TextureWriter; public class TextureIO { /** Constant which can be used as a file suffix to indicate a - DirectDraw Surface file. */ - public static final String DDS = "dds"; + DirectDraw Surface file, value {@value}. + <p>Alias for {@link ImageType#T_DDS}.</p> + */ + public static final String DDS = ImageType.T_DDS; - /** Constant which can be used as a file suffix to indicate an SGI - RGB file. */ + /** + * Constant which can be used as a file suffix to indicate an SGI RGB file, value {@value}. + * <p> + * Same semantics as {@link ImageType#SGI_RGB} and {@link #SGI_RGB}. + * </p> + */ public static final String SGI = "sgi"; - /** Constant which can be used as a file suffix to indicate an SGI - RGB file. */ - public static final String SGI_RGB = "rgb"; + /** Constant which can be used as a file suffix to indicate an SGI RGB file, value {@value}. + <p>Alias for {@link ImageType#T_SGI_RGB}. </p> + */ + public static final String SGI_RGB = ImageType.T_SGI_RGB; - /** Constant which can be used as a file suffix to indicate a GIF - file. */ - public static final String GIF = "gif"; + /** Constant which can be used as a file suffix to indicate a GIF file, value {@value}. + <p>Alias for {@link ImageType#T_GIF}.</p> + */ + public static final String GIF = ImageType.T_GIF; - /** Constant which can be used as a file suffix to indicate a JPEG - file. */ - public static final String JPG = "jpg"; + /** Constant which can be used as a file suffix to indicate a JPEG file, value {@value}. + <p>Alias for {@link ImageType#T_JPG}.</p> + */ + public static final String JPG = ImageType.T_JPG; - /** Constant which can be used as a file suffix to indicate a PNG - file. */ - public static final String PNG = "png"; + /** Constant which can be used as a file suffix to indicate a PNG file, value {@value}. + <p>Alias for {@link ImageType#T_PNG}.</p> + */ + public static final String PNG = ImageType.T_PNG; - /** Constant which can be used as a file suffix to indicate a Targa - file. */ - public static final String TGA = "tga"; + /** Constant which can be used as a file suffix to indicate a Targa file, value {@value}. + <p>Alias for {@link ImageType#T_TGA}.</p> + */ + public static final String TGA = ImageType.T_TGA; - /** Constant which can be used as a file suffix to indicate a TIFF - file. */ - public static final String TIFF = "tiff"; + /** Constant which can be used as a file suffix to indicate a TIFF file, value {@value}. + <p>Alias for {@link ImageType#T_TIFF}.</p> + */ + public static final String TIFF = ImageType.T_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"; + file, NetPbm magic 7 - binary RGB and RGBA. Write support only, value {@value}. + <p>Alias for {@link ImageType#T_PAM}.</p> + */ + public static final String PAM = ImageType.T_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"; + file, NetPbm magic 6 - binary RGB. Write support only, value {@value}. + <p>Alias for {@link ImageType#T_PPM}.</p> + */ + public static final String PPM = ImageType.T_PPM; private static final boolean DEBUG = Debug.debug("TextureIO"); @@ -677,16 +696,27 @@ public class TextureIO { // /** - * Adds a TextureProvider to support reading of a new file format. + * Adds a {@link TextureProvider} to support reading of a new file format. * <p> * The last provider added, will be the first provider to be tested. * </p> + * <p> + * The {@link TextureProvider} is being mapped to its supporting {@link ImageType}s + * allowing an O(1) association, if {@link TextureProvider#} + * </p> */ public static void addTextureProvider(final 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 // more optimal provider textureProviders.add(0, provider); + + final ImageType[] imageTypes = provider.getImageTypes(); + if( null != imageTypes ) { + for(int i=0; i<imageTypes.length; i++) { + imageType2TextureProvider.put(imageTypes[i], provider); + } + } } /** @@ -736,6 +766,7 @@ public class TextureIO { // private static List<TextureProvider> textureProviders = new ArrayList<TextureProvider>(); + private static Map<ImageType,TextureProvider> imageType2TextureProvider = new HashMap<ImageType,TextureProvider>(); private static List<TextureWriter> textureWriters = new ArrayList<TextureWriter>(); static { @@ -787,32 +818,6 @@ public class TextureIO { } // Implementation methods - private static TextureData newTextureDataImpl(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - String fileSuffix) throws IOException { - if (file == null) { - throw new IOException("File was null"); - } - - fileSuffix = toLowerCase(fileSuffix); - - for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { - final TextureProvider provider = iter.next(); - final TextureData data = provider.newTextureData(glp, file, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); - if (data != null) { - return data; - } - } - - throw new IOException("No suitable reader for given file "+file.getAbsolutePath()); - } - private static TextureData newTextureDataImpl(final GLProfile glp, InputStream stream, final int internalFormat, final int pixelFormat, @@ -822,70 +827,97 @@ public class TextureIO { throw new IOException("Stream was null"); } - fileSuffix = toLowerCase(fileSuffix); - // Note: use of BufferedInputStream works around 4764639/4892246 if (!(stream instanceof BufferedInputStream)) { stream = new BufferedInputStream(stream); } + // First attempt to use an ImageType mapped TextureProvider for O(1) + // using stream parsed data, ignoring the given fileSuffix! + try { + final ImageType imageType = new ImageType(stream); + if( imageType.isDefined() ) { + final TextureProvider mappedProvider = imageType2TextureProvider.get(imageType); + if( null != mappedProvider ) { + final TextureData data = mappedProvider.newTextureData(glp, stream, + internalFormat, + pixelFormat, + mipmap, + imageType.type); + if (data != null) { + data.srcImageType = imageType; + return data; + } + } + } + } catch (final IOException ioe) { + if(DEBUG) { + System.err.println("Caught "+ioe.getMessage()); + ioe.printStackTrace(); + } + } + + fileSuffix = toLowerCase(fileSuffix); + for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { final TextureProvider provider = iter.next(); final TextureData data = provider.newTextureData(glp, stream, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); + internalFormat, + pixelFormat, + mipmap, + fileSuffix); if (data != null) { + final ImageType[] imageTypes = provider.getImageTypes(); + data.srcImageType = null != imageTypes ? imageTypes[0] : null; return data; } } throw new IOException("No suitable reader for given stream"); } - + private static TextureData newTextureDataImpl(final GLProfile glp, final File file, + final int internalFormat, + final int pixelFormat, + final boolean mipmap, + final String fileSuffix) throws IOException { + if (file == null) { + throw new IOException("File was null"); + } + final InputStream stream = new BufferedInputStream(new FileInputStream(file)); + try { + return newTextureDataImpl( glp, stream, internalFormat, pixelFormat, mipmap, + (fileSuffix != null) ? fileSuffix : IOUtil.getFileSuffix(file) ); + } catch(final IOException ioe) { + throw new IOException(ioe.getMessage()+", given file "+file.getAbsolutePath(), ioe); + } finally { + stream.close(); + } + } private static TextureData newTextureDataImpl(final GLProfile glp, final URL url, final int internalFormat, final int pixelFormat, final boolean mipmap, - String fileSuffix) throws IOException { + final String fileSuffix) throws IOException { if (url == null) { throw new IOException("URL was null"); } - - fileSuffix = toLowerCase(fileSuffix); - - for (final Iterator<TextureProvider> iter = textureProviders.iterator(); iter.hasNext(); ) { - final TextureProvider provider = iter.next(); - final TextureData data = provider.newTextureData(glp, url, - internalFormat, - pixelFormat, - mipmap, - fileSuffix); - if (data != null) { - return data; - } + final InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureDataImpl(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } catch(final IOException ioe) { + throw new IOException(ioe.getMessage()+", given URL "+url, ioe); + } finally { + stream.close(); } - - throw new IOException("No suitable reader for given URL "+url); } //---------------------------------------------------------------------- - // DDS provider -- supports files only for now + // DDS image provider static class DDSTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_DDS) }; @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - if (DDS.equals(fileSuffix) || - DDS.equals(IOUtil.getFileSuffix(file))) { - final DDSImage image = DDSImage.read(file); - return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); - } - - return null; + public final ImageType[] getImageTypes() { + return imageTypes; } @Override @@ -894,8 +926,8 @@ public class TextureIO { final int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (DDS.equals(fileSuffix) || - DDS.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_DDS.equals(fileSuffix) || + ImageType.T_DDS.equals(ImageType.Util.getFileSuffix(stream))) { final byte[] data = IOUtil.copyStream2ByteArray(stream); final ByteBuffer buf = ByteBuffer.wrap(data); final DDSImage image = DDSImage.read(buf); @@ -905,20 +937,6 @@ public class TextureIO { return null; } - @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = new BufferedInputStream(url.openStream()); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } - } - private TextureData newTextureData(final GLProfile glp, final DDSImage image, int internalFormat, int pixelFormat, @@ -1003,47 +1021,14 @@ public class TextureIO { } //---------------------------------------------------------------------- - // Base class for SGI RGB and TGA image providers - static abstract class StreamBasedTextureProvider implements TextureProvider { - @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream inStream = new BufferedInputStream(new FileInputStream(file)); - try { - // The SGIImage and TGAImage implementations use InputStreams - // anyway so there isn't much point in having a separate code - // path for files - return newTextureData(glp, inStream, - internalFormat, - pixelFormat, - mipmap, - ((fileSuffix != null) ? fileSuffix : IOUtil.getFileSuffix(file))); - } finally { - inStream.close(); - } - } - + // SGI RGB image provider + static class SGITextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_SGI_RGB) }; @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = new BufferedInputStream(url.openStream()); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } + public final ImageType[] getImageTypes() { + return imageTypes; } - } - //---------------------------------------------------------------------- - // SGI RGB image provider - static class SGITextureProvider extends StreamBasedTextureProvider { @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, @@ -1051,9 +1036,9 @@ public class TextureIO { final boolean mipmap, final String fileSuffix) throws IOException { if (SGI.equals(fileSuffix) || - SGI_RGB.equals(fileSuffix) || - SGI.equals(ImageIOUtil.getFileSuffix(stream)) || - SGI_RGB.equals(ImageIOUtil.getFileSuffix(stream))) { + ImageType.T_SGI_RGB.equals(fileSuffix) || + SGI.equals(ImageType.Util.getFileSuffix(stream)) || + ImageType.T_SGI_RGB.equals(ImageType.Util.getFileSuffix(stream))) { final SGIImage image = SGIImage.read(stream); if (pixelFormat == 0) { pixelFormat = image.getFormat(); @@ -1080,14 +1065,20 @@ public class TextureIO { //---------------------------------------------------------------------- // TGA (Targa) image provider - static class TGATextureProvider extends StreamBasedTextureProvider { + static class TGATextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_TGA) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (TGA.equals(fileSuffix)) { + if (ImageType.T_TGA.equals(fileSuffix)) { final TGAImage image = TGAImage.read(glp, stream); if (pixelFormat == 0) { pixelFormat = image.getGLFormat(); @@ -1118,15 +1109,21 @@ public class TextureIO { //---------------------------------------------------------------------- // PNG image provider - static class PNGTextureProvider extends StreamBasedTextureProvider { + static class PNGTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_PNG) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (PNG.equals(fileSuffix) || - PNG.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_PNG.equals(fileSuffix) || + ImageType.T_PNG.equals(ImageType.Util.getFileSuffix(stream))) { final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */); if ( 0 == pixelFormat ) { @@ -1159,15 +1156,21 @@ public class TextureIO { //---------------------------------------------------------------------- // JPEG image provider - static class JPGTextureProvider extends StreamBasedTextureProvider { + static class JPGTextureProvider implements TextureProvider { + private static final ImageType[] imageTypes = new ImageType[] { new ImageType(ImageType.T_JPG) }; + @Override + public final ImageType[] getImageTypes() { + return imageTypes; + } + @Override public TextureData newTextureData(final GLProfile glp, final InputStream stream, int internalFormat, int pixelFormat, final boolean mipmap, final String fileSuffix) throws IOException { - if (JPG.equals(fileSuffix) || - JPG.equals(ImageIOUtil.getFileSuffix(stream))) { + if (ImageType.T_JPG.equals(fileSuffix) || + ImageType.T_JPG.equals(ImageType.Util.getFileSuffix(stream))) { final JPEGImage image = JPEGImage.read(/*glp, */ stream); if (pixelFormat == 0) { pixelFormat = image.getGLFormat(); @@ -1203,7 +1206,7 @@ public class TextureIO { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (DDS.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_DDS.equals(IOUtil.getFileSuffix(file))) { // See whether the DDS writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1256,7 +1259,7 @@ public class TextureIO { final TextureData data) throws IOException { final String fileSuffix = IOUtil.getFileSuffix(file); if (SGI.equals(fileSuffix) || - SGI_RGB.equals(fileSuffix)) { + ImageType.T_SGI_RGB.equals(fileSuffix)) { // See whether the SGI writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1300,7 +1303,7 @@ public class TextureIO { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (TGA.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_TGA.equals(IOUtil.getFileSuffix(file))) { // See whether the TGA writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; @@ -1350,7 +1353,7 @@ public class TextureIO { static class PNGTextureWriter implements TextureWriter { @Override public boolean write(final File file, final TextureData data) throws IOException { - if (PNG.equals(IOUtil.getFileSuffix(file))) { + if (ImageType.T_PNG.equals(IOUtil.getFileSuffix(file))) { // See whether the PNG writer can handle this TextureData final GLPixelAttributes pixelAttribs = data.getPixelAttributes(); final int pixelFormat = pixelAttribs.format; 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 36c44a409..246676aae 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 @@ -53,8 +53,7 @@ import java.nio.channels.FileChannel; import com.jogamp.opengl.GL; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IOUtil; -import com.jogamp.opengl.util.GLBuffers; -import com.jogamp.opengl.util.texture.ImageIOUtil; +import com.jogamp.opengl.util.texture.ImageType; /** A reader and writer for DirectDraw Surface (.dds) files, which are used to describe textures. These files can contain multiple mipmap @@ -238,38 +237,6 @@ public class DDSImage { return image; } - /** Determines from the magic number whether the given InputStream - points to a DDS image. The given InputStream must return true - from markSupported() and support a minimum of four bytes of - read-ahead. - - @param in Stream to check - @return true if input stream is DDS image or false otherwise - @throws java.io.IOException if an I/O exception occurred - @deprecated rather call {@link ImageIOUtil#getFileSuffix(InputStream)} - */ - @Deprecated - public static boolean isDDSImage(InputStream in) throws IOException { - if (!(in instanceof BufferedInputStream)) { - in = new BufferedInputStream(in); - } - if (!in.markSupported()) { - throw new IOException("Can not test non-destructively whether given InputStream is a DDS image"); - } - in.mark(4); - int magic = 0; - for (int i = 0; i < 4; i++) { - final int tmp = in.read(); - if (tmp < 0) { - in.reset(); - return false; - } - magic = ((magic >>> 8) | (tmp << 24)); - } - in.reset(); - return (magic == MAGIC); - } - /** * Writes this DDSImage to the specified file name. * @param filename File name to write to 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 ff8167bb0..47e40e367 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 @@ -42,7 +42,7 @@ package com.jogamp.opengl.util.texture.spi; import java.io.*; import com.jogamp.opengl.*; -import com.jogamp.opengl.util.texture.ImageIOUtil; +import com.jogamp.opengl.util.texture.ImageType; import com.jogamp.common.util.IOUtil; /** <p> Reads and writes SGI RGB/RGBA images. </p> @@ -191,28 +191,6 @@ public class SGIImage { return image; } - /** - * Determines from the magic number whether the given InputStream points to - * an SGI RGB image. The given InputStream must return true from - * markSupported() and support a minimum of two bytes of read-ahead. - * - * @deprecated rather call {@link ImageIOUtil#getFileSuffix(InputStream)} - */ - @Deprecated - public static boolean isSGIImage(InputStream in) throws IOException { - if (!(in instanceof BufferedInputStream)) { - in = new BufferedInputStream(in); - } - if (!in.markSupported()) { - throw new IOException("Can not test non-destructively whether given InputStream is an SGI RGB image"); - } - final DataInputStream dIn = new DataInputStream(in); - dIn.mark(4); - final short magic = dIn.readShort(); - dIn.reset(); - return (magic == MAGIC); - } - /** Returns the width of the image. */ public int getWidth() { return header.xsize; 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 e84f300e2..485a1b82d 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,5 +1,6 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2015 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 @@ -39,11 +40,13 @@ package com.jogamp.opengl.util.texture.spi; -import java.io.*; -import java.net.*; +import java.io.IOException; +import java.io.InputStream; + import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.util.texture.ImageType; +import com.jogamp.opengl.util.texture.TextureData; -import com.jogamp.opengl.util.texture.*; /** Plug-in interface to TextureIO to support reading OpenGL textures from new file formats. For all methods, either internalFormat or @@ -54,43 +57,24 @@ import com.jogamp.opengl.util.texture.*; public interface TextureProvider { /** - * Produces a TextureData object from a file, or returns null if the - * file format was not supported by this TextureProvider. Does not - * do any OpenGL-related work. The resulting TextureData can be - * converted into an OpenGL texture in a later step. - * - * @param glp the OpenGL Profile this texture data should be - * created for. - * @param file the file from which to read the texture data - * - * @param internalFormat the OpenGL internal format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param pixelFormat the OpenGL pixel format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param mipmap whether mipmaps should be produced for this - * texture either by autogenerating them or - * reading them from the file. Some file formats - * support multiple mipmaps in a single file in - * which case those mipmaps will be used rather - * than generating them. - * - * @param fileSuffix the file suffix to be used as a hint to the - * provider to more quickly decide whether it - * can handle the file, or null if the - * provider should infer the type from the - * file's contents - * - * @throws IOException if an error occurred while reading the file + * Optional additional interface for {@link TextureProvider} implementation + * exposing the supported {@link ImageType}s. + * <p> + * Use case: Mapping of {@link ImageType}s to {@link TextureProvider}. + * </p> */ - public TextureData newTextureData(GLProfile glp, File file, - int internalFormat, - int pixelFormat, - boolean mipmap, - String fileSuffix) throws IOException; + public static interface SupportsImageTypes { + /** Returns the supported {@link ImageType}s. */ + ImageType[] getImageTypes(); + } + + /** + * Returns the known supported {@link ImageType}s, or {@code null} if unknown. + * <p> + * Use case: Mapping of {@link ImageType}s to {@link TextureProvider}. + * </p> + */ + ImageType[] getImageTypes(); /** * Produces a TextureData object from a stream, or returns null if @@ -130,43 +114,4 @@ public interface TextureProvider { int pixelFormat, boolean mipmap, String fileSuffix) throws IOException; - - /** - * Produces a TextureData object from a URL, or returns null if the - * file format was not supported by this TextureProvider. Does not - * do any OpenGL-related work. The resulting TextureData can be - * converted into an OpenGL texture in a later step. - * - * @param glp the OpenGL Profile this texture data should be - * created for. - * @param url the URL from which to read the texture data - * - * @param internalFormat the OpenGL internal format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param pixelFormat the OpenGL pixel format to be used for - * the texture, or 0 if it should be inferred - * from the file's contents - * - * @param mipmap whether mipmaps should be produced for this - * texture either by autogenerating them or - * reading them from the file. Some file formats - * support multiple mipmaps in a single file in - * which case those mipmaps will be used rather - * than generating them. - * - * @param fileSuffix the file suffix to be used as a hint to the - * provider to more quickly decide whether it - * can handle the file, or null if the - * provider should infer the type from the - * file's contents - * - * @throws IOException if an error occurred while reading the URL - */ - public TextureData newTextureData(GLProfile glp, URL url, - int internalFormat, - int pixelFormat, - boolean mipmap, - String fileSuffix) throws IOException; } 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 ba762baf3..8ee54899c 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,5 +1,6 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2015 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 @@ -36,39 +37,29 @@ * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ - +// package com.jogamp.opengl.util.texture.spi.awt; -import java.awt.Graphics; -import java.awt.image.*; -import java.io.*; -import java.net.*; -import javax.imageio.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.util.texture.ImageType; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.awt.AWTTextureData; +import com.jogamp.opengl.util.texture.spi.TextureProvider; import jogamp.opengl.Debug; -import com.jogamp.opengl.util.texture.*; -import com.jogamp.opengl.util.texture.awt.*; -import com.jogamp.opengl.util.texture.spi.*; public class IIOTextureProvider implements TextureProvider { private static final boolean DEBUG = Debug.debug("TextureIO"); @Override - public TextureData newTextureData(final GLProfile glp, final File file, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final BufferedImage img = ImageIO.read(file); - if (img == null) { - return null; - } - if (DEBUG) { - System.out.println("TextureIO.newTextureData(): BufferedImage type for " + file + " = " + - img.getType()); - } - return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); + public final ImageType[] getImageTypes() { + return null; } @Override @@ -87,18 +78,4 @@ public class IIOTextureProvider implements TextureProvider { } return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); } - - @Override - public TextureData newTextureData(final GLProfile glp, final URL url, - final int internalFormat, - final int pixelFormat, - final boolean mipmap, - final String fileSuffix) throws IOException { - final InputStream stream = url.openStream(); - try { - return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); - } finally { - stream.close(); - } - } } |