001/* An actor that reads an image from a FileParameter and outputs 002 an AWTImageToken. 003 004 @Copyright (c) 2001-2017 The Regents of the University of California. 005 All rights reserved. 006 007 Permission is hereby granted, without written agreement and without 008 license or royalty fees, to use, copy, modify, and distribute this 009 software and its documentation for any purpose, provided that the 010 above copyright notice and the following two paragraphs appear in all 011 copies of this software. 012 013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 017 SUCH DAMAGE. 018 019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 ENHANCEMENTS, OR MODIFICATIONS. 025 026 PT_COPYRIGHT_VERSION 2 027 COPYRIGHTENDKEY 028 */ 029package ptolemy.actor.lib.image; 030 031import java.awt.Image; 032import java.io.IOException; 033import java.net.URL; 034 035import javax.imageio.ImageIO; 036 037import ptolemy.actor.lib.Source; 038import ptolemy.data.AWTImageToken; 039import ptolemy.data.expr.FileParameter; 040import ptolemy.data.type.BaseType; 041import ptolemy.kernel.CompositeEntity; 042import ptolemy.kernel.util.Attribute; 043import ptolemy.kernel.util.IllegalActionException; 044import ptolemy.kernel.util.NameDuplicationException; 045import ptolemy.util.FileUtilities; 046 047/////////////////////////////////////////////////////////////////// 048//// ImageReader 049 050/** 051 <p>This actor reads an Image from a FileParameter, and outputs it as an 052 AWTImageToken.</p> 053 054 <p>FIXME: It would be nice if we could read images from stdin.</p> 055 056 @see FileParameter 057 @see AWTImageToken 058 @author Christopher Hylands 059 @version $Id$ 060 @since Ptolemy II 3.0 061 @Pt.ProposedRating Red (cxh) 062 @Pt.AcceptedRating Red (cxh) 063 */ 064public class ImageReader extends Source { 065 // We don't extend ptolemy.actor.lib.Reader because we are not 066 // reading in data by columns. Probably this class and 067 // ptolemy.actor.lib.Reader should extend a common base class? 068 069 /** Construct an actor with the given container and name. 070 * @param container The container. 071 * @param name The name of this actor. 072 * @exception IllegalActionException If the actor cannot be contained 073 * by the proposed container. 074 * @exception NameDuplicationException If the container already has an 075 * actor with this name. 076 */ 077 public ImageReader(CompositeEntity container, String name) 078 throws IllegalActionException, NameDuplicationException { 079 super(container, name); 080 081 // Set the type of the output port. 082 //output.setMultiport(true); 083 output.setTypeEquals(BaseType.OBJECT); 084 085 fileOrURL = new FileParameter(this, "fileOrURL"); 086 } 087 088 /////////////////////////////////////////////////////////////////// 089 //// ports and parameters //// 090 091 /** The file name or URL from which to read. This is a string with 092 * any form accepted by File Attribute. 093 * @see FileParameter 094 */ 095 public FileParameter fileOrURL; 096 097 /////////////////////////////////////////////////////////////////// 098 //// public methods //// 099 100 /** If the specified attribute is <i>URL</i>, then close 101 * the current file (if there is one) and open the new one. 102 * @param attribute The attribute that has changed. 103 * @exception IllegalActionException If the specified attribute 104 * is <i>URL</i> and the file cannot be opened. 105 */ 106 @Override 107 public void attributeChanged(Attribute attribute) 108 throws IllegalActionException { 109 if (attribute == fileOrURL) { 110 // Would it be worth checking to see if the URL exists and 111 // is readable? 112 _url = fileOrURL.asURL(); 113 } 114 115 super.attributeChanged(attribute); 116 } 117 118 /** Output the data read in the prefire. 119 * @exception IllegalActionException If there's no director. 120 */ 121 @Override 122 public void fire() throws IllegalActionException { 123 super.fire(); 124 output.broadcast(new AWTImageToken(_image)); 125 } 126 127 /** Open the file at the URL, and set the width of the output. 128 */ 129 @Override 130 public void initialize() throws IllegalActionException { 131 super.initialize(); 132 attributeChanged(fileOrURL); 133 } 134 135 /** Read in an image. 136 * @exception IllegalActionException If an IO error occurs. 137 */ 138 @Override 139 public boolean prefire() throws IllegalActionException { 140 if (!super.prefire()) { 141 return false; 142 } 143 if (_url == null) { 144 throw new IllegalActionException("sourceURL was null"); 145 } 146 147 try { 148 _image = ImageIO.read(FileUtilities.followRedirects(_url)); 149 } catch (IOException e) { 150 throw new IllegalActionException(this, e, "Failed to read image."); 151 } 152 153 // Coverity Scan: ImageIO.read() can return null. 154 if (_image != null && _image.getWidth(null) == -1 155 && _image.getHeight(null) == -1) { 156 throw new IllegalActionException(this, 157 "Image size is -1 x -1. Failed to open '" + _url + "'"); 158 } 159 160 return super.prefire(); 161 } 162 163 // Image that is read in. 164 private Image _image; 165 166 // The URL of the file. 167 private URL _url; 168}