diff options
author | Sven Gothel <[email protected]> | 2014-12-06 21:12:18 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-12-06 21:12:18 +0100 |
commit | a53e87a84c92444e8a3173f25ce86dcfd536d6a8 (patch) | |
tree | bd19e9f40e4c67203d579c28b3775a5c17adc106 /src/test | |
parent | 241d505749b7d2bd383673a378fdca268989d2fd (diff) |
Bug 1107 - Refine PixelFormat, GLPixelBuffer and DirectDataBufferInt/BufferedImageInt
- PixelFormat
Refine definition allowing complete format conversion by its attributes
instead of static 'knowledge'.
- PixelFormat has_a *new* PixelFormat.Composition
- PixelFormat.Composition contains all pixel component layout
information as required for inspection and conversion.
Component names are enumerated via PixelFormat.CType.
- PixelFormatUtil.convert(..) utilizes generic conversion
based on PixelFormat.Composition rather static type mapping.
However, a int32 RGBA static conversion is still supported for performance.
Utilizes Bitstream for varying pixel component bit-width.
- Complete w/ hashCode() and equals(..)
- GLPixelBuffer
- Take 'pack' mode into account when determine GLPixelAttributes,
i.e. on GLES pack=true (e.g. glReadPixel) only RGBA is guaranteed to work.
Hence querying GLPixelAttributes requires the GLProfile, PixelFormat and pack mode.
- Complete GLPixelAttributes conversions from PixelFormat or GL format/data-type,
while taking GL data-type into account, as well as pack-mode.
- Complete w/ hashCode() and equals(..)
- SingletonGLPixelBufferProvider queries singleton GLPixelBuffer via
- PixelFormat.Composition hostPixelComp,
- GLPixelAttributes pixelAttributes,
- boolean pack
which comprise a unique key, allowing the implementation to utilize
a hash map. This is implemented in AWTSingletonGLPixelBufferProvider.
This allows distinct singleton GLPixelBuffer for different
host PixelFormat (conversion) and GLPixelAttributes (depending on GLProfile).
- Removes field 'componentCount' which was 'hacked in' to pass
information about an optional host memory layout.
Implementations utilizing conversion, e.g. AWTGLPixelBuffer,
can implement GLPixelBufferProvider's
'PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount)'
and manage such implementation details, see use-case GLJPanel.
- DirectDataBufferInt/BufferedImageInt: Expose underlying NIO ByteBuffer
- AWTMisc.createCursor(..) uses DirectDataBufferInt.BufferedImageInt exposed
NIO ByteBuffer, allowing to use generic PixelFormatUtil.convert(..).
Diffstat (limited to 'src/test')
10 files changed, 508 insertions, 164 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java index ae11c9d54..3e2476563 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java @@ -70,6 +70,7 @@ import com.jogamp.opengl.util.FPSAnimator; public class TestGearsES2GLJPanelAWT extends UITestCase { static Dimension wsize, rwsize=null; static boolean forceES2 = false; + static boolean forceES3 = false; static boolean forceGL3 = false; static boolean forceGLFFP = false; static boolean shallUsePBuffer = false; @@ -117,6 +118,8 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { protected void runTestGL(final GLCapabilities caps) throws AWTException, InterruptedException, InvocationTargetException { + System.err.println("Requesting: "+caps); + final JFrame frame = new JFrame("Swing GLJPanel"); Assert.assertNotNull(frame); @@ -302,12 +305,14 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { final GLProfile glp; if(forceGL3) { glp = GLProfile.get(GLProfile.GL3); + } else if(forceES3) { + glp = GLProfile.get(GLProfile.GLES3); } else if(forceES2) { glp = GLProfile.get(GLProfile.GLES2); } else if(forceGLFFP) { glp = GLProfile.getMaxFixedFunc(true); } else { - glp = GLProfile.getGL2ES2(); + glp = GLProfile.getDefault(); } final GLCapabilities caps = new GLCapabilities( glp ); if(useMSAA) { @@ -406,7 +411,24 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { } @Test - public void test30_GL3() + public void test30_GLES3() + throws AWTException, InterruptedException, InvocationTargetException + { + if( manualTest ) { + return; + } + + if( !GLProfile.isAvailable(GLProfile.GLES3) ) { + System.err.println("GLES3 n/a"); + return; + } + final GLProfile glp = GLProfile.get(GLProfile.GLES3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } + + @Test + public void test40_GL3() throws AWTException, InterruptedException, InvocationTargetException { if( manualTest ) { @@ -447,6 +469,8 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { duration = MiscUtils.atol(args[i], duration); } else if(args[i].equals("-es2")) { forceES2 = true; + } else if(args[i].equals("-es3")) { + forceES3 = true; } else if(args[i].equals("-gl3")) { forceGL3 = true; } else if(args[i].equals("-glFFP")) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java index 11d9da780..c22a6fdf8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java @@ -99,7 +99,7 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase { if( initSingleBuffer ) { singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( glp.isGL2ES3() /* allowRowStride */); - singleAWTGLPixelBufferProvider.initSingleton(4, 600, 600, 1, true); + singleAWTGLPixelBufferProvider.initSingleton(null, 4, true, 600, 600, 1); } else { singleAWTGLPixelBufferProvider = null; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java index 546420057..ed20ccd97 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java @@ -40,6 +40,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -117,8 +118,9 @@ public class TestRandomTiledRendering2GL2NEWT extends UITestCase { @Override public void init(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); - final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); - final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true); + final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0); renderer.setImageBuffer(pixelBuffer); if( drawable.isGLOriented() ) { flipVertically[0] = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java index b128f8691..a9d159684 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java @@ -48,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -136,8 +137,9 @@ public class TestRandomTiledRendering3GL2AWT extends UITestCase { @Override public void init(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); - final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); - final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true); + final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0); renderer.setImageBuffer(pixelBuffer); if( drawable.isGLOriented() ) { flipVertically[0] = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java index 9dee67e5e..1f7016b7c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java @@ -39,6 +39,7 @@ import com.jogamp.opengl.util.texture.TextureIO; import java.io.File; import java.io.IOException; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -121,8 +122,9 @@ public class TestTiledRendering1GL2NEWT extends UITestCase { final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; final boolean[] flipVertically = { false }; - final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); - final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true); + final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0); renderer.setImageBuffer(pixelBuffer); flipVertically[0] = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java index e979ac966..e792ecaa2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java @@ -40,6 +40,8 @@ import com.jogamp.opengl.util.texture.TextureIO; import java.io.File; import java.io.IOException; + +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -197,8 +199,9 @@ public class TestTiledRendering2NEWT extends UITestCase { @Override public void init(final GLAutoDrawable drawable) { final GL gl = drawable.getGL(); - final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); - final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true); + final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0); renderer.setImageBuffer(pixelBuffer); if( drawable.isGLOriented() ) { flipVertically[0] = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java index 2eb8b45c3..1a146adb6 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java @@ -112,7 +112,7 @@ public class TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT extends UITestC public void dispose(final GLAutoDrawable drawable) {} public void display(final GLAutoDrawable drawable) { final GLPixelBufferProvider pixelBufferProvider = screenshot.getPixelBufferProvider(); - final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3); + final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3, true); System.err.println("GLPixelAttributes: "+pixelAttribs); snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java index 4a324f594..3f910ed36 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java @@ -73,9 +73,10 @@ public class TestPNGPixelRect01NEWT extends UITestCase { final GLProfile glp = GLProfile.getGL2ES2(); final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */); Assert.assertNotNull(image); - final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp); - final boolean hasAlpha = 4 == glpa.bytesPerPixel; - System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa); + System.err.println("PNGPixelRect: "+basename+", "+image); + final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */); + final boolean hasAlpha = 4 == glpa.pfmt.comp.bytesPerPixel(); + System.err.println("GLPixelAttributes: "+glpa); final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); final GLCapabilities caps = new GLCapabilities(glp); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java index 1b549fa96..6193ad1a7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java @@ -36,12 +36,14 @@ import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.PixelFormat; import javax.media.nativewindow.util.PixelFormatUtil; import javax.media.nativewindow.util.PixelRectangle; +import javax.media.nativewindow.util.PixelFormat.CType; import org.junit.Assert; import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.common.util.Bitstream; import com.jogamp.opengl.test.junit.util.UITestCase; /** @@ -50,142 +52,401 @@ import com.jogamp.opengl.test.junit.util.UITestCase; */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestPixelFormatUtil00NEWT extends UITestCase { + static final byte undef_val = (byte)0xFF; + static final PixelFormat.Composition comp_val = PixelFormat.RGBA8888.comp; + static final float red___valF; + static final float green_valF; + static final float blue__valF; + static final float alpha_valF; + static final float lum___valF; + static { + // Using am equal stepping of 0x30 = 48 between each RGBA and undefined values, + // dividing 0xff equally by 5 excluding zero. + final byte red___val = (byte)0x30; + final byte green_val = (byte)0x60; + final byte blue__val = (byte)0x90; + final byte alpha_val = (byte)0xC0; + red___valF = comp_val.toFloat(red___val, 0, false); + green_valF = comp_val.toFloat(green_val, 1, false); + blue__valF = comp_val.toFloat(blue__val, 2, false); + alpha_valF = comp_val.toFloat(alpha_val, 3, false); + lum___valF = ( red___valF + green_valF + blue__valF ) / 3f; + } + + @Test + public void testConversion00() throws InterruptedException, IOException, MalformedURLException { + { + final PixelFormat fmt = PixelFormat.RGBA5551; + final PixelFormat.Composition comp = fmt.comp; + System.err.printf("%s, %s:%n", fmt, comp); + final int u16_alpha = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false), + (byte)comp.fromFloat(green_valF, 0, false), + (byte)comp.fromFloat(blue__valF, 0, false), + (byte)comp.fromFloat(alpha_valF, 0, false)); + final int u16_undef = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false), + (byte)comp.fromFloat(green_valF, 0, false), + (byte)comp.fromFloat(blue__valF, 0, false), + undef_val); + System.err.printf(" u16_alpha %s%n", Bitstream.toHexBinString(true, u16_alpha, comp.bitsPerPixel())); + System.err.printf(" u16_undef %s%n", Bitstream.toHexBinString(true, u16_undef, comp.bitsPerPixel())); + { + final byte c4NormI8_alpha = (byte)comp.fromFloat(alpha_valF, 0, false); + final byte c4NormI8_undef = undef_val; + final int compBitShift = 15; + final int compMask = 0x1; + final int v_alpha = ( c4NormI8_alpha & compMask ) << compBitShift ; + final int v_undef = ( c4NormI8_undef & compMask ) << compBitShift ; + System.err.printf(" xx_alpha %s%n", Bitstream.toHexBinString(true, v_alpha, comp.bitsPerPixel())); + System.err.printf(" xx_undef %s%n", Bitstream.toHexBinString(true, v_undef, comp.bitsPerPixel())); + } + } + { + final int r8 = 0x30; + final int g8 = 0x60; + final int b8 = 0x90; + final int a8 = 0xC0; + + final int l1 = 0x1; + final int r5 = 0x6; + final int g6 = 0xC; + final int b5 = 0x6; + + final PixelFormat rgba8888Fmt = PixelFormat.RGBA8888; + final PixelFormat.Composition rgba8888Comp = rgba8888Fmt.comp; + final PixelFormat rgb565Fmt = PixelFormat.RGB565; + final PixelFormat.Composition rgb565Comp = rgb565Fmt.comp; + final PixelFormat lumFmt = PixelFormat.LUMINANCE; + final PixelFormat.Composition lumComp = lumFmt.comp; + System.err.printf("%s, %s -> %s %s%n", rgb565Fmt, rgb565Comp, lumFmt, lumComp); + + { + final float r8f = rgba8888Comp.toFloat(r8, 0, false); + final int r8fi = rgba8888Comp.fromFloat(r8f, 0, false); + final float g8f = rgba8888Comp.toFloat(g8, 1, false); + final int g8fi = rgba8888Comp.fromFloat(g8f, 1, false); + final float b8f = rgba8888Comp.toFloat(b8, 2, false); + final int b8fi = rgba8888Comp.fromFloat(b8f, 2, false); + final float a8f = rgba8888Comp.toFloat(a8, 3, false); + final int a8fi = rgba8888Comp.fromFloat(a8f, 3, false); + + System.err.printf("res00.0.r %s -> %f -> %s%n", Bitstream.toHexBinString(true, r8, 8), r8f, Bitstream.toHexBinString(true, r8fi, 8)); + System.err.printf("res00.0.g %s -> %f -> %s%n", Bitstream.toHexBinString(true, g8, 8), g8f, Bitstream.toHexBinString(true, g8fi, 8)); + System.err.printf("res00.0.b %s -> %f -> %s%n", Bitstream.toHexBinString(true, b8, 8), b8f, Bitstream.toHexBinString(true, b8fi, 8)); + System.err.printf("res00.0.a %s -> %f -> %s%n", Bitstream.toHexBinString(true, a8, 8), a8f, Bitstream.toHexBinString(true, a8fi, 8)); + } + { + final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f; + final int res00 = rgba8888Comp.fromFloat(res00_0, 0, false); + System.err.printf("res01.0 ( %f + %f + %f ) / 3f = %f -> %s%n", + red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8)); + } + { + final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f; + final int res00 = lumComp.fromFloat(res00_0, 0, false); + System.err.printf("res02.1 ( %f + %f + %f ) / 3f = %f -> %s%n", + red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8)); + } + { + // sourceNorm static -> lum + final int rl1 = lumComp.fromFloat(red___valF, 0, false); + final int gl1 = lumComp.fromFloat(green_valF, 0, false); + final int bl1 = lumComp.fromFloat(blue__valF, 0, false); + final float rl2 = lumComp.toFloat(rl1, 0, false); + final float gl2 = lumComp.toFloat(gl1, 0, false); + final float bl2 = lumComp.toFloat(bl1, 0, false); + System.err.printf("res20.l1 ( %s + %s + %s )%n", + Bitstream.toHexBinString(true, rl1, 8), + Bitstream.toHexBinString(true, gl1, 8), + Bitstream.toHexBinString(true, bl1, 8)); + System.err.printf("res20.l2 ( %f + %f + %f )%n", rl2, gl2, bl2); + final float res02_l2_0 = ( rl2 + gl2 + bl2 ) / 3f; + final int res02_l2_x = lumComp.fromFloat(res02_l2_0, 0, false); + System.err.printf("res20.l3 ( %f + %f + %f ) / 3f = %f -> %s%n", + rl2, gl2, bl2, res02_l2_0, Bitstream.toHexBinString(true, res02_l2_x, 8)); + + // rescale lum -> rgb565 + final int r_1 = rgb565Comp.fromFloat(rl2, 0, false); + final int g_1 = rgb565Comp.fromFloat(gl2, 1, false); + final int b_1 = rgb565Comp.fromFloat(bl2, 2, false); + final float r_2 = rgb565Comp.toFloat(r_1, 0, false); + final float g_2 = rgb565Comp.toFloat(g_1, 1, false); + final float b_2 = rgb565Comp.toFloat(b_1, 2, false); + System.err.printf("res20._1 ( %s + %s + %s )%n", + Bitstream.toHexBinString(true, r_1, 8), + Bitstream.toHexBinString(true, g_1, 8), + Bitstream.toHexBinString(true, b_1, 8)); + System.err.printf("res20._2 ( %f + %f + %f )%n", r_2, g_2, b_2); + final float res02__3_0 = ( r_2 + g_2 + b_2 ) / 3f; + final int res02__3_x = lumComp.fromFloat(res02__3_0, 0, false); + System.err.printf("res20._3 ( %f + %f + %f ) / 3f = %f -> %s%n", + r_2, g_2, b_2, res02__3_0, Bitstream.toHexBinString(true, res02__3_x, 8)); + } + { + // sourceNorm static -> lum + // rescale lum -> rgb565 + final float rF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 0, red___valF), 0, false); + final float gF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 1, green_valF), 1, false); + final float bF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 2, blue__valF), 2, false); + final float res01_0 = ( rF + gF + bF ) / 3f; + final int res01 = lumComp.fromFloat(res01_0, 0, false); + System.err.printf("res30.xx ( %f + %f + %f ) / 3f = %f -> %s%n", + rF, gF, bF, res01_0, Bitstream.toHexBinString(true, res01, 8)); + } + { + final float rF = rgb565Comp.toFloat(r5, 0, false); + final float gF = rgb565Comp.toFloat(g6, 1, false); + final float bF = rgb565Comp.toFloat(b5, 2, false); + + final float lF = ( rF + gF + bF ) / 3f; + final int res00 = lumComp.fromFloat(lF, 0, false); + + System.err.printf("res40 ( %f + %f + %f ) / 3f = %s%n", + rF, gF, bF, Bitstream.toHexBinString(true, res00, 8)); + } + } + + } + @Test public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException { - testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, - 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); } @Test public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException { - testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */, - 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); + testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */, + 0 /* destMinStrideInBytes */, false /* destIsGLOriented */); } @Test public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { - testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, - 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); } @Test public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { - testPNG00Impl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, - 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + testConversionImpl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); } @Test public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException { - testPNG00Impl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, - 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); + testConversionImpl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */, + 259 /* destMinStrideInBytes */, false /* destIsGLOriented */); } - static final byte red___val = (byte)0x01; - static final byte green_val = (byte)0x02; - static final byte blue__val = (byte)0x03; - static final byte alpha_val = (byte)0x04; - static final byte undef_val = (byte)0xff; - - static final void getComponents(final int srcComps, final PixelFormat fmt, final byte[] components) { + /** + * Note: Fixes bit-rounding errors, i.e. RGBA5551: A 0.6f -> 0x01 -> 1f ... -> RGBA8888: A 0xff + */ + static final float sourceNorm(final PixelFormat.Composition srcComp, final int sIdx, final float f) { + if( sIdx >= 0 && sIdx < srcComp.componenCount() ) { + return srcComp.toFloat(srcComp.fromFloat(f, sIdx, false), sIdx, false); + } else { + return 0f; + } + } + static final byte rescaleComp(final PixelFormat.Composition srcComp, final int sIdx, + final PixelFormat.Composition dstComp, final int dIdx, final float f) { + if( dIdx >= 0 && dIdx < dstComp.componenCount() ) { + return (byte)dstComp.fromFloat(sourceNorm(srcComp, sIdx, f), dIdx, false); + } else { + return (byte)0; + } + } + static final void getComponentData(final PixelFormat srcFmt, final PixelFormat dstFmt, final byte[] components) { + final PixelFormat.Composition srcComp = srcFmt.comp; + final PixelFormat.Composition dstComp = dstFmt.comp; final byte b1, b2, b3, b4; - if( 1 == srcComps ) { + int u16; + if( PixelFormat.LUMINANCE == srcFmt ) { // LUM -> Fmt Conversion - switch(fmt) { + switch(dstFmt) { case LUMINANCE: - b1 = red___val; + b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF); b2 = undef_val; b3 = undef_val; b4 = undef_val; break; - case RGB888: - b1 = red___val; - b2 = red___val; - b3 = red___val; + case RGB565: + case BGR565: + u16 = dstComp.encode3CompI8( + rescaleComp(srcComp, 0, dstComp, 0, lum___valF), + rescaleComp(srcComp, 0, dstComp, 1, lum___valF), + rescaleComp(srcComp, 0, dstComp, 2, lum___valF)); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; b4 = undef_val; break; - case BGR888: - b1 = red___val; - b2 = red___val; - b3 = red___val; + case RGBA5551: + u16 = dstComp.encode4CompI8( + rescaleComp(srcComp, 0, dstComp, 0, lum___valF), + rescaleComp(srcComp, 0, dstComp, 1, lum___valF), + rescaleComp(srcComp, 0, dstComp, 2, lum___valF), + undef_val); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; b4 = undef_val; break; + case ABGR1555: + u16 = dstComp.encode4CompI8( + undef_val, + rescaleComp(srcComp, 0, dstComp, 0, lum___valF), + rescaleComp(srcComp, 0, dstComp, 1, lum___valF), + rescaleComp(srcComp, 0, dstComp, 2, lum___valF) ); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; + b4 = undef_val; + break; + case BGRx8888: + case RGBx8888: + case RGB888: + case BGR888: case RGBA8888: - b1 = red___val; - b2 = red___val; - b3 = red___val; + b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF); + b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF); + b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF); b4 = undef_val; break; case ABGR8888: + case ARGB8888: b1 = undef_val; - b2 = red___val; - b3 = red___val; - b4 = red___val; + b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF); + b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF); + b4 = rescaleComp(srcComp, 0, dstComp, 3, lum___valF); break; case BGRA8888: - b1 = red___val; - b2 = red___val; - b3 = red___val; + b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF); + b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF); + b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF); b4 = undef_val; break; - case ARGB8888: - b1 = undef_val; - b2 = red___val; - b3 = red___val; - b4 = red___val; - break; default: - throw new InternalError("Unhandled format "+fmt); + throw new InternalError("Unhandled format "+dstFmt); } } else { + final int srcIdxR = srcComp.find(CType.R); + final int srcIdxG = srcComp.find(CType.G); + final int srcIdxB = srcComp.find(CType.B); + final int srcIdxA = srcComp.find(CType.A); + final boolean srcHasAlpha = 0 <= srcIdxA; + final boolean srcHasRGB = 0 <= srcIdxR && 0 <= srcIdxG && 0 <= srcIdxB; // 1:1 values - switch(fmt) { + switch(dstFmt) { case LUMINANCE: - if( srcComps > 1 ) { - b1 = ( red___val + green_val+ blue__val ) / 3; + if( srcHasRGB ) { + final float rF = sourceNorm(srcComp, srcIdxR, red___valF); + final float gF = sourceNorm(srcComp, srcIdxG, green_valF); + final float bF = sourceNorm(srcComp, srcIdxB, blue__valF); + b1 = (byte)dstComp.fromFloat( ( rF + gF + bF ) / 3f, 0, false); b2 = undef_val; b3 = undef_val; b4 = undef_val; } else { - b1 = red___val; + b1 = rescaleComp(srcComp, 0, dstComp, 0, red___valF); b2 = undef_val; b3 = undef_val; b4 = undef_val; } break; + case RGB565: + u16 = dstComp.encode3CompI8( + rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF), + rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF), + rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF)); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; + b4 = undef_val; + break; + case BGR565: + u16 = dstComp.encode3CompI8( + rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF), + rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF), + rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF)); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; + b4 = undef_val; + break; + case RGBA5551: + u16 = dstComp.encode4CompI8( + rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF), + rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF), + rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF), + srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF) : undef_val); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; + b4 = undef_val; + break; + case ABGR1555: + u16 = dstComp.encode4CompI8( + srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF) : undef_val, + rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF), + rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF), + rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF) ); + b1 = (byte)( u16 & 0xff ); + b2 = (byte)( ( u16 >>> 8 ) & 0xff ); + b3 = undef_val; + b4 = undef_val; + break; + case RGBx8888: case RGB888: - b1 = red___val; - b2 = green_val; - b3 = blue__val; + b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF); + b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF); + b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF); b4 = undef_val; break; + case BGRx8888: case BGR888: - b1 = blue__val; - b2 = green_val; - b3 = red___val; + b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF); + b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF); + b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF); b4 = undef_val; break; case RGBA8888: - b1 = red___val; - b2 = green_val; - b3 = blue__val; - b4 = srcComps > 3 ? alpha_val : undef_val; + b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF); + b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF); + b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF); + if( srcHasAlpha ) { + b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF); + } else { + b4 = undef_val; + } break; case ABGR8888: - b1 = srcComps > 3 ? alpha_val : undef_val; - b2 = blue__val; - b3 = green_val; - b4 = red___val; + if( srcHasAlpha ) { + b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF); + } else { + b1 = undef_val; + } + b2 = rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF); + b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF); + b4 = rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF); break; case BGRA8888: - b1 = blue__val; - b2 = green_val; - b3 = red___val; - b4 = srcComps > 3 ? alpha_val : undef_val; + b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF); + b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF); + b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF); + if( srcHasAlpha ) { + b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF); + } else { + b4 = undef_val; + } break; case ARGB8888: - b1 = srcComps > 3 ? alpha_val : undef_val; - b2 = red___val; - b3 = green_val; - b4 = blue__val; + if( srcHasAlpha ) { + b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF); + } else { + b1 = undef_val; + } + b2 = rescaleComp(srcComp, srcIdxR, dstComp, 1, red___valF); + b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF); + b4 = rescaleComp(srcComp, srcIdxB, dstComp, 3, blue__valF); break; default: - throw new InternalError("Unhandled format "+fmt); + throw new InternalError("Unhandled format "+dstFmt); } } components[0] = b1; @@ -193,85 +454,120 @@ public class TestPixelFormatUtil00NEWT extends UITestCase { components[2] = b3; components[3] = b4; } - private void testPNG00Impl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented, + private void testConversionImpl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented, final int destMinStrideInBytes, final boolean destIsGLOriented) throws InterruptedException, IOException, MalformedURLException { System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+ ", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented); - final PixelFormat[] formats = PixelFormat.values(); + // final PixelFormat[] srcFormats = { PixelFormat.LUMINANCE }; + // final PixelFormat[] dstFormats = { PixelFormat.RGBx8888 }; + // final PixelFormat[] dstFormats = { PixelFormat.RGB5551 }; + // final PixelFormat[] dstFormats = { PixelFormat.RGB888 }; + // final PixelFormat[] srcFormats = { PixelFormat.RGB888 }; + // final PixelFormat[] dstFormats = { PixelFormat.RGB565 }; + final PixelFormat[] srcFormats = PixelFormat.values(); + final PixelFormat[] dstFormats = PixelFormat.values(); final int width = 64, height = 64; - for(int i=0; i<formats.length; i++) { - final PixelFormat srcFmt = formats[i]; - final int srcBpp = srcFmt.bytesPerPixel(); + for(int i=0; i<srcFormats.length; i++) { + final PixelFormat srcFmt = srcFormats[i]; + final int srcBpp = srcFmt.comp.bytesPerPixel(); final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp); final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder); - final byte[] srcComponents = new byte[4]; - getComponents(srcFmt.componentCount, srcFmt, srcComponents); + final byte[] srcData = new byte[4]; + getComponentData(srcFmt, srcFmt, srcData); for(int y=0; y<height; y++) { int o = y*srcStrideBytes; for(int x=0; x<width; x++) { switch(srcFmt) { case LUMINANCE: - srcPixels.put(o++, srcComponents[0]); + srcPixels.put(o++, srcData[0]); + break; + case BGR565: + case RGB565: + case ABGR1555: + case RGBA5551: + srcPixels.put(o++, srcData[0]); + srcPixels.put(o++, srcData[1]); break; case RGB888: case BGR888: - srcPixels.put(o++, srcComponents[0]); - srcPixels.put(o++, srcComponents[1]); - srcPixels.put(o++, srcComponents[2]); + srcPixels.put(o++, srcData[0]); + srcPixels.put(o++, srcData[1]); + srcPixels.put(o++, srcData[2]); break; + case RGBx8888: + case BGRx8888: case RGBA8888: case ABGR8888: case BGRA8888: case ARGB8888: - srcPixels.put(o++, srcComponents[0]); - srcPixels.put(o++, srcComponents[1]); - srcPixels.put(o++, srcComponents[2]); - srcPixels.put(o++, srcComponents[3]); + srcPixels.put(o++, srcData[0]); + srcPixels.put(o++, srcData[1]); + srcPixels.put(o++, srcData[2]); + srcPixels.put(o++, srcData[3]); break; default: throw new InternalError("Unhandled format "+srcFmt); } } } - final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), srcStrideBytes, srcIsGLOriented, srcPixels); + final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), + srcStrideBytes, srcIsGLOriented, srcPixels); + System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc); - testComponents(imageSrc, 0, 0, srcComponents); - testComponents(imageSrc, width-1, height-1, srcComponents); + System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp); + System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel())); + testComponents(imageSrc, 0, 0, srcData, 0); + testComponents(imageSrc, width-1, height-1, srcData, 0); - for(int j=0; j<formats.length; j++) { - final PixelFormat destFmt = formats[j]; - System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt); + final int maxDelta = 12; - final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.bytesPerPixel()); + for(int j=0; j<dstFormats.length; j++) { + final PixelFormat destFmt = dstFormats[j]; + System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt); + final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.comp.bytesPerPixel()); final byte[] destComponents = new byte[4]; - getComponents(srcFmt.componentCount, destFmt, destComponents); - final PixelRectangle imageConv1 = PixelFormatUtil.convert32(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */); - System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1); - testComponents(imageConv1, 0, 0, destComponents); - testComponents(imageConv1, width-1, height-1, destComponents); + getComponentData(srcFmt, destFmt, destComponents); + System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp); + System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel())); + System.err.printf("Dest %s, %s%n", destFmt, destFmt.comp); + System.err.printf("Dest Data: %s%n", Bitstream.toHexBinString(true, destComponents, 0, destFmt.comp.bytesPerPixel())); + final PixelRectangle imageConv1 = PixelFormatUtil.convert(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */); + System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1+", maxDelta "+maxDelta); + System.err.printf("Conv1 Data: %s%n", Bitstream.toHexBinString(true, imageConv1.getPixels(), 0, destFmt.comp.bytesPerPixel())); + testComponents(imageConv1, 0, 0, destComponents, maxDelta); + testComponents(imageConv1, width-1, height-1, destComponents, maxDelta); if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) { // Cannot convert: RGB* -> LUM -> RGB* System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM"); - } else if( srcFmt.componentCount > destFmt.componentCount ) { + } else if( srcFmt.comp.componenCount() > destFmt.comp.componenCount() ) { // Cannot convert back if: src.componentCount > dest.componentCount System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount"); } else { - final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */); - System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2); - testComponents(imageConv2, 0, 0, srcComponents); - testComponents(imageConv2, width-1, height-1, srcComponents); + final PixelRectangle imageConv2 = PixelFormatUtil.convert(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */); + System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2+", maxDelta "+maxDelta); + System.err.printf("Conv2 Data: %s%n", Bitstream.toHexBinString(true, imageConv2.getPixels(), 0, srcFmt.comp.bytesPerPixel())); + final byte[] destReComponents = new byte[4]; + getComponentData(destFmt, srcFmt, destReComponents); + System.err.printf("DestRe Data: %s%n", Bitstream.toHexBinString(true, destReComponents, 0, srcFmt.comp.bytesPerPixel())); + testComponents(imageConv2, 0, 0, destReComponents, maxDelta); + testComponents(imageConv2, width-1, height-1, destReComponents, maxDelta); + /** + * Due to 'dead' components or value range re-scale, + * identity comparison on byte level is not correct. + * if( imageSrc.getStride() == imageConv1.getStride() ) { Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels()); } + */ } } } } - private void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) { + static void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) { if( x1 + w >= image.getSize().getWidth() ) { x1 = image.getSize().getWidth() - w; } @@ -280,7 +576,7 @@ public class TestPixelFormatUtil00NEWT extends UITestCase { } System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":"); final ByteBuffer bb = image.getPixels(); - final int bpp = image.getPixelformat().bytesPerPixel(); + final int bpp = image.getPixelformat().comp.bytesPerPixel(); for(int y = y1; y< y1+h; y++) { System.err.printf("%n[%3d][%3d] ", x1, y); int o = y * image.getStride()+x1*bpp; @@ -311,51 +607,58 @@ public class TestPixelFormatUtil00NEWT extends UITestCase { } System.err.println(); } - private void testComponents(final PixelRectangle image, final int x, final int y, final byte[] components) { + + static final void assertEquals(final int a, final int b, final int maxDelta) { + final int d = Math.abs( a - b ); + Assert.assertTrue(String.format("Not equal: abs(%s - %s) = %d, > %d maxDelta", + Bitstream.toHexBinString(true, a, 8), Bitstream.toHexBinString(true, b, 8), d, maxDelta), + d <= maxDelta); + } + static final boolean equals(final int a, final int b, final int maxDelta) { + final int d = Math.abs( a - b ); + return d <= maxDelta; + } + + /** + * + * @param image actual data + * @param x position in actual data + * @param y position in actual data + * @param expData expected data + * @param maxDelta the maximum delta between expected {@code components} and actual {@code image} data + */ + static void testComponents(final PixelRectangle image, final int x, final int y, final byte[] expData, final int maxDelta) { dumpComponents(image, x, y, 3, 3); + final PixelFormat.Composition imgComp = image.getPixelformat().comp; final ByteBuffer bb = image.getPixels(); - final int bpp = image.getPixelformat().bytesPerPixel(); - int o = y * image.getStride()+x*bpp; - switch(bpp) { - case 1: { - final byte c1 = bb.get(o++); - final boolean equal = c1==components[0]; - System.err.printf("Test [%3d][%3d] exp 0x%02X == has 0x%02X : %b%n", - x, y, components[0], c1, equal ); - Assert.assertEquals(components[0], c1); - } - break; - case 2: { - final byte c1 = bb.get(o++), c2 = bb.get(o++); - final boolean equal = c1==components[0] && c2==components[1]; - System.err.printf("Test [%3d][%3d] exp 0x%02X%02X == has 0x%02X%02X : %b%n", - x, y, components[1], components[0], c2, c1, equal ); - Assert.assertEquals(components[0], c1); - Assert.assertEquals(components[1], c2); - } - break; - case 3: { - final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++); - final boolean equal = c1==components[0] && c2==components[1] && c3==components[2]; - System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X == has 0x%02X%02X%02X : %b%n", - x, y, components[2], components[1], components[0], c3, c2, c1, equal ); - Assert.assertEquals(components[0], c1); - Assert.assertEquals(components[1], c2); - Assert.assertEquals(components[2], c3); - } - break; - case 4: { - final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++), c4 = bb.get(o++); - final boolean equal = c1==components[0] && c2==components[1] && c3==components[2] && c4==components[3]; - System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X%02X == has 0x%02X%02X%02X%02X : %b%n", - x, y, components[3], components[2], components[1], components[0], c4, c3, c2, c1, equal ); - Assert.assertEquals(components[0], c1); - Assert.assertEquals(components[1], c2); - Assert.assertEquals(components[2], c3); - Assert.assertEquals(components[3], c4); - } - break; + final int bytesPerPixel = imgComp.bytesPerPixel(); + final int compCount = imgComp.componenCount(); + final int[] compBitCount = imgComp.componentBitCount(); + + final int srcPixOffset = y * image.getStride()+x*bytesPerPixel; + final int bbPos = bb.position(); + bb.position(bbPos+srcPixOffset); + + final long srcPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), bb, true); + final int[] srcComponents = new int[compCount]; + final long expPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), expData, 0); + final int[] expComponents = new int[compCount]; + boolean equal = true; + for(int i=0; i<compCount; i++) { + srcComponents[i] = imgComp.decodeSingleI64(srcPix64, i); + expComponents[i] = imgComp.decodeSingleI64(expPix64, i); + equal = equal && equals(srcComponents[i], expComponents[i], maxDelta); } + System.err.printf("Test [%3d][%3d] exp ", x, y); + for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, expComponents[i], compBitCount[i])); } + System.err.printf("==%nTest [%3d][%3d] has ", x, y); + for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, srcComponents[i], compBitCount[i])); } + System.err.printf(": equal %b%n%n", equal); + for(int i=0; i<compCount; i++) { + assertEquals(srcComponents[i], expComponents[i], maxDelta); + } + + bb.position(bbPos); } public static void main(final String args[]) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java index eba920032..37c8c4494 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java @@ -40,6 +40,7 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import com.jogamp.common.util.Bitstream; import com.jogamp.common.util.IOUtil; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.PNGPixelRect; @@ -86,15 +87,21 @@ public class TestPixelFormatUtil01NEWT extends UITestCase { final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */); System.err.println("PNGPixelRect - Orig: "+image1); + System.err.printf("Image Data: %s%n", Bitstream.toHexBinString(true, image1.getPixels(), 0, image1.getPixelformat().comp.bytesPerPixel())); + TestPixelFormatUtil00NEWT.dumpComponents(image1, 0, 0, 3, 3); final PixelFormat[] formats = new PixelFormat[] { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 }; for(int i=0; i<formats.length; i++) { final PixelFormat destFmt = formats[i]; System.err.println("CONVERT["+i+"]: "+srcFmt+" -> "+destFmt); - final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */); + final PixelRectangle imageConv1 = PixelFormatUtil.convert(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */); System.err.println("PNGPixelRect - Conv1: "+imageConv1); - final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */); + System.err.printf("Conv1 Data: %s%n", Bitstream.toHexBinString(true, imageConv1.getPixels(), 0, imageConv1.getPixelformat().comp.bytesPerPixel())); + TestPixelFormatUtil00NEWT.dumpComponents(imageConv1, 0, 0, 3, 3); + final PixelRectangle imageConv2 = PixelFormatUtil.convert(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */); System.err.println("PNGPixelRect - Conv2: "+imageConv2); + System.err.printf("Conv2 Data: %s%n", Bitstream.toHexBinString(true, imageConv2.getPixels(), 0, imageConv2.getPixelformat().comp.bytesPerPixel())); + TestPixelFormatUtil00NEWT.dumpComponents(imageConv2, 0, 0, 3, 3); Assert.assertEquals(image1.getPixels(), imageConv2.getPixels()); } } |