import ij.IJ; import ij.ImagePlus; import ij.gui.ImageWindow; import ij.plugin.PlugIn; import ij.process.ColorProcessor; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.nio.IntBuffer; import javax.media.opengl.*; import javax.media.opengl.glu.GLU; // Note that a GLCanvas is not a window component Java knows about, // and it will not appear in the ImageJ window menu. // Also, even though it extends Canvas, its paint and update methods can't // be used to draw on it, or the Graphics object be used to get at pixel values public class OpenGLExample1_ implements PlugIn, GLEventListener { public OpenGLExample1_() { } public void run (String arg) { final Frame f = new Frame("OpenGL Canvas 1"); f.addWindowListener(new WindowAdapter() { public void windowClosing (WindowEvent evt) { f.dispose(); } }); GLCanvas canvas1 = new GLCanvas(); canvas1.addGLEventListener(this); canvas1.setSize(300, 300); f.add(canvas1); f.pack(); f.setVisible(true); } // The following methods implement the GLEventListener interface public void init (GLAutoDrawable drawable) { GL gl = drawable.getGL(); gl.glShadeModel(GL.GL_SMOOTH); // Enables Smooth Shading gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background gl.glClearDepth(1.0); // Depth Buffer Setup gl.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing gl.glDepthFunc(GL.GL_LEQUAL); // The Type Of Depth Test To Do gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Really Nice Perspective Calculations } public void reshape (GLAutoDrawable drawable, int x, int y, int width, int height) { GL gl = drawable.getGL(); if (height == 0) height = 1; float h = (float)width / (float)height; gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); GLU glu = new GLU(); glu.gluPerspective(45.0, h, 1.0, 20.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); } public void display (GLAutoDrawable drawable) { // Here's Where We Do All Drawing GL gl = drawable.getGL(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer gl.glLoadIdentity(); // Reset The View gl.glTranslatef(-1.5f, 0.0f, -6.0f); // Move Into The Screen And Left gl.glBegin(GL.GL_TRIANGLES); gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glVertex3f(0.0f, 1.0f, 0.0f); gl.glColor3f(0.0f, 1.0f, 0.0f); gl.glVertex3f(1.0f, -1.0f, 0.0f); gl.glColor3f(0.0f, 0.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, 0.0f); gl.glEnd(); // transferPixels will be called every time the window is resized or moved transferPixels(drawable); } public void displayChanged (GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { } public void transferPixels (GLAutoDrawable drawable) { int width = drawable.getWidth(); int height = drawable.getHeight(); ColorProcessor proc = new ColorProcessor(width, height); ImagePlus implus = new ImagePlus("Lesson01 ImageJ", proc); if (!implus.lock()) { IJ.showMessage("Can't lock image"); ImageWindow iw = implus.getWindow(); if (iw != null) iw.close(); return; } GL gl = drawable.getGL(); //gl.glFlush(); gl.glFinish(); gl.glReadBuffer(GL.GL_FRONT); IntBuffer buffer = IntBuffer.allocate(3 * width * height); // pixels are returned separately by R, G and B components, hence the factor 3 gl.glReadPixels(0, 0, width, height, GL.GL_RGB, GL.GL_INT, buffer); int[] pixels = buffer.array(); int mask = 255 << 24; // Note that the OpenGL and ImageJ coordinate systems are inverse to each other along the y axis: // point (0,0) is at the lower left for OpenGL, and at the upper left for ImageJ for (int h=0; h>7 | (g&mask)>>15 | b>>23); // if these bit operations look strange, it's because I don't fully // understand how OpenGL stores R, G and B values in integers } implus.show(); implus.updateAndRepaintWindow(); implus.unlock(); IJ.showStatus("OpenGL image copied"); } }