com.jogamp.opengl.util.texture.spi.JPEGImage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jogl-all Show documentation
Show all versions of jogl-all Show documentation
Java™ Binding for the OpenGL® API
/**
* Copyright 2013 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.util.texture.spi;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import javax.media.opengl.GL;
import jogamp.opengl.Debug;
import jogamp.opengl.util.jpeg.JPEGDecoder;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
public class JPEGImage {
private static final boolean DEBUG = Debug.debug("JPEGImage");
/**
* Reads a JPEG image from the specified InputStream, using the given color space for storage.
*
* @param in
* @param cs Storage color space, either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception!
* @return
* @throws IOException
*/
public static JPEGImage read(InputStream in, ColorSpace cs) throws IOException {
return new JPEGImage(in, cs);
}
/** Reads a JPEG image from the specified InputStream, using the {@link ColorSpace#RGB}. */
public static JPEGImage read(InputStream in) throws IOException {
return new JPEGImage(in, ColorSpace.RGB);
}
private static class JPEGColorSink implements JPEGDecoder.ColorSink {
int width=0, height=0;
int sourceComponents=0;
ColorSpace sourceCS = ColorSpace.YCbCr;
int storageComponents;
final ColorSpace storageCS;
ByteBuffer data = null;
JPEGColorSink(ColorSpace storageCM) {
this.storageCS = storageCM;
switch(storageCS) {
case RGB:
case YCbCr:
storageComponents = 3;
break;
default:
throw new IllegalArgumentException("Unsupported storage color-space: "+storageCS);
}
}
@Override
public final ColorSpace allocate(int width, int height, ColorSpace sourceCM, int sourceComponents) throws RuntimeException {
this.width = width;
this.height = height;
this.sourceComponents = sourceComponents;
this.sourceCS = sourceCM;
this.data = Buffers.newDirectByteBuffer(width * height * storageComponents);
return storageCS;
}
@Override
public final void storeRGB(int x, int y, byte r, byte g, byte b) {
int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
data.put(i++, r);
data.put(i++, g);
data.put(i++, b);
// data.put(i++, (byte)0xff);
}
@Override
public final void store2(int x, int y, byte c1, byte c2) {
throw new RuntimeException("not supported yet");
}
@Override
public final void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr) {
int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
data.put(i++, Y);
data.put(i++, Cb);
data.put(i++, Cr);
}
public String toString() {
return "JPEGPixels["+width+"x"+height+", sourceComp "+sourceComponents+", sourceCS "+sourceCS+", storageCS "+storageCS+", storageComp "+storageComponents+"]";
}
};
private JPEGImage(InputStream in, ColorSpace cs) throws IOException {
pixelStorage = new JPEGColorSink(cs);
final JPEGDecoder decoder = new JPEGDecoder();
decoder.parse(in);
pixelWidth = decoder.getWidth();
pixelHeight = decoder.getHeight();
decoder.getPixel(pixelStorage, pixelWidth, pixelHeight);
data = pixelStorage.data;
final boolean hasAlpha = false;
bytesPerPixel = 3;
glFormat = GL.GL_RGB;
reversedChannels = false; // RGB[A]
if(DEBUG) {
System.err.println("JPEGImage: alpha "+hasAlpha+", bytesPerPixel "+bytesPerPixel+
", pixels "+pixelWidth+"x"+pixelHeight+", glFormat 0x"+Integer.toHexString(glFormat));
System.err.println("JPEGImage: "+decoder);
System.err.println("JPEGImage: "+pixelStorage);
}
decoder.clear(null);
}
private JPEGColorSink pixelStorage;
private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
private boolean reversedChannels;
private final ByteBuffer data;
/** Returns the color space of the pixel data */
public ColorSpace getColorSpace() { return pixelStorage.storageCS; }
/** Returns the number of components of the pixel data */
public int getComponentCount() { return pixelStorage.storageComponents; }
/** Returns the width of the image. */
public int getWidth() { return pixelWidth; }
/** Returns the height of the image. */
public int getHeight() { return pixelHeight; }
/** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
public boolean getHasReversedChannels() { return reversedChannels; }
/** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */
public int getGLFormat() { return glFormat; }
/** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
public int getGLType() { return GL.GL_UNSIGNED_BYTE; }
/** Returns the bytes per pixel */
public int getBytesPerPixel() { return bytesPerPixel; }
/** Returns the raw data for this texture in the correct
(bottom-to-top) order for calls to glTexImage2D. */
public ByteBuffer getData() { return data; }
public String toString() { return "JPEGImage["+pixelWidth+"x"+pixelHeight+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+pixelStorage+", "+data+"]"; }
}