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

org.bytedeco.javacv.GLCanvasFrame Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 * Copyright (C) 2012 Samuel Audet
 *
 * This file is part of JavaCV.
 *
 * JavaCV is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version (subject to the "Classpath" exception
 * as provided in the LICENSE.txt file that accompanied this code).
 *
 * JavaCV is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JavaCV.  If not, see .
 */

package org.bytedeco.javacv;

import com.jogamp.opencl.CLImage2d;
import com.jogamp.opencl.gl.CLGLImage2d;
import com.jogamp.opengl.util.Gamma;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferFloat;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferUShort;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;

import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_highgui.*;

/**
 *
 * @author Samuel Audet
 */
public class GLCanvasFrame extends CanvasFrame {
    public GLCanvasFrame(String title) {
        this(title, 0.0);
    }
    public GLCanvasFrame(String title, double gamma) {
        super(title, gamma);
        init(false, null, null);
    }

    public GLCanvasFrame(String title, GraphicsConfiguration gc,
            GLCapabilitiesImmutable caps, GLContext shareWith) {
        this(title, gc, caps, shareWith, 0.0);
    }
    public GLCanvasFrame(String title, GraphicsConfiguration gc,
            GLCapabilitiesImmutable caps, GLContext shareWith, double gamma) {
        super(title, gc, gamma);
        init(false, caps, shareWith);
    }

    public GLCanvasFrame(String title, int screenNumber, DisplayMode displayMode) throws Exception {
        this(title, screenNumber, displayMode, 0.0);
    }
    public GLCanvasFrame(String title, int screenNumber, DisplayMode displayMode, double gamma) throws Exception {
        super(title, screenNumber, displayMode, gamma);
        init(true, null, null);
    }

    public GLCanvasFrame(String title, int screenNumber, DisplayMode displayMode,
            GLCapabilitiesImmutable caps, GLContext shareWith) throws Exception {
        this(title, screenNumber, displayMode, caps, shareWith, 0.0);
    }
    public GLCanvasFrame(String title, int screenNumber, DisplayMode displayMode,
            GLCapabilitiesImmutable caps, GLContext shareWith, double gamma) throws Exception {
        super(title, screenNumber, displayMode, gamma);
        init(true, caps, shareWith);
    }

    private void init(final boolean fullScreen,
            final GLCapabilitiesImmutable caps, final GLContext shareWith) {
        Runnable r = new Runnable() { public void run() {
            String wasErase = System.setProperty("sun.awt.noerasebackground", "true");

            canvas = new GLCanvas(caps, shareWith);
            ((GLCanvas)canvas).addGLEventListener(eventListener);
            if (fullScreen) {
                canvas.setSize(getSize());
                needInitialResize = false;
            } else {
                canvas.setSize(1, 1); // or we do not get a GLContext
                needInitialResize = true;
            }
            getContentPane().add(canvas);
            canvas.setVisible(true);

            if (wasErase != null) {
                System.setProperty("sun.awt.noerasebackground", wasErase);
            } else {
                System.clearProperty("sun.awt.noerasebackground");
            }
        }};

        if (EventQueue.isDispatchThread()) {
            r.run();
        } else {
            try {
                EventQueue.invokeAndWait(r);
            } catch (java.lang.Exception ex) { }
        }
    }

    @Override protected void initCanvas(boolean fullScreen, DisplayMode displayMode, double gamma) { }

    private int[] params = new int[2];
    private Color color = null;
    private int width, height, format, type;
    private Buffer buffer = null;
    private int frameBuffer = 0, renderBuffer = 0;

