diff options
author | Sven Gothel <[email protected]> | 2008-06-21 02:33:51 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2008-06-21 02:33:51 +0000 |
commit | 006acbb9463af33a8b45aa0b3a298604eba72d82 (patch) | |
tree | 2c71662575a2c098b22c4b19b471bb5c732041c5 /src/classes/com/sun/opengl/util/awt/gl2 | |
parent | cbc45e816f4ee81031bffce19a99550681462a24 (diff) |
2nd big refactoring.
Goals are orthogonal components for:
- OS Windowing system
- NEWT, X11, Windows, MacOsX
- GL Windowing GLUE
- EGL, GLX, WGL, CGL
- GL profiles
- core and util packages
- generate all Java components from any platform
All above goals are achieved.
TODO:
- Native compilation fix and test
- Check/Fix Win32, MacOSX and the mobile devices
- ..
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/branches/JOGL_2_SANDBOX@1665 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/classes/com/sun/opengl/util/awt/gl2')
-rwxr-xr-x | src/classes/com/sun/opengl/util/awt/gl2/GL2Screenshot.java | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/classes/com/sun/opengl/util/awt/gl2/GL2Screenshot.java b/src/classes/com/sun/opengl/util/awt/gl2/GL2Screenshot.java new file mode 100755 index 000000000..03313e2e5 --- /dev/null +++ b/src/classes/com/sun/opengl/util/awt/gl2/GL2Screenshot.java @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.sun.opengl.util.awt.gl2; + +import java.awt.image.*; +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import javax.imageio.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; + +import com.sun.opengl.util.io.*; +import com.sun.opengl.util.awt.*; + +/** Utilities for taking screenshots of OpenGL applications. */ + +public class GL2Screenshot { + private GL2Screenshot() {} + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). <p> + * + * No alpha channel is written with this variant. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int width, + int height) throws GLException, IOException { + writeToTargaFile(file, width, height, false); + } + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether the alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int width, + int height, + boolean alpha) throws GLException, IOException { + writeToTargaFile(file, 0, 0, width, height, alpha); + } + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). + * + * @param file the file to write containing the screenshot + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the desired screenshot area + * @param height the height of the desired screenshot area + * @param alpha whether the alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int x, + int y, + int width, + int height, + boolean alpha) throws GLException, IOException { + if (alpha) { + checkExtABGR(); + } + + TGAWriter writer = new TGAWriter(); + writer.open(file, width, height, alpha); + ByteBuffer bgr = writer.getImageData(); + + GL2 gl = GLUgl2.getCurrentGL2(); + + // Set up pixel storage modes + PixelStorageModes psm = new PixelStorageModes(); + psm.save(gl); + + int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR); + + // read the BGR values into the image buffer + gl.glReadPixels(x, y, width, height, readbackType, + GL2.GL_UNSIGNED_BYTE, bgr); + + // Restore pixel storage modes + psm.restore(gl); + + // close the file + writer.close(); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. <P> + * + * No alpha channel is read back with this variant. + * + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int width, + int height) throws GLException { + return readToBufferedImage(width, height, false); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. + * + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether the alpha channel should be read back. If + * true, requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int width, + int height, + boolean alpha) throws GLException { + return readToBufferedImage(0, 0, width, height, alpha); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. + * + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the desired screenshot area + * @param height the height of the desired screenshot area + * @param alpha whether the alpha channel should be read back. If + * true, requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int x, + int y, + int width, + int height, + boolean alpha) throws GLException { + int bufImgType = (alpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR); + int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR); + + if (alpha) { + checkExtABGR(); + } + + // Allocate necessary storage + BufferedImage image = new BufferedImage(width, height, bufImgType); + + GL2 gl = GLUgl2.getCurrentGL2(); + + // Set up pixel storage modes + PixelStorageModes psm = new PixelStorageModes(); + psm.save(gl); + + // read the BGR values into the image + gl.glReadPixels(x, y, width, height, readbackType, + GL2.GL_UNSIGNED_BYTE, + ByteBuffer.wrap(((DataBufferByte) image.getRaster().getDataBuffer()).getData())); + + // Restore pixel storage modes + psm.restore(gl); + + // Must flip BufferedImage vertically for correct results + ImageUtil.flipImageVertically(image); + return image; + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * No alpha channel is saved with this variant. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int width, + int height) throws IOException, GLException { + writeToFile(file, width, height, false); + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * Note that some file formats, in particular JPEG, can not handle + * an alpha channel properly. If the "alpha" argument is specified + * as true for such a file format it will be silently ignored. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether an alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int width, + int height, + boolean alpha) throws IOException, GLException { + writeToFile(file, 0, 0, width, height, alpha); + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * Note that some file formats, in particular JPEG, can not handle + * an alpha channel properly. If the "alpha" argument is specified + * as true for such a file format it will be silently ignored. + * + * @param file the file to write containing the screenshot + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether an alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int x, + int y, + int width, + int height, + boolean alpha) throws IOException, GLException { + String fileSuffix = FileUtil.getFileSuffix(file); + if (alpha && (fileSuffix.equals("jpg") || fileSuffix.equals("jpeg"))) { + // JPEGs can't deal properly with alpha channels + alpha = false; + } + + BufferedImage image = readToBufferedImage(x, y, width, height, alpha); + if (!ImageIO.write(image, fileSuffix, file)) { + throw new IOException("Unsupported file format " + fileSuffix); + } + } + + private static int glGetInteger(GL2 gl, int pname, int[] tmp) { + gl.glGetIntegerv(pname, tmp, 0); + return tmp[0]; + } + + private static void checkExtABGR() { + GL2 gl = GLUgl2.getCurrentGL2(); + if (!gl.isExtensionAvailable("GL_EXT_abgr")) { + throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr"); + } + } + + static class PixelStorageModes { + int packAlignment; + int packRowLength; + int packSkipRows; + int packSkipPixels; + int packSwapBytes; + int[] tmp = new int[1]; + + void save(GL2 gl) { + packAlignment = glGetInteger(gl, GL2.GL_PACK_ALIGNMENT, tmp); + packRowLength = glGetInteger(gl, GL2.GL_PACK_ROW_LENGTH, tmp); + packSkipRows = glGetInteger(gl, GL2.GL_PACK_SKIP_ROWS, tmp); + packSkipPixels = glGetInteger(gl, GL2.GL_PACK_SKIP_PIXELS, tmp); + packSwapBytes = glGetInteger(gl, GL2.GL_PACK_SWAP_BYTES, tmp); + + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 0); + } + + void restore(GL2 gl) { + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, packAlignment); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, packRowLength); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes); + } + } +} |