package psychWithJava; /* * BitsPPFake.java * * Copyright (C) 2005-2008 Huseyin Boyaci. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This program 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. This program 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 version 2 for more details * (a copy is included in the LICENSE file that accompanied this code) * (also available at http://www.gnu.org) You should have received a copy of * the GNU General Public License along with this program; if not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ import psychWithJava.FullScreen; import java.awt.*; import java.awt.image.*; /** * Provides Fake Bits++ methods for development. The method signitures are * identical to BitsPP class. Therefore * a program using BitsPP class can easily be converted to one * which uses BitsPPFake class and run on a system without the Bits++ device * for developing the actual experimental code while the programmer is * away from his or her labaratory. *

* Inherited from FullScreen class, therefore it has all FullScreen * methods available. Additional methods specific to Bits++ device * is detailed below. *

* See Chapter A: Bits++ in * The Guide to Psychophysics Programming * with Java for more information. * * @see BitsPP * @see FullScreen * * @author boyaci * */ public class BitsPPFake extends FullScreen { private BufferedImageOp op; private LookupTable table; /** * * Constructs a BitsPP object on the default screen. * It initializes a fake clut line used for software lookup * operation, as opposed to the real one used to communicate * with the Bits++ device. * By default it uses a single video buffer and the current * display mode. Once it is constructed, FullScreen captures the entire screen * immediately. At the end client's program must * terminate this mode and go back to system's default display. * To do this use the method closeScreen(). * * @see #initClut() * @see #setDisplayMode(DisplayMode) * @see #setNBuffers(int) * @see #closeScreen() */ public BitsPPFake() { this(0); } /** * Constructs a BitsPP object on the screen designated with * displayID. It initializes a fake clut line used for software lookup * operation, as opposed to the real one used to communicate * with the Bits++ device. * By default it uses a single video buffer and the current * display mode of the client's OS. * Once it is constructed, BitsPP captures the entire screen * immediately. At the end client's program must * terminate this mode and go back to system's default display. * To do this use the method closeScreen(). * * @param screen_id a numerical id indicating the screen device * * @see #initClut() * @see #setDisplayMode(DisplayMode) * @see #setNBuffers(int) * @see #closeScreen() * */ public BitsPPFake(int screen_id) { super(screen_id); initClut(); } /** * Initializes the clut row used for software look up * operation as opposed to the actual one used for * communicating with Bits++ * hardware device. * */ public void initClut() { int[] convert = new int[256]; for (int i = 0; i < 256; i++) convert[i] = i << 6; setClut(convert); } /** * Sets a new look up table for each color channel for software * look up operation. It uses the most significant 8 bit of each * element in the tables. Therefore user should pass the same * 14 bit values as in actual BitsPP class. * * @param redClut red look up table * @param greenClut green look up table * @param blueClut blue look up table * * @throws ArrayIndexOutOfBoundsException if the number of elements is not * equal to 256 for any color table */ public void setClut(int[] redClut, int[] greenClut, int[] blueClut) throws ArrayIndexOutOfBoundsException{ int len = 256; if (redClut.length != len || greenClut.length != len || blueClut.length != len) throw new ArrayIndexOutOfBoundsException( "Clut should have " + len + " elements"); byte[][] row = new byte[3][len]; for (int i = 0; i < len; i++) { row[0][i] = (byte) (blueClut[i] >> 6); row[1][i] = (byte) (greenClut[i] >> 6); row[2][i] = (byte) (redClut[i] >> 6); } table = new ByteLookupTable(0, row); op = new LookupOp(table, new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); } /** * Sets a new look up table for each color channel for software look up * operation. * It uses the most significant 8 bit of each * element in the tables. Therefore user should pass the same * 14 bit values as in actual BitsPP class. * * @param clut look up table for all color channels. * * @throws ArrayIndexOutOfBoundsException if the number of elements of clut * is not equal to 256 */ public void setClut(int clut[]) throws ArrayIndexOutOfBoundsException{ int len = 256; if (clut.length != len) throw new ArrayIndexOutOfBoundsException( "Clut should have " + len + " elements"); byte[] row = new byte[len]; for (int i = 0; i < len; i++) row[i] = (byte) (clut[i] >> 6); table = new ByteLookupTable(0, row); op = new LookupOp(table, new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); } /** * Displays a BufferedImage at the specified position. * Note that, in case there is a back video buffer * this method draws the image on the back buffer. In that case * user has to invoke the updateScreen() method * to actually display the image on the screen. *

* This method also applies the look up operation specified by the * color look up tables. Currently accepts only TYPE_BYTE_GRAY and * TYPE_3BYTE_BGR types of BufferedImage. It is highly recommended to * use with only gray scale images because a software look up is * a very expensive operation. * * @param x horizontal offset of the upper left corner of the image from the * upper left corner of the screen * @param y vertical offset of the upper left corner of the image from the * upper left corner of the screen * @param bi BufferedImage to display * * @see #displayImage(BufferedImage) * @see #updateScreen() * @see #setClut(int[], int[], int[]) * @see #setClut(int[]) */ public void displayImage(int x, int y, BufferedImage bi) { Graphics g = getBufferStrategy().getDrawGraphics(); try { if(g!=null && bi!=null){ if (bi.getRaster().getNumBands() != table.getNumComponents() || (bi.getType() != BufferedImage.TYPE_3BYTE_BGR && bi.getType() != BufferedImage.TYPE_BYTE_GRAY)) { System.err.println( "Exception in BitsPPFake.displayImage(): Wrong image or table type"); System.err.println( "use either a BufferedImage of TYPE_BYTE_GRAY with setClut(table)"); System.err.println( " or a TYPE_3BYTE_BGR with setClut(tableR, tableG, tableB)"); closeScreen(); System.exit(0); } else g.drawImage(op.filter(bi, null), x, y, null); } } finally { g.dispose(); } } }