public static void convert( final ComponentMap cmap, final PixelFormat.Composition dstComp, final Bitstream<ByteBuffer> dstBitStream, final PixelFormat.Composition srcComp, final Bitstream<ByteBuffer> srcBitStream) throws IllegalStateException, IOException { final int sCompCount = srcComp.componentCount(); final int dCompCount = dstComp.componentCount(); final int[] sc = new int[sCompCount]; final int[] dcDef = new int[dCompCount]; final int[] srcCompBitCount = srcComp.componentBitCount(); final int[] srcCompBitMask = srcComp.componentBitMask(); final int[] dstCompBitCount = dstComp.componentBitCount(); // Fill w/ source values for (int sIdx = 0; sIdx < sCompCount; sIdx++) { sc[sIdx] = srcBitStream.readBits31(srcCompBitCount[sIdx]) & srcCompBitMask[sIdx]; } srcBitStream.skip(srcComp.bitStride() - srcComp.bitsPerPixel()); // Cache missing defaults for (int i = 0; i < dCompCount; i++) { dcDef[i] = dstComp.defaultValue(i, false); } if (1 == dCompCount && PixelFormat.CType.Y == dstComp.componentOrder()[0] && cmap.hasSrcRGB) { // RGB[A] -> Y conversion final int r = sc[cmap.srcRGBA[0]]; final int g = sc[cmap.srcRGBA[1]]; final int b = sc[cmap.srcRGBA[2]]; final float rF = srcComp.toFloat(r, cmap.srcRGBA[0], false); final float gF = srcComp.toFloat(g, cmap.srcRGBA[1], false); final float bF = srcComp.toFloat(b, cmap.srcRGBA[2], false); final int a; final float aF; /** * if( 0 <= cmap.srcRGBA[3] ) { // disable premultiplied-alpha a = sc[cmap.srcRGBA[3]]; aF = * srcComp.toFloat(a, false, cmap.srcRGBA[3]); } else */ { a = 1; aF = 1f; } final float lF = (rF + gF + bF) * aF / 3f; final int v = dstComp.fromFloat(lF, 0, false); dstBitStream.writeBits31(dstCompBitCount[0], v); dstBitStream.skip(dstComp.bitStride() - dstComp.bitsPerPixel()); if (DEBUG) { if (srcBitStream.position() <= 8 * 4) { System.err.printf( "convert: rgb[a] -> Y: rgb 0x%02X 0x%02X 0x%02X 0x%02X -> %f %f %f %f" + " -> %f -> dstC 0 0x%08X (%d bits: %s)%n", r, g, b, a, rF, gF, bF, aF, lF, v, dstCompBitCount[0], Bitstream.toBinString(true, v, dstCompBitCount[0])); } } return; } for (int dIdx = 0; dIdx < dCompCount; dIdx++) { int sIdx; if (0 <= (sIdx = cmap.dst2src[dIdx])) { final float f = srcComp.toFloat(sc[sIdx], sIdx, false); final int v = dstComp.fromFloat(f, dIdx, false); dstBitStream.writeBits31(dstCompBitCount[dIdx], v); if (DEBUG) { if (srcBitStream.position() <= 8 * 4) { System.err.printf( "convert: srcC %d: 0x%08X -> %f -> dstC %d 0x%08X (%d bits: %s)%n", sIdx, sc[sIdx], f, dIdx, v, dstCompBitCount[dIdx], Bitstream.toBinString(true, v, dstCompBitCount[dIdx])); } } } else { dstBitStream.writeBits31(dstCompBitCount[dIdx], dcDef[dIdx]); if (DEBUG) { if (srcBitStream.position() <= 8 * 4) { System.err.printf( "convert: srcC %d: undef -> dstC %d 0x%08X (%d bits: %s)%n", sIdx, dIdx, dcDef[dIdx], dstCompBitCount[dIdx], Bitstream.toBinString(true, dcDef[dIdx], dstCompBitCount[dIdx])); } } } } dstBitStream.skip(dstComp.bitStride() - dstComp.bitsPerPixel()); return; }
/** * @param width width of the to be converted pixel rectangle * @param height height of the to be converted pixel rectangle * @param src_bb {@link ByteBuffer} source * @param src_fmt source {@link PixelFormat} * @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, * <i>origin at bottom left</i>, otherwise <i>origin at top left</i>. * @param src_lineStride line stride in byte-size for source, i.e. byte count from one line to the * next. Must be >= {@link PixelFormat.Composition#bytesPerPixel() * src_fmt.comp.bytesPerPixel()} * width or {@code zero} for default stride. * @param dst_bb {@link ByteBuffer} sink * @param dst_fmt destination {@link PixelFormat} * @param dst_glOriented if true, the source memory is laid out in OpenGL's coordinate system, * <i>origin at bottom left</i>, otherwise <i>origin at top left</i>. * @param dst_lineStride line stride in byte-size for destination, i.e. byte count from one line * to the next. Must be >= {@link PixelFormat.Composition#bytesPerPixel() * dst_fmt.comp.bytesPerPixel()} * width or {@code zero} for default stride. * @throws IllegalStateException * @throws IllegalArgumentException if {@code src_lineStride} or {@code dst_lineStride} is invalid */ public static void convert( final int width, final int height, final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, int src_lineStride, final ByteBuffer dst_bb, final PixelFormat dst_fmt, final boolean dst_glOriented, int dst_lineStride) throws IllegalStateException, IllegalArgumentException { final PixelFormat.Composition src_comp = src_fmt.comp; final PixelFormat.Composition dst_comp = dst_fmt.comp; final int src_bpp = src_comp.bytesPerPixel(); final int dst_bpp = dst_comp.bytesPerPixel(); if (0 != src_lineStride) { if (src_lineStride < src_bpp * width) { throw new IllegalArgumentException( String.format( "Invalid %s stride %d, must be greater than bytesPerPixel %d * width %d", "source", src_lineStride, src_bpp, width)); } } else { src_lineStride = src_bpp * width; } if (0 != dst_lineStride) { if (dst_lineStride < dst_bpp * width) { throw new IllegalArgumentException( String.format( "Invalid %s stride %d, must be greater than bytesPerPixel %d * width %d", "destination", dst_lineStride, dst_bpp, width)); } } else { dst_lineStride = dst_bpp * width; } // final int src_comp_bitStride = src_comp.bitStride(); final int dst_comp_bitStride = dst_comp.bitStride(); final boolean vert_flip = src_glOriented != dst_glOriented; final boolean fast_copy = src_comp.equals(dst_comp) && 0 == dst_comp_bitStride % 8; if (DEBUG) { System.err.println("XXX: size " + width + "x" + height + ", fast_copy " + fast_copy); System.err.println( "XXX: SRC fmt " + src_fmt + ", " + src_comp + ", stride " + src_lineStride + ", isGLOrient " + src_glOriented); System.err.println( "XXX: DST fmt " + dst_fmt + ", " + dst_comp + ", stride " + dst_lineStride + ", isGLOrient " + dst_glOriented); } if (fast_copy) { // Fast copy for (int y = 0; y < height; y++) { int src_off = vert_flip ? (height - 1 - y) * src_lineStride : y * src_lineStride; int dst_off = dst_lineStride * y; for (int x = 0; x < width; x++) { dst_bb.put(dst_off + 0, src_bb.get(src_off + 0)); // 1 if (2 <= dst_bpp) { dst_bb.put(dst_off + 1, src_bb.get(src_off + 1)); // 2 if (3 <= dst_bpp) { dst_bb.put(dst_off + 2, src_bb.get(src_off + 2)); // 3 if (4 <= dst_bpp) { dst_bb.put(dst_off + 3, src_bb.get(src_off + 3)); // 4 } } } src_off += src_bpp; dst_off += dst_bpp; } } } else { // Conversion final ComponentMap cmap = new ComponentMap(src_fmt.comp, dst_fmt.comp); final Bitstream.ByteBufferStream srcBBS = new Bitstream.ByteBufferStream(src_bb); final Bitstream<ByteBuffer> srcBitStream = new Bitstream<ByteBuffer>(srcBBS, false /* outputMode */); srcBitStream.setThrowIOExceptionOnEOF(true); final Bitstream.ByteBufferStream dstBBS = new Bitstream.ByteBufferStream(dst_bb); final Bitstream<ByteBuffer> dstBitStream = new Bitstream<ByteBuffer>(dstBBS, true /* outputMode */); dstBitStream.setThrowIOExceptionOnEOF(true); if (DEBUG) { System.err.println("XXX: cmap.dst2src " + Arrays.toString(cmap.dst2src)); System.err.println("XXX: cmap.src2dst " + Arrays.toString(cmap.src2dst)); System.err.println("XXX: cmap.srcRGBA " + Arrays.toString(cmap.srcRGBA)); System.err.println("XXX: srcBitStream " + srcBitStream); System.err.println("XXX: dstBitStream " + dstBitStream); } try { for (int y = 0; y < height; y++) { final int src_off = vert_flip ? (height - 1 - y) * src_lineStride * 8 : y * src_lineStride * 8; // final int dst_off = dst_lineStride*8*y; srcBitStream.position(src_off); for (int x = 0; x < width; x++) { convert(cmap, dst_comp, dstBitStream, src_comp, srcBitStream); } // srcBitStream.skip(( src_lineStride * 8 ) - ( src_comp_bitStride * width )); dstBitStream.skip((dst_lineStride * 8) - (dst_comp_bitStride * width)); } } catch (final IOException ioe) { throw new RuntimeException(ioe); } if (DEBUG) { System.err.println("XXX: srcBitStream " + srcBitStream); System.err.println("XXX: dstBitStream " + dstBitStream); } } }