org.bytedeco.javacv.GLCanvasFrame Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javacv Show documentation
Show all versions of javacv Show documentation
Java interface to OpenCV, FFmpeg, and more
/*
* Copyright (C) 2012 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bytedeco.javacv;
import com.jogamp.opencl.CLImage2d;
import com.jogamp.opencl.gl.CLGLImage2d;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
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.swing.JFrame;
import org.bytedeco.opencv.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
/**
*
* @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);
if (shareWith != null) {
((GLCanvas)canvas).setSharedContext(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(drawable, (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(drawable);
}
}
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(Frame frame) {
showImage(frame, false);
}
@Override public void showImage(Frame frame, boolean flipChannels) {
if (flipChannels) {
throw new RuntimeException("GLCanvasFrame does not support channel flipping.");
}
if (frame == null) {
return;
}
this.color = null;
this.width = frame.imageWidth;
this.height = frame.imageHeight;
this.buffer = frame.image[0];
switch (frame.imageDepth) {
case Frame.DEPTH_BYTE: this.type = GL2.GL_BYTE; break;
case Frame.DEPTH_UBYTE: this.type = GL2.GL_UNSIGNED_BYTE; break;
case Frame.DEPTH_SHORT: this.type = GL2.GL_SHORT; break;
case Frame.DEPTH_USHORT: this.type = GL2.GL_UNSIGNED_SHORT; break;
case Frame.DEPTH_INT: this.type = GL2.GL_INT; break;
case Frame.DEPTH_FLOAT: this.type = GL2.GL_FLOAT; break;
case Frame.DEPTH_DOUBLE: this.type = GL2.GL_DOUBLE; break;
default: assert false;
}
switch (frame.imageChannels) {
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);
}
}