All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.media.nativewindow.util.PixelFormatUtil Maven / Gradle / Ivy

There is a newer version: 2.3.2
Show newest version
/**
 * Copyright (c) 2014 JogAmp Community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of
 *       conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
 *       of conditions and the following disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of JogAmp Community.
 */
package javax.media.nativewindow.util;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import com.jogamp.common.nio.Buffers;

/**
 * Pixel Rectangle Utilities.
 * 

* All conversion methods are endian independent. *

*/ public class PixelFormatUtil { public static interface PixelSink { /** Return the sink's destination pixelformat. */ PixelFormat getPixelformat(); /** * Returns stride in byte-size, i.e. byte count from one line to the next. *

* Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}. *

*/ int getStride(); /** * Returns true if the sink's memory is laid out in * OpenGL's coordinate system, origin at bottom left. * Otherwise returns false, i.e. origin at top left. */ boolean isGLOriented(); } /** * Pixel sink for up-to 32bit. */ public static interface PixelSink32 extends PixelSink { /** * Will be invoked over all rows top-to down * and all columns left-to-right. *

* Shall consider dest pixelformat and only store as much components * as defined, up to 32bit. *

*

* Implementation may better write single bytes from low-to-high bits, * e.g. {@link ByteOrder#LITTLE_ENDIAN} order. * Otherwise a possible endian conversion must be taken into consideration. *

* @param x * @param y * @param pixel */ void store(int x, int y, int pixel); } /** * Returns the {@link PixelFormat} with reversed components of fmt. * If no reversed {@link PixelFormat} is available, returns fmt. */ public static PixelFormat getReversed(final PixelFormat fmt) { switch(fmt) { case LUMINANCE: return PixelFormat.LUMINANCE; case RGB888: return PixelFormat.BGR888; case BGR888: return PixelFormat.RGB888; case RGBA8888: return PixelFormat.ABGR8888; case ABGR8888: return PixelFormat.RGBA8888; case ARGB8888: return PixelFormat.BGRA8888; case BGRA8888: return PixelFormat.ABGR8888; default: throw new InternalError("Unhandled format "+fmt); } } public static int getValue32(final PixelFormat src_fmt, final ByteBuffer src, int srcOff) { switch(src_fmt) { case LUMINANCE: { final byte c1 = src.get(srcOff++); return ( 0xff ) << 24 | ( 0xff & c1 ) << 16 | ( 0xff & c1 ) << 8 | ( 0xff & c1 ); } case RGB888: case BGR888: { final byte c1 = src.get(srcOff++); final byte c2 = src.get(srcOff++); final byte c3 = src.get(srcOff++); return ( 0xff ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 ); } case RGBA8888: case ABGR8888: case ARGB8888: case BGRA8888: { final byte c1 = src.get(srcOff++); final byte c2 = src.get(srcOff++); final byte c3 = src.get(srcOff++); final byte c4 = src.get(srcOff++); return ( 0xff & c4 ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 ); } default: throw new InternalError("Unhandled format "+src_fmt); } } public static int convertToInt32(final PixelFormat dest_fmt, final byte r, final byte g, final byte b, final byte a) { switch(dest_fmt) { case LUMINANCE: { final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) ); return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l ); } case RGB888: return ( 0xff ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r ); case BGR888: return ( 0xff ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b ); case RGBA8888: return ( 0xff & a ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r ); case ABGR8888: return ( 0xff & r ) << 24 | ( 0xff & g ) << 16 | ( 0xff & b ) << 8 | ( 0xff & a ); case ARGB8888: return ( 0xff & b ) << 24 | ( 0xff & g ) << 16 | ( 0xff & r ) << 8 | ( 0xff & a ); case BGRA8888: return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b ); default: throw new InternalError("Unhandled format "+dest_fmt); } } public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final ByteBuffer src, int srcOff) { final byte r, g, b, a; switch(src_fmt) { case LUMINANCE: r = src.get(srcOff++); // R g = r; // G b = r; // B a = (byte) 0xff; // A break; case RGB888: r = src.get(srcOff++); // R g = src.get(srcOff++); // G b = src.get(srcOff++); // B a = (byte) 0xff; // A break; case BGR888: b = src.get(srcOff++); // B g = src.get(srcOff++); // G r = src.get(srcOff++); // R a = (byte) 0xff; // A break; case RGBA8888: r = src.get(srcOff++); // R g = src.get(srcOff++); // G b = src.get(srcOff++); // B a = src.get(srcOff++); // A break; case ABGR8888: a = src.get(srcOff++); // A b = src.get(srcOff++); // B g = src.get(srcOff++); // G r = src.get(srcOff++); // R break; case ARGB8888: a = src.get(srcOff++); // A r = src.get(srcOff++); // R g = src.get(srcOff++); // G b = src.get(srcOff++); // B break; case BGRA8888: b = src.get(srcOff++); // B g = src.get(srcOff++); // G r = src.get(srcOff++); // R a = src.get(srcOff++); // A break; default: throw new InternalError("Unhandled format "+src_fmt); } return convertToInt32(dest_fmt, r, g, b, a); } public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final int src_pixel) { final byte r, g, b, a; switch(src_fmt) { case LUMINANCE: r = (byte) ( src_pixel ); // R g = r; // G b = r; // B a = (byte) 0xff; // A break; case RGB888: r = (byte) ( src_pixel ); // R g = (byte) ( src_pixel >>> 8 ); // G b = (byte) ( src_pixel >>> 16 ); // B a = (byte) 0xff; // A break; case BGR888: b = (byte) ( src_pixel ); // B g = (byte) ( src_pixel >>> 8 ); // G r = (byte) ( src_pixel >>> 16 ); // R a = (byte) 0xff; // A break; case RGBA8888: r = (byte) ( src_pixel ); // R g = (byte) ( src_pixel >>> 8 ); // G b = (byte) ( src_pixel >>> 16 ); // B a = (byte) ( src_pixel >>> 24 ); // A break; case ABGR8888: a = (byte) ( src_pixel ); // A b = (byte) ( src_pixel >>> 8 ); // B g = (byte) ( src_pixel >>> 16 ); // G r = (byte) ( src_pixel >>> 24 ); // R break; case ARGB8888: a = (byte) ( src_pixel ); // A r = (byte) ( src_pixel >>> 8 ); // R g = (byte) ( src_pixel >>> 16 ); // G b = (byte) ( src_pixel >>> 24 ); // B break; case BGRA8888: b = (byte) ( src_pixel ); // B g = (byte) ( src_pixel >>> 8 ); // G r = (byte) ( src_pixel >>> 16 ); // R a = (byte) ( src_pixel >>> 24 ); // A break; default: throw new InternalError("Unhandled format "+src_fmt); } return convertToInt32(dest_fmt, r, g, b, a); } public static PixelRectangle convert32(final PixelRectangle src, final PixelFormat destFmt, final int ddestStride, final boolean isGLOriented, final boolean destIsDirect) { final int width = src.getSize().getWidth(); final int height = src.getSize().getHeight(); final int bpp = destFmt.bytesPerPixel(); final int destStride; if( 0 != ddestStride ) { destStride = ddestStride; if( destStride < bpp * width ) { throw new IllegalArgumentException("Invalid stride "+destStride+", must be greater than bytesPerPixel "+bpp+" * width "+width); } } else { destStride = bpp * width; } final int capacity = destStride*height; final ByteBuffer bb = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order()); // System.err.println("XXX: SOURCE "+src); // System.err.println("XXX: DEST fmt "+destFmt+", stride "+destStride+" ("+ddestStride+"), isGL "+isGLOriented+", "+width+"x"+height+", capacity "+capacity+", "+bb); final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() { public void store(final int x, final int y, final int pixel) { int o = destStride*y+x*bpp; bb.put(o++, (byte) ( pixel )); // 1 if( 3 <= bpp ) { bb.put(o++, (byte) ( pixel >>> 8 )); // 2 bb.put(o++, (byte) ( pixel >>> 16 )); // 3 if( 4 <= bpp ) { bb.put(o++, (byte) ( pixel >>> 24 )); // 4 } } } @Override public final PixelFormat getPixelformat() { return destFmt; } @Override public final int getStride() { return destStride; } @Override public final boolean isGLOriented() { return isGLOriented; } }; convert32(imgSink, src); return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, bb); } public static void convert32(final PixelSink32 destInt32, final PixelRectangle src) { convert32(destInt32, src.getPixels(), src.getPixelformat(), src.isGLOriented(), src.getSize().getWidth(), src.getSize().getHeight(), src.getStride()); } /** * * @param dest32 32bit pixel sink * @param src_bb * @param src_fmt * @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, origin at bottom left, * otherwise origin at top left. * @param width * @param height * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next. * If zero, stride is set to width * bytes-per-pixel. * If not zero, value must be >= width * bytes-per-pixel. * @param stride_bytes stride in byte-size, i.e. byte count from one line to the next. * Must be >= {@link PixelFormat#bytesPerPixel() src_fmt.bytesPerPixel()} * width. * @throws IllegalArgumentException if strideInBytes is invalid */ public static void convert32(final PixelSink32 dest32, final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, final int width, final int height, int stride_bytes) { final int src_bpp = src_fmt.bytesPerPixel(); if( 0 != stride_bytes ) { if( stride_bytes < src_bpp * width ) { throw new IllegalArgumentException("Invalid stride "+stride_bytes+", must be greater than bytesPerPixel "+src_bpp+" * width "+width); } } else { stride_bytes = src_bpp * width; } final PixelFormat dest_fmt = dest32.getPixelformat(); final boolean vert_flip = src_glOriented != dest32.isGLOriented(); final boolean fast_copy = src_fmt == dest_fmt && dest_fmt.bytesPerPixel() == 4 ; // System.err.println("XXX: SRC fmt "+src_fmt+", stride "+stride_bytes+", isGL "+src_glOriented+", "+width+"x"+height); // System.err.println("XXX: DST fmt "+dest_fmt+", fast_copy "+fast_copy); if( fast_copy ) { // Fast copy for(int y=0; y




© 2015 - 2024 Weber Informatics LLC | Privacy Policy