import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.Timer; import java.awt.image.*; /** * @author Donald Yessick * */ @SuppressWarnings("serial") public class BlueScreenTV extends JComponent implements MouseListener { /* BlueScreenTV attributes */ protected boolean isPowerOn = true; // true = on, false is off protected int channel = 1; // we have channel 1 and channel 2 public String toString(){ return ( (isPowerOn)? "Channel "+channel: "off"); } public void pushPowerButton() { isPowerOn = !isPowerOn; // toggle power } public void changeChannel() { channel = channel % 2 + 1; } private static BufferedImage tv, blueTube, pictureChannel1, pictureChannel2, pictureChannel; //images private static URL urlTV, urlBlueTube, urlChannel1, urlChannel2; //urls for images private static float scaleCh1, scaleCh2, scale; //will use this to render private AffineTransform affineTransformChannel1 = new AffineTransform(); private AffineTransform affineTransformChannel2 = new AffineTransform(); /** * @param args */ public static void main(String[] args) { try { urlTV = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/Panasonic1952.PNG"); urlBlueTube = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/Panasonic1952BlueTube.PNG"); urlChannel1 = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/AmalienborgPalace.jpg"); urlChannel2 = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/MarsLander.jpg"); tv = ImageIO.read(urlTV); blueTube = makeColorTransparent(ImageIO.read(urlBlueTube), new Color(0, 255, 255)); pictureChannel1 = ImageIO.read(urlChannel1); pictureChannel2 = ImageIO.read(urlChannel2); } catch (MalformedURLException badUrl) { badUrl.printStackTrace(); System.out.println("ABORTING: " + badUrl.toString()); System.exit(0); } catch (IOException ioError) { ioError.printStackTrace(); System.out.println("ABORTING: " + ioError.toString()); System.exit(0); } catch (Exception otherError) {// this alone is sufficient otherError.printStackTrace(); System.out.println("ABORTING: " + otherError.toString()); System.exit(0); } int top = 67; int bottom = 158; int ht = bottom-top; scaleCh1 = (float)(pictureChannel1.getHeight()) / (float)(ht); scaleCh2 = (float)(pictureChannel2.getHeight()) / (float)(ht); BlueScreenTV tv = new BlueScreenTV(); tv.getWindow().setVisible(true); tv.timer.start(); } public static void lab13(BlueScreenTV subclass) { try { urlTV = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/Panasonic1952.PNG"); urlBlueTube = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/Panasonic1952BlueTube.PNG"); urlChannel1 = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/AmalienborgPalace.jpg"); urlChannel2 = new URL( "http://dyessick.com/Coastal/Spring2008/csci140lab/images/MarsLander.jpg"); tv = ImageIO.read(urlTV); blueTube = makeColorTransparent(ImageIO.read(urlBlueTube), new Color(0, 255, 255)); pictureChannel1 = ImageIO.read(urlChannel1); pictureChannel2 = ImageIO.read(urlChannel2); } catch (MalformedURLException badUrl) { badUrl.printStackTrace(); System.out.println("ABORTING: " + badUrl.toString()); System.exit(0); } catch (IOException ioError) { ioError.printStackTrace(); System.out.println("ABORTING: " + ioError.toString()); System.exit(0); } catch (Exception otherError) {// this alone is sufficient otherError.printStackTrace(); System.out.println("ABORTING: " + otherError.toString()); System.exit(0); } int top = 67; int bottom = 158; int ht = bottom-top; scaleCh1 = (float)(pictureChannel1.getHeight()) / (float)(ht); scaleCh2 = (float)(pictureChannel2.getHeight()) / (float)(ht); BlueScreenTV tv = subclass; tv.getWindow().setVisible(true); tv.timer.start(); } /** * getWindow is a helper to keep main clean and simple handles the details * of creating a window for our JComponent * * @returns a window with our component */ private JFrame window; private JFrame getWindow() { // this is the lab8 object if (window != null) return window; window = new JFrame(this.toString()); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setSize(tv.getWidth(), tv.getHeight()); window.setContentPane(this); window.addMouseListener(this); return window; } public void paintComponent(Graphics oldGraphics) { Graphics2D g = (Graphics2D) oldGraphics; this.getWindow().setTitle(this.toString()); if (!isPowerOn){ g.drawImage(tv,0,0,null); return; } try{ AffineTransform reset = g.getTransform(); switch (channel){ case(1): pictureChannel = pictureChannel1; g.setTransform(affineTransformChannel1); scale = scaleCh1; break; case(2): pictureChannel = pictureChannel2; g.setTransform(affineTransformChannel2); scale = scaleCh2; break; default: throw new Exception("invalid channel"); } playChannel(g, pictureChannel); g.setTransform(reset); } catch (Exception badChannel) {// this alone is sufficient badChannel.printStackTrace(); System.out.println("ABORTING: " + badChannel.toString()); System.exit(0); } g.drawImage(blueTube,0,0,null); } /** * paintImage is a helper function that paints an image. This method has * some nastiness to it. putting it all in paintComponent would simply make * that method nasty too. * * @param g * Graphics2D on which to draw the image * @param stringURL * universal resource locator for image */ private void playChannel(Graphics2D g, BufferedImage theImage) { int imageWidth = theImage.getWidth(); int imageHeight = theImage.getHeight(); //scales and draws image on the fly int top = 67; int bottom = 158; //int ht = bottom-top; //scale = (float)imageHeight / (float)(ht); int left = tv.getWidth()/3+1; int right =left+(int)((float)(imageWidth)*scale); g.drawImage( //the image theImage, //top left coordinate to place image left,top, ////bottom right coordinate to scale image right, bottom, //where to start in the image --you can choose part of the image 0, 0, //where to end in the image --you can choose part of the image imageWidth,imageHeight, //transparent fill color, e.g. Color.YELLOW, leave as null, or omit to leave transparent null, //ImageObserver -- null will do -- can be used to alert when null ); } public static BufferedImage makeColorTransparent(BufferedImage bim, final Color color) { ImageFilter filter = new RGBImageFilter() { // the color we are looking for... Alpha bits are set to opaque public int markerRGB = color.getRGB() | 0xFF000000; public final int filterRGB(int x, int y, int rgb) { if ((rgb | 0xFF000000) == markerRGB) {// Mark the alpha bits // as zero - transparent return 0x00FFFFFF & rgb; } else {// nothing to do return rgb; } } }; ImageProducer ip = new FilteredImageSource(bim.getSource(), filter); Image im = Toolkit.getDefaultToolkit().createImage(ip); return convert(im); } static public BufferedImage convert(Image im) { BufferedImage bi = new BufferedImage(im.getWidth(null), im .getHeight(null), BufferedImage.TYPE_4BYTE_ABGR); Graphics bg = bi.getGraphics(); bg.drawImage(im, 0, 0, null); bg.dispose(); return bi; } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ @Override public void mouseClicked(MouseEvent mouseEvent) { int x = mouseEvent.getX(); int y = mouseEvent.getY(); //System.out.print(x); System.out.print(","); System.out.println(y); if (x < 110 || x > 252) return; //x bounds if (y < 240 || y > 260) return; //y bounds if (x < 130) channel = 1; if (x > 217) channel = 2; if (x < 151 || x > 197) return; //new x bounds if (y < 246 || y > 256) return; //new y bounds if (x < 165) isPowerOn=true; if (x > 185) isPowerOn=false; } /** * timer forces repainting (with new rotation) every 15000 milliseconds (15 * seconds)) this is syntactically ugly so don't get hung up on it key idea, * repaint(), forces the screen to repaint */ protected Timer timer = new Timer(33, new ActionListener() { int t1 = 1; int t2 = 1; void updateChannel1(){ int sizeGraphic = (int)((float)(pictureChannel1.getWidth())*scaleCh1)-(tv.getWidth()/3+1); t1 = (t1+1)%(2*sizeGraphic); if ((t1 / sizeGraphic) % 2 == 0) // change direction periodically affineTransformChannel1.translate(-1, 0); // move camera right else // every odd N iterations affineTransformChannel1.translate(1, 0);// move camera left } void updateChannel2(){ int sizeGraphic = (int)((float)(pictureChannel1.getWidth())*scaleCh1)-(tv.getWidth()/3+1); t2 = (t2+1)%(2*sizeGraphic); if ((t2 / sizeGraphic) % 2 == 0) // change direction periodically affineTransformChannel2.translate(-1, 0); // move camera right else // every odd N iterations affineTransformChannel2.translate(1, 0);// move camera left } public void actionPerformed(ActionEvent time) { if (pictureChannel == null) return; updateChannel1(); updateChannel2(); repaint(); } }); public void mouseEntered(MouseEvent arg0) { //timer.start(); } public void mouseExited(MouseEvent arg0) { //timer.stop(); } public void mousePressed(MouseEvent arg0) { //timer.stop(); } public void mouseReleased(MouseEvent arg0) { //timer.start(); } }