diff options
author | Sven Gothel <[email protected]> | 2012-06-18 03:42:13 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-06-18 03:42:13 +0200 |
commit | 6f5f8a8eb046689e49668dd4d82e48bc7cb341d7 (patch) | |
tree | b6e12865432d1e1cf10cb36359d99b356fcda43d | |
parent | e8078eb70f6f82613d730ae5b8f837ccb46b81fb (diff) |
TextureIO TGA/PNG: Use RGB[9] for 1-3 channel data; PNGImage(PNGJ) add 1 channel (Luminance) read/write
4 files changed, 65 insertions, 35 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java index a94b1f827..49d4add5f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -907,12 +907,17 @@ public class Texture { } } else { if (mustFlipVertically) { - coords = new TextureCoords(0, (float) imgHeight / (float) texHeight, - (float) imgWidth / (float) texWidth, 0); + coords = new TextureCoords(0, // l + (float) imgHeight / (float) texHeight, // b + (float) imgWidth / (float) texWidth, // r + 0 // t + ); } else { - coords = new TextureCoords(0, 0, - (float) imgWidth / (float) texWidth, - (float) imgHeight / (float) texHeight); + coords = new TextureCoords(0, // l + 0, // b + (float) imgWidth / (float) texWidth, // r + (float) imgHeight / (float) texHeight // t + ); } } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java index 928f91ce5..96ee233fd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -355,7 +355,7 @@ public class TextureData { } public String toString() { - return "TextureData["+width+"x"+height+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; + return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; } //---------------------------------------------------------------------- diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java index d72210016..ca97cdc4b 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java @@ -1106,7 +1106,7 @@ public class TextureIO { } if (internalFormat == 0) { if(glp.isGL2GL3()) { - internalFormat = GL.GL_RGBA8; + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8; } else { internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; } @@ -1143,7 +1143,7 @@ public class TextureIO { } if (internalFormat == 0) { if(glp.isGL2GL3()) { - internalFormat = GL.GL_RGBA8; + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8; } else { internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; } @@ -1153,7 +1153,7 @@ public class TextureIO { image.getHeight(), 0, pixelFormat, - GL.GL_UNSIGNED_BYTE, + image.getGLType(), mipmap, false, false, @@ -1183,13 +1183,13 @@ public class TextureIO { int d3dFormat = 0; // FIXME: some of these are probably not completely correct and would require swizzling switch (pixelFormat) { - case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; - case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; - case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; - case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); - case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; - case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; - default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); + case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; + case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; + default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); } ByteBuffer[] mipmaps = null; @@ -1319,6 +1319,10 @@ public class TextureIO { boolean reversedChannels; int bytesPerPixel; switch(pixelFormat) { + case GL.GL_LUMINANCE: + reversedChannels=false; + bytesPerPixel=1; + break; case GL.GL_RGB: reversedChannels=false; bytesPerPixel=3; @@ -1340,10 +1344,8 @@ public class TextureIO { bytesPerPixel=-1; break; } - if ( 1 < bytesPerPixel && - (pixelType == GL.GL_BYTE || - pixelType == GL.GL_UNSIGNED_BYTE)) { - + if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) && + ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) { ByteBuffer buf = (ByteBuffer) data.getBuffer(); if (null == buf) { buf = (ByteBuffer) data.getMipmapData()[0]; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java index a89418f84..d8d6f7daa 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java @@ -23,7 +23,7 @@ import com.jogamp.common.util.IOUtil; public class PNGImage { /** Creates a PNGImage from data supplied by the end user. Shares data with the passed ByteBuffer. Assumes the data is already in - the correct byte order for writing to disk, i.e., RGB or RGBA bottom-to-top (OpenGL coord). */ + the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA bottom-to-top (OpenGL coord). */ public static PNGImage createFromData(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, ByteBuffer data) { return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, data); @@ -44,7 +44,7 @@ public class PNGImage { d.put(dOff--, (byte)line.scanline[lineOff ]); // R return dOff; } - /** Reverse read and store, implicitly flip image from GL coords. */ + /** Reverse read and store, implicitly flip image from GL coords. Handle reversed channels (BGR[A])*/ private static int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha, boolean reversedChannels) { if(reversedChannels) { line.scanline[lineOff ] = d.get(dOff--); // R, A @@ -83,12 +83,15 @@ public class PNGImage { private PNGImage(InputStream in) { final PngReader pngr = new PngReader(new BufferedInputStream(in), null); final int channels = pngr.imgInfo.channels; - if (3 > channels || channels > 4 ) { - throw new RuntimeException("PNGImage can only handle RGB/RGBA images for now. Channels "+channels); + if ( ! ( 1 == channels || 3 == channels || 4 == channels ) ) { + throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels); } bytesPerPixel=pngr.imgInfo.bytesPixel; - if (3 > bytesPerPixel || bytesPerPixel > 4 ) { - throw new RuntimeException("PNGImage can only handle RGB/RGBA images for now. BytesPerPixel "+bytesPerPixel); + if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel ) ) { + throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel); + } + if(channels != bytesPerPixel) { + throw new RuntimeException("PNGImage currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel); } pixelWidth=pngr.imgInfo.cols; pixelHeight=pngr.imgInfo.rows; @@ -97,18 +100,29 @@ public class PNGImage { final double[] dpi2 = pngr.getMetadata().getDpi(); dpi[0]=dpi2[0]; dpi[1]=dpi2[1]; - } - glFormat= ( 4 == bytesPerPixel ) ? GL.GL_RGBA : GL.GL_RGB; + } + switch(channels) { + case 1: glFormat = GL.GL_LUMINANCE; break; + case 3: glFormat = GL.GL_RGB; break; + case 4: glFormat = GL.GL_RGBA; break; + default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel); + } data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight); reversedChannels = false; // RGB[A] - final boolean hasAlpha = 4 == bytesPerPixel; + final boolean hasAlpha = 4 == channels; int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store for (int row = 0; row < pixelHeight; row++) { final ImageLine l1 = pngr.readRow(row); int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = getPixelRGBA8(data, dataOff, l1, lineOff, hasAlpha); - lineOff -= bytesPerPixel; + if(1 == channels) { + for (int j = pixelWidth - 1; j >= 0; j--) { + data.put(dataOff--, (byte)l1.scanline[lineOff--]); // Luminance, 1 bytesPerPixel + } + } else { + for (int j = pixelWidth - 1; j >= 0; j--) { + dataOff = getPixelRGBA8(data, dataOff, l1, lineOff, hasAlpha); + lineOff -= bytesPerPixel; + } } } pngr.end(); @@ -132,6 +146,9 @@ public class PNGImage { /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ 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; } @@ -156,9 +173,15 @@ public class PNGImage { int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse read for (int row = 0; row < pixelHeight; row++) { int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store - for (int j = pixelWidth - 1; j >= 0; j--) { - dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels); - lineOff -= bytesPerPixel; + if(1 == bytesPerPixel) { + for (int j = pixelWidth - 1; j >= 0; j--) { + l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel + } + } else { + for (int j = pixelWidth - 1; j >= 0; j--) { + dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels); + lineOff -= bytesPerPixel; + } } png.writeRow(l1, row); } |