    private GLEventListener eventListener = new GLEventListener() {
        public void init(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();

            gl.setSwapInterval(1); // Sync to VBlank

            if (inverseGamma != 1.0) {
                // Yeah baby, gamma correction in hardware!
                Gamma.setDisplayGamma(gl, (float)inverseGamma, 0, 1);
            }
            gl.glGenFramebuffers(1, params, 0);
            frameBuffer = params[0];
        }
        public void dispose(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();

            params[0] = frameBuffer;
            gl.glDeleteFramebuffers(1, params, 0);
            if (inverseGamma != 1.0) {
                Gamma.resetDisplayGamma(gl);
            }
        }
        public void display(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();

            if (color != null) {
                gl.glClearColor(color.getRed()/255f, color.getGreen()/255f, color.getBlue()/255f, 1f);
                gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
            } else if (buffer != null) {
                if (isResizable() && needInitialResize) {
                    int w = (int)Math.round(width *initialScale);
                    int h = (int)Math.round(height*initialScale);
                    setCanvasSize(w, h);
                }
                gl.glWindowPos2i(0, canvas.getHeight());
                gl.glPixelZoom((float)canvas.getWidth()/width, -(float)canvas.getHeight()/height);
                // XXX: Tell OpenGL about the alignment of buffer via glPixelStore(), somehow...
                gl.glDrawPixels(width, height, format, type, buffer);
            } else if (renderBuffer > 0) {
                gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, renderBuffer);
                gl.glGetRenderbufferParameteriv(GL2.GL_RENDERBUFFER,
                        GL2.GL_RENDERBUFFER_WIDTH, params, 0);
                gl.glGetRenderbufferParameteriv(GL2.GL_RENDERBUFFER,
                        GL2.GL_RENDERBUFFER_HEIGHT, params, 1);
                if (isResizable() && needInitialResize) {
                    int w = (int)Math.round(params[0]*initialScale);
                    int h = (int)Math.round(params[1]*initialScale);
                    setCanvasSize(w, h);
                }
                gl.glBindFramebuffer(GL2.GL_READ_FRAMEBUFFER, frameBuffer);
                gl.glFramebufferRenderbuffer(GL2.GL_READ_FRAMEBUFFER,
                        GL2.GL_COLOR_ATTACHMENT0, GL2.GL_RENDERBUFFER, renderBuffer);
                // Often GL_RENDERBUFFER_WIDTH == 0 and GL_RENDERBUFFER_HEIGHT == 1,
                // while glCheckFramebufferStatus() returns
                // GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT here,
                // but, for a given object, it either never happens or
                // always happens ... NVIDIA driver bug?
//System.out.println(params[0] + " " + params[1] +
//        " glCheckFramebufferStatus = " + gl.glCheckFramebufferStatus(GL2.GL_READ_FRAMEBUFFER));
                assert gl.glCheckFramebufferStatus(GL2.GL_READ_FRAMEBUFFER) == GL2.GL_FRAMEBUFFER_COMPLETE;
                gl.glBlitFramebuffer(0, 0,  params[0], params[1],
                        0, canvas.getHeight(),  canvas.getWidth(), 0,
                        GL2.GL_COLOR_BUFFER_BIT, GL2.GL_LINEAR);
            }
        }
        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
    };

    public GLCanvas getGLCanvas() {
        return (GLCanvas)canvas;
    }

    @Override public void showColor(Color color) {
        this.color = color;
        this.buffer = null;
        getGLCanvas().display();
    }

    @Override public void showImage(AbstractArray image) {
        showImage(image, false);
    }
    @Override public void showImage(AbstractArray image, boolean flipChannels) {
        if (flipChannels) {
            throw new RuntimeException("GLCanvasFrame does not support channel flipping.");
        }
        if (image == null) {
            return;
        }
        this.color  = null;
        this.width  = image.arrayWidth();
        this.height = image.arrayHeight();
        this.buffer = image.getByteBuffer();
        switch (image.arrayDepth()) {
            case IPL_DEPTH_8S:  this.type = GL2.GL_BYTE;           break;
            case IPL_DEPTH_8U:  this.type = GL2.GL_UNSIGNED_BYTE;  break;
            case IPL_DEPTH_16S: this.type = GL2.GL_SHORT;          break;
            case IPL_DEPTH_16U: this.type = GL2.GL_UNSIGNED_SHORT; break;
            case IPL_DEPTH_32S: this.type = GL2.GL_INT;            break;
            case IPL_DEPTH_32F: this.type = GL2.GL_FLOAT;          break;
            case IPL_DEPTH_64F: this.type = GL2.GL_DOUBLE;         break;
            default: assert false;
        }
        switch (image.arrayChannels()) {
            case 1: this.format = GL2.GL_LUMINANCE; break;
            case 2: this.format = GL2.GL_RG;        break;
            case 3: this.format = GL2.GL_RGB;       break;
            case 4: this.format = GL2.GL_RGBA;      break;
            default: assert false;
        }
        getGLCanvas().display();
    }
    @Override public void showImage(Image image) {
        if (!(image instanceof BufferedImage)) {
            throw new RuntimeException("GLCanvasFrame does not support " + image + ", BufferedImage required.");
        }
        showImage((BufferedImage)image);
    }
    public void showImage(BufferedImage image) {
        if (image == null) {
            return;
        }
        this.color = null;
        this.width  = image.getWidth();
        this.height = image.getHeight();

        DataBuffer buffer = image.getRaster().getDataBuffer();
        if (buffer instanceof DataBufferByte) {
            this.buffer = ByteBuffer.wrap(((DataBufferByte)buffer).getData());
            this.type = GL2.GL_UNSIGNED_BYTE;
        } else if (buffer instanceof DataBufferDouble) {
            this.buffer = DoubleBuffer.wrap(((DataBufferDouble)buffer).getData());
            this.type = GL2.GL_DOUBLE;
        } else if (buffer instanceof DataBufferFloat) {
            this.buffer = FloatBuffer.wrap(((DataBufferFloat)buffer).getData());
            this.type = GL2.GL_FLOAT;
        } else if (buffer instanceof DataBufferInt) {
            this.buffer = IntBuffer.wrap(((DataBufferInt)buffer).getData());
            this.type = GL2.GL_INT;
        } else if (buffer instanceof DataBufferShort) {
            this.buffer = ShortBuffer.wrap(((DataBufferShort)buffer).getData());
            this.type = GL2.GL_SHORT;
        } else if (buffer instanceof DataBufferUShort) {
            this.buffer = ShortBuffer.wrap(((DataBufferUShort)buffer).getData());
            this.type = GL2.GL_UNSIGNED_SHORT;
        } else {
            assert false;
        }
        switch (image.getSampleModel().getNumBands()) {
            case 1: this.format = GL2.GL_LUMINANCE; break;
            case 2: this.format = GL2.GL_RG;        break;
            case 3: this.format = GL2.GL_RGB;       break;
            case 4: this.format = GL2.GL_RGBA;      break;
            default: assert false;
        }
        getGLCanvas().display();
    }
    public void showImage(int renderBuffer) {
        if (renderBuffer <= 0) {
            return;
        }
        this.color = null;
        this.buffer = null;
        this.renderBuffer = renderBuffer;
        getGLCanvas().display();
    }

    private static GLCanvasFrame canvasFrame;
    public static void main(String[] args) throws java.lang.Exception {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                try {
                    canvasFrame = new GLCanvasFrame("Some Title"/*, context.getGLContext()*/);
                    canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    //canvasFrame.setCanvasSize(640, 480);
                    canvasFrame.showColor(Color.BLUE);
                } catch (java.lang.Exception ex) {
                    ex.printStackTrace();
                }
            }
        });

        final JavaCVCL context = new JavaCVCL(canvasFrame.getGLCanvas().getContext());
        final IplImage image = cvLoadImageBGRA("/usr/share/opencv/samples/c/lena.jpg"/*args[0]*/);
        //final IplImage image = cvLoadImage("/usr/share/opencv/samples/c/lena.jpg"/*args[0]*/, 0);
        //final IplImage image = IplImage.create(640, 480, IPL_DEPTH_32F, 4);
        final CLGLImage2d imageCLGL = context.createCLGLImageFrom(image);
        //final CLImage2d imageCL = context.createCLImageFrom(image);
        context.acquireGLObject(imageCLGL);
        context.writeImage(imageCLGL, image, true);
        context.releaseGLObject(imageCLGL);
        //System.out.println(imageCLGL.getFormat());
        //System.exit(0);

        canvasFrame.setCanvasScale(0.5);
        for (int i = 0; i < 1000; i++) {
            canvasFrame.showImage(imageCLGL.getGLObjectID());
            Thread.sleep(10);
            canvasFrame.showColor(Color.RED);
            Thread.sleep(10);
        }
        canvasFrame.waitKey();
        context.release();
        System.exit(0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy