JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestPixelFormatUtil00NEWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2014 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.opengl.test.junit.jogl.util.texture;
29
30import java.io.IOException;
31import java.net.MalformedURLException;
32import java.nio.ByteBuffer;
33import java.nio.ByteOrder;
34
35import com.jogamp.nativewindow.util.Dimension;
36import com.jogamp.nativewindow.util.PixelFormat;
37import com.jogamp.nativewindow.util.PixelFormatUtil;
38import com.jogamp.nativewindow.util.PixelRectangle;
39import com.jogamp.nativewindow.util.PixelFormat.CType;
40
41import org.junit.Assert;
42import org.junit.Test;
43import org.junit.FixMethodOrder;
44import org.junit.runners.MethodSorters;
45
46import com.jogamp.common.util.Bitstream;
47import com.jogamp.opengl.test.junit.util.UITestCase;
48
49/**
50 * Testing PixelFormatUtil's Conversion using synthetic test data
51 * including strides, endian-order and all PixelFormat conversions.
52 */
53@FixMethodOrder(MethodSorters.NAME_ASCENDING)
55 static final byte undef_val = (byte)0xFF;
56 static final PixelFormat.Composition comp_val = PixelFormat.RGBA8888.comp;
57 static final float red___valF;
58 static final float green_valF;
59 static final float blue__valF;
60 static final float alpha_valF;
61 static final float lum___valF;
62 static {
63 // Using am equal stepping of 0x30 = 48 between each RGBA and undefined values,
64 // dividing 0xff equally by 5 excluding zero.
65 final byte red___val = (byte)0x30;
66 final byte green_val = (byte)0x60;
67 final byte blue__val = (byte)0x90;
68 final byte alpha_val = (byte)0xC0;
69 red___valF = comp_val.toFloat(red___val, 0, false);
70 green_valF = comp_val.toFloat(green_val, 1, false);
71 blue__valF = comp_val.toFloat(blue__val, 2, false);
72 alpha_valF = comp_val.toFloat(alpha_val, 3, false);
73 lum___valF = ( red___valF + green_valF + blue__valF ) / 3f;
74 }
75
76 @Test
77 public void testConversion00() throws InterruptedException, IOException, MalformedURLException {
78 {
80 final PixelFormat.Composition comp = fmt.comp;
81 System.err.printf("%s, %s:%n", fmt, comp);
82 final int u16_alpha = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false),
83 (byte)comp.fromFloat(green_valF, 0, false),
84 (byte)comp.fromFloat(blue__valF, 0, false),
85 (byte)comp.fromFloat(alpha_valF, 0, false));
86 final int u16_undef = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false),
87 (byte)comp.fromFloat(green_valF, 0, false),
88 (byte)comp.fromFloat(blue__valF, 0, false),
89 undef_val);
90 System.err.printf(" u16_alpha %s%n", Bitstream.toHexBinString(true, u16_alpha, comp.bitsPerPixel()));
91 System.err.printf(" u16_undef %s%n", Bitstream.toHexBinString(true, u16_undef, comp.bitsPerPixel()));
92 {
93 final byte c4NormI8_alpha = (byte)comp.fromFloat(alpha_valF, 0, false);
94 final byte c4NormI8_undef = undef_val;
95 final int compBitShift = 15;
96 final int compMask = 0x1;
97 final int v_alpha = ( c4NormI8_alpha & compMask ) << compBitShift ;
98 final int v_undef = ( c4NormI8_undef & compMask ) << compBitShift ;
99 System.err.printf(" xx_alpha %s%n", Bitstream.toHexBinString(true, v_alpha, comp.bitsPerPixel()));
100 System.err.printf(" xx_undef %s%n", Bitstream.toHexBinString(true, v_undef, comp.bitsPerPixel()));
101 }
102 }
103 {
104 final int r8 = 0x30;
105 final int g8 = 0x60;
106 final int b8 = 0x90;
107 final int a8 = 0xC0;
108
109 final int l1 = 0x1;
110 final int r5 = 0x6;
111 final int g6 = 0xC;
112 final int b5 = 0x6;
113
114 final PixelFormat rgba8888Fmt = PixelFormat.RGBA8888;
115 final PixelFormat.Composition rgba8888Comp = rgba8888Fmt.comp;
116 final PixelFormat rgb565Fmt = PixelFormat.RGB565;
117 final PixelFormat.Composition rgb565Comp = rgb565Fmt.comp;
118 final PixelFormat lumFmt = PixelFormat.LUMINANCE;
119 final PixelFormat.Composition lumComp = lumFmt.comp;
120 System.err.printf("%s, %s -> %s %s%n", rgb565Fmt, rgb565Comp, lumFmt, lumComp);
121
122 {
123 final float r8f = rgba8888Comp.toFloat(r8, 0, false);
124 final int r8fi = rgba8888Comp.fromFloat(r8f, 0, false);
125 final float g8f = rgba8888Comp.toFloat(g8, 1, false);
126 final int g8fi = rgba8888Comp.fromFloat(g8f, 1, false);
127 final float b8f = rgba8888Comp.toFloat(b8, 2, false);
128 final int b8fi = rgba8888Comp.fromFloat(b8f, 2, false);
129 final float a8f = rgba8888Comp.toFloat(a8, 3, false);
130 final int a8fi = rgba8888Comp.fromFloat(a8f, 3, false);
131
132 System.err.printf("res00.0.r %s -> %f -> %s%n", Bitstream.toHexBinString(true, r8, 8), r8f, Bitstream.toHexBinString(true, r8fi, 8));
133 System.err.printf("res00.0.g %s -> %f -> %s%n", Bitstream.toHexBinString(true, g8, 8), g8f, Bitstream.toHexBinString(true, g8fi, 8));
134 System.err.printf("res00.0.b %s -> %f -> %s%n", Bitstream.toHexBinString(true, b8, 8), b8f, Bitstream.toHexBinString(true, b8fi, 8));
135 System.err.printf("res00.0.a %s -> %f -> %s%n", Bitstream.toHexBinString(true, a8, 8), a8f, Bitstream.toHexBinString(true, a8fi, 8));
136 }
137 {
138 final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f;
139 final int res00 = rgba8888Comp.fromFloat(res00_0, 0, false);
140 System.err.printf("res01.0 ( %f + %f + %f ) / 3f = %f -> %s%n",
141 red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8));
142 }
143 {
144 final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f;
145 final int res00 = lumComp.fromFloat(res00_0, 0, false);
146 System.err.printf("res02.1 ( %f + %f + %f ) / 3f = %f -> %s%n",
147 red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8));
148 }
149 {
150 // sourceNorm static -> lum
151 final int rl1 = lumComp.fromFloat(red___valF, 0, false);
152 final int gl1 = lumComp.fromFloat(green_valF, 0, false);
153 final int bl1 = lumComp.fromFloat(blue__valF, 0, false);
154 final float rl2 = lumComp.toFloat(rl1, 0, false);
155 final float gl2 = lumComp.toFloat(gl1, 0, false);
156 final float bl2 = lumComp.toFloat(bl1, 0, false);
157 System.err.printf("res20.l1 ( %s + %s + %s )%n",
158 Bitstream.toHexBinString(true, rl1, 8),
159 Bitstream.toHexBinString(true, gl1, 8),
160 Bitstream.toHexBinString(true, bl1, 8));
161 System.err.printf("res20.l2 ( %f + %f + %f )%n", rl2, gl2, bl2);
162 final float res02_l2_0 = ( rl2 + gl2 + bl2 ) / 3f;
163 final int res02_l2_x = lumComp.fromFloat(res02_l2_0, 0, false);
164 System.err.printf("res20.l3 ( %f + %f + %f ) / 3f = %f -> %s%n",
165 rl2, gl2, bl2, res02_l2_0, Bitstream.toHexBinString(true, res02_l2_x, 8));
166
167 // rescale lum -> rgb565
168 final int r_1 = rgb565Comp.fromFloat(rl2, 0, false);
169 final int g_1 = rgb565Comp.fromFloat(gl2, 1, false);
170 final int b_1 = rgb565Comp.fromFloat(bl2, 2, false);
171 final float r_2 = rgb565Comp.toFloat(r_1, 0, false);
172 final float g_2 = rgb565Comp.toFloat(g_1, 1, false);
173 final float b_2 = rgb565Comp.toFloat(b_1, 2, false);
174 System.err.printf("res20._1 ( %s + %s + %s )%n",
175 Bitstream.toHexBinString(true, r_1, 8),
176 Bitstream.toHexBinString(true, g_1, 8),
177 Bitstream.toHexBinString(true, b_1, 8));
178 System.err.printf("res20._2 ( %f + %f + %f )%n", r_2, g_2, b_2);
179 final float res02__3_0 = ( r_2 + g_2 + b_2 ) / 3f;
180 final int res02__3_x = lumComp.fromFloat(res02__3_0, 0, false);
181 System.err.printf("res20._3 ( %f + %f + %f ) / 3f = %f -> %s%n",
182 r_2, g_2, b_2, res02__3_0, Bitstream.toHexBinString(true, res02__3_x, 8));
183 }
184 {
185 // sourceNorm static -> lum
186 // rescale lum -> rgb565
187 final float rF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 0, red___valF), 0, false);
188 final float gF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 1, green_valF), 1, false);
189 final float bF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 2, blue__valF), 2, false);
190 final float res01_0 = ( rF + gF + bF ) / 3f;
191 final int res01 = lumComp.fromFloat(res01_0, 0, false);
192 System.err.printf("res30.xx ( %f + %f + %f ) / 3f = %f -> %s%n",
193 rF, gF, bF, res01_0, Bitstream.toHexBinString(true, res01, 8));
194 }
195 {
196 final float rF = rgb565Comp.toFloat(r5, 0, false);
197 final float gF = rgb565Comp.toFloat(g6, 1, false);
198 final float bF = rgb565Comp.toFloat(b5, 2, false);
199
200 final float lF = ( rF + gF + bF ) / 3f;
201 final int res00 = lumComp.fromFloat(lF, 0, false);
202
203 System.err.printf("res40 ( %f + %f + %f ) / 3f = %s%n",
204 rF, gF, bF, Bitstream.toHexBinString(true, res00, 8));
205 }
206 }
207
208 }
209
210 @Test
211 public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
212 testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
213 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
214 }
215 @Test
216 public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
217 testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */,
218 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
219 }
220 @Test
221 public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
222 testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
223 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
224 }
225 @Test
226 public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
227 testConversionImpl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
228 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
229 }
230 @Test
231 public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
232 testConversionImpl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
233 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
234 }
235
236 /**
237 * Note: Fixes bit-rounding errors, i.e. RGBA5551: A 0.6f -> 0x01 -> 1f ... -> RGBA8888: A 0xff
238 */
239 static final float sourceNorm(final PixelFormat.Composition srcComp, final int sIdx, final float f) {
240 if( sIdx >= 0 && sIdx < srcComp.componentCount() ) {
241 return srcComp.toFloat(srcComp.fromFloat(f, sIdx, false), sIdx, false);
242 } else {
243 return 0f;
244 }
245 }
246 static final byte rescaleComp(final PixelFormat.Composition srcComp, final int sIdx,
247 final PixelFormat.Composition dstComp, final int dIdx, final float f) {
248 if( dIdx >= 0 && dIdx < dstComp.componentCount() ) {
249 return (byte)dstComp.fromFloat(sourceNorm(srcComp, sIdx, f), dIdx, false);
250 } else {
251 return (byte)0;
252 }
253 }
254 static final void getComponentData(final PixelFormat srcFmt, final PixelFormat dstFmt, final byte[] components) {
255 final PixelFormat.Composition srcComp = srcFmt.comp;
256 final PixelFormat.Composition dstComp = dstFmt.comp;
257 final byte b1, b2, b3, b4;
258 int u16;
259 if( PixelFormat.LUMINANCE == srcFmt ) {
260 // LUM -> Fmt Conversion
261 switch(dstFmt) {
262 case LUMINANCE:
263 b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
264 b2 = undef_val;
265 b3 = undef_val;
266 b4 = undef_val;
267 break;
268 case RGB565:
269 case BGR565:
270 u16 = dstComp.encode3CompI8(
271 rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
272 rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
273 rescaleComp(srcComp, 0, dstComp, 2, lum___valF));
274 b1 = (byte)( u16 & 0xff );
275 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
276 b3 = undef_val;
277 b4 = undef_val;
278 break;
279 case RGBA5551:
280 u16 = dstComp.encode4CompI8(
281 rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
282 rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
283 rescaleComp(srcComp, 0, dstComp, 2, lum___valF),
284 undef_val);
285 b1 = (byte)( u16 & 0xff );
286 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
287 b3 = undef_val;
288 b4 = undef_val;
289 break;
290 case ABGR1555:
291 u16 = dstComp.encode4CompI8(
292 undef_val,
293 rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
294 rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
295 rescaleComp(srcComp, 0, dstComp, 2, lum___valF) );
296 b1 = (byte)( u16 & 0xff );
297 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
298 b3 = undef_val;
299 b4 = undef_val;
300 break;
301 case BGRx8888:
302 case RGBx8888:
303 case RGB888:
304 case BGR888:
305 case RGBA8888:
306 b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
307 b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
308 b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
309 b4 = undef_val;
310 break;
311 case ABGR8888:
312 case ARGB8888:
313 b1 = undef_val;
314 b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
315 b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
316 b4 = rescaleComp(srcComp, 0, dstComp, 3, lum___valF);
317 break;
318 case BGRA8888:
319 b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
320 b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
321 b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
322 b4 = undef_val;
323 break;
324 default:
325 throw new InternalError("Unhandled format "+dstFmt);
326 }
327 } else {
328 final int srcIdxR = srcComp.find(CType.R);
329 final int srcIdxG = srcComp.find(CType.G);
330 final int srcIdxB = srcComp.find(CType.B);
331 final int srcIdxA = srcComp.find(CType.A);
332 final boolean srcHasAlpha = 0 <= srcIdxA;
333 final boolean srcHasRGB = 0 <= srcIdxR && 0 <= srcIdxG && 0 <= srcIdxB;
334 // 1:1 values
335 switch(dstFmt) {
336 case LUMINANCE:
337 if( srcHasRGB ) {
338 final float rF = sourceNorm(srcComp, srcIdxR, red___valF);
339 final float gF = sourceNorm(srcComp, srcIdxG, green_valF);
340 final float bF = sourceNorm(srcComp, srcIdxB, blue__valF);
341 b1 = (byte)dstComp.fromFloat( ( rF + gF + bF ) / 3f, 0, false);
342 b2 = undef_val;
343 b3 = undef_val;
344 b4 = undef_val;
345 } else {
346 b1 = rescaleComp(srcComp, 0, dstComp, 0, red___valF);
347 b2 = undef_val;
348 b3 = undef_val;
349 b4 = undef_val;
350 }
351 break;
352 case RGB565:
353 u16 = dstComp.encode3CompI8(
354 rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF),
355 rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
356 rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF));
357 b1 = (byte)( u16 & 0xff );
358 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
359 b3 = undef_val;
360 b4 = undef_val;
361 break;
362 case BGR565:
363 u16 = dstComp.encode3CompI8(
364 rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF),
365 rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
366 rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF));
367 b1 = (byte)( u16 & 0xff );
368 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
369 b3 = undef_val;
370 b4 = undef_val;
371 break;
372 case RGBA5551:
373 u16 = dstComp.encode4CompI8(
374 rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF),
375 rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
376 rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF),
377 srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF) : undef_val);
378 b1 = (byte)( u16 & 0xff );
379 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
380 b3 = undef_val;
381 b4 = undef_val;
382 break;
383 case ABGR1555:
384 u16 = dstComp.encode4CompI8(
385 srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF) : undef_val,
386 rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF),
387 rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF),
388 rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF) );
389 b1 = (byte)( u16 & 0xff );
390 b2 = (byte)( ( u16 >>> 8 ) & 0xff );
391 b3 = undef_val;
392 b4 = undef_val;
393 break;
394 case RGBx8888:
395 case RGB888:
396 b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF);
397 b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
398 b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF);
399 b4 = undef_val;
400 break;
401 case BGRx8888:
402 case BGR888:
403 b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF);
404 b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
405 b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF);
406 b4 = undef_val;
407 break;
408 case RGBA8888:
409 b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF);
410 b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
411 b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF);
412 if( srcHasAlpha ) {
413 b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF);
414 } else {
415 b4 = undef_val;
416 }
417 break;
418 case ABGR8888:
419 if( srcHasAlpha ) {
420 b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF);
421 } else {
422 b1 = undef_val;
423 }
424 b2 = rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF);
425 b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF);
426 b4 = rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF);
427 break;
428 case BGRA8888:
429 b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF);
430 b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
431 b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF);
432 if( srcHasAlpha ) {
433 b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF);
434 } else {
435 b4 = undef_val;
436 }
437 break;
438 case ARGB8888:
439 if( srcHasAlpha ) {
440 b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF);
441 } else {
442 b1 = undef_val;
443 }
444 b2 = rescaleComp(srcComp, srcIdxR, dstComp, 1, red___valF);
445 b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF);
446 b4 = rescaleComp(srcComp, srcIdxB, dstComp, 3, blue__valF);
447 break;
448 default:
449 throw new InternalError("Unhandled format "+dstFmt);
450 }
451 }
452 components[0] = b1;
453 components[1] = b2;
454 components[2] = b3;
455 components[3] = b4;
456 }
457 private void testConversionImpl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented,
458 final int destMinStrideInBytes, final boolean destIsGLOriented)
459 throws InterruptedException, IOException, MalformedURLException
460 {
461 System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+
462 ", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
463
464 // final PixelFormat[] srcFormats = { PixelFormat.LUMINANCE };
465 // final PixelFormat[] dstFormats = { PixelFormat.RGBx8888 };
466 // final PixelFormat[] dstFormats = { PixelFormat.RGB5551 };
467 // final PixelFormat[] dstFormats = { PixelFormat.RGB888 };
468 // final PixelFormat[] srcFormats = { PixelFormat.RGB888 };
469 // final PixelFormat[] dstFormats = { PixelFormat.RGB565 };
470 final PixelFormat[] srcFormats = PixelFormat.values();
471 final PixelFormat[] dstFormats = PixelFormat.values();
472 final int width = 64, height = 64;
473
474 for(int i=0; i<srcFormats.length; i++) {
475 final PixelFormat srcFmt = srcFormats[i];
476 final int srcBpp = srcFmt.comp.bytesPerPixel();
477 final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp);
478 final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder);
479 final byte[] srcData = new byte[4];
480 getComponentData(srcFmt, srcFmt, srcData);
481 for(int y=0; y<height; y++) {
482 int o = y*srcStrideBytes;
483 for(int x=0; x<width; x++) {
484 switch(srcFmt) {
485 case LUMINANCE:
486 srcPixels.put(o++, srcData[0]);
487 break;
488 case BGR565:
489 case RGB565:
490 case ABGR1555:
491 case RGBA5551:
492 srcPixels.put(o++, srcData[0]);
493 srcPixels.put(o++, srcData[1]);
494 break;
495 case RGB888:
496 case BGR888:
497 srcPixels.put(o++, srcData[0]);
498 srcPixels.put(o++, srcData[1]);
499 srcPixels.put(o++, srcData[2]);
500 break;
501 case RGBx8888:
502 case BGRx8888:
503 case RGBA8888:
504 case ABGR8888:
505 case BGRA8888:
506 case ARGB8888:
507 srcPixels.put(o++, srcData[0]);
508 srcPixels.put(o++, srcData[1]);
509 srcPixels.put(o++, srcData[2]);
510 srcPixels.put(o++, srcData[3]);
511 break;
512 default:
513 throw new InternalError("Unhandled format "+srcFmt);
514 }
515 }
516 }
517 final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height),
518 srcStrideBytes, srcIsGLOriented, srcPixels);
519
520 System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc);
521 System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp);
522 System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel()));
523 testComponents(imageSrc, 0, 0, srcData, 0);
524 testComponents(imageSrc, width-1, height-1, srcData, 0);
525
526 final int maxDelta = 12;
527
528 for(int j=0; j<dstFormats.length; j++) {
529 final PixelFormat destFmt = dstFormats[j];
530 System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt);
531 final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.comp.bytesPerPixel());
532 final byte[] destComponents = new byte[4];
533 getComponentData(srcFmt, destFmt, destComponents);
534 System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp);
535 System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel()));
536 System.err.printf("Dest %s, %s%n", destFmt, destFmt.comp);
537 System.err.printf("Dest Data: %s%n", Bitstream.toHexBinString(true, destComponents, 0, destFmt.comp.bytesPerPixel()));
538 final PixelRectangle imageConv1 = PixelFormatUtil.convert(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */);
539 System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1+", maxDelta "+maxDelta);
540 System.err.printf("Conv1 Data: %s%n", Bitstream.toHexBinString(true, imageConv1.getPixels(), 0, destFmt.comp.bytesPerPixel()));
541 testComponents(imageConv1, 0, 0, destComponents, maxDelta);
542 testComponents(imageConv1, width-1, height-1, destComponents, maxDelta);
543 if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) {
544 // Cannot convert: RGB* -> LUM -> RGB*
545 System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM");
546 } else if( srcFmt.comp.componentCount() > destFmt.comp.componentCount() ) {
547 // Cannot convert back if: src.componentCount > dest.componentCount
548 System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount");
549 } else {
550 final PixelRectangle imageConv2 = PixelFormatUtil.convert(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */);
551 System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2+", maxDelta "+maxDelta);
552 System.err.printf("Conv2 Data: %s%n", Bitstream.toHexBinString(true, imageConv2.getPixels(), 0, srcFmt.comp.bytesPerPixel()));
553 final byte[] destReComponents = new byte[4];
554 getComponentData(destFmt, srcFmt, destReComponents);
555 System.err.printf("DestRe Data: %s%n", Bitstream.toHexBinString(true, destReComponents, 0, srcFmt.comp.bytesPerPixel()));
556 testComponents(imageConv2, 0, 0, destReComponents, maxDelta);
557 testComponents(imageConv2, width-1, height-1, destReComponents, maxDelta);
558 /**
559 * Due to 'dead' components or value range re-scale,
560 * identity comparison on byte level is not correct.
561 *
562 if( imageSrc.getStride() == imageConv1.getStride() ) {
563 Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels());
564 }
565 */
566 }
567 }
568 }
569 }
570 static void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) {
571 if( x1 + w >= image.getSize().getWidth() ) {
572 x1 = image.getSize().getWidth() - w;
573 }
574 if( y1 + h >= image.getSize().getHeight() ) {
575 y1 = image.getSize().getHeight() - h;
576 }
577 System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":");
578 final ByteBuffer bb = image.getPixels();
579 final int bpp = image.getPixelformat().comp.bytesPerPixel();
580 for(int y = y1; y< y1+h; y++) {
581 System.err.printf("%n[%3d][%3d] ", x1, y);
582 int o = y * image.getStride()+x1*bpp;
583 for(int x = x1; x< x1+w; x++) {
584 switch(bpp) {
585 case 1: {
586 final byte a = bb.get(o++);
587 System.err.printf(" 0x%02X", a);
588 }
589 break;
590 case 2: {
591 final byte a = bb.get(o++), b = bb.get(o++);
592 System.err.printf(" 0x%02X%02X", b, a);
593 }
594 break;
595 case 3: {
596 final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++);
597 System.err.printf(" 0x%02X%02X%02X", c, b, a);
598 }
599 break;
600 case 4: {
601 final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++), d = bb.get(o++);
602 System.err.printf(" 0x%02X%02X%02X%02X", d, c, b, a);
603 }
604 break;
605 }
606 }
607 }
608 System.err.println();
609 }
610
611 static final void assertEquals(final int a, final int b, final int maxDelta) {
612 final int d = Math.abs( a - b );
613 Assert.assertTrue(String.format("Not equal: abs(%s - %s) = %d, > %d maxDelta",
614 Bitstream.toHexBinString(true, a, 8), Bitstream.toHexBinString(true, b, 8), d, maxDelta),
615 d <= maxDelta);
616 }
617 static final boolean equals(final int a, final int b, final int maxDelta) {
618 final int d = Math.abs( a - b );
619 return d <= maxDelta;
620 }
621
622 /**
623 *
624 * @param image actual data
625 * @param x position in actual data
626 * @param y position in actual data
627 * @param expData expected data
628 * @param maxDelta the maximum delta between expected {@code components} and actual {@code image} data
629 */
630 static void testComponents(final PixelRectangle image, final int x, final int y, final byte[] expData, final int maxDelta) {
631 dumpComponents(image, x, y, 3, 3);
632 final PixelFormat.Composition imgComp = image.getPixelformat().comp;
633 final ByteBuffer bb = image.getPixels();
634 final int bytesPerPixel = imgComp.bytesPerPixel();
635 final int compCount = imgComp.componentCount();
636 final int[] compBitCount = imgComp.componentBitCount();
637
638 final int srcPixOffset = y * image.getStride()+x*bytesPerPixel;
639 final int bbPos = bb.position();
640 bb.position(bbPos+srcPixOffset);
641
642 final long srcPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), bb, true);
643 final int[] srcComponents = new int[compCount];
644 final long expPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), expData, 0);
645 final int[] expComponents = new int[compCount];
646 boolean equal = true;
647 for(int i=0; i<compCount; i++) {
648 srcComponents[i] = imgComp.decodeSingleI64(srcPix64, i);
649 expComponents[i] = imgComp.decodeSingleI64(expPix64, i);
650 equal = equal && equals(srcComponents[i], expComponents[i], maxDelta);
651 }
652 System.err.printf("Test [%3d][%3d] exp ", x, y);
653 for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, expComponents[i], compBitCount[i])); }
654 System.err.printf("==%nTest [%3d][%3d] has ", x, y);
655 for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, srcComponents[i], compBitCount[i])); }
656 System.err.printf(": equal %b%n%n", equal);
657 for(int i=0; i<compCount; i++) {
658 assertEquals(srcComponents[i], expComponents[i], maxDelta);
659 }
660
661 bb.position(bbPos);
662 }
663
664 public static void main(final String args[]) {
665 org.junit.runner.JUnitCore.main(TestPixelFormatUtil00NEWT.class.getName());
666 }
667}
Testing PixelFormatUtil's Conversion using synthetic test data including strides, endian-order and al...
LUMINANCE
Stride is 8 bits, 8 bits per pixel, 1 component of 8 bits.
final Composition comp
Unique Pixel Composition, i.e.
RGBA8888
Stride is 32 bits, 32 bits per pixel, 4 uniform components of 8 bits.
RGBA5551
Stride is 16 bits, 16 bits per pixel, 4 discrete components.
RGB565
Stride is 16 bits, 16 bits per pixel, 3 discrete components.
float toFloat(final int i32, final int cIdx, final boolean i32Shifted)
int encode4CompI8(final byte c1NormI8, final byte c2NormI8, final byte c3NormI8, final byte c4NormI8)