001/* An actor that converts an AWTImage to a base-64 encoded String. 002 003 @Copyright (c) 2003-2018 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the 009 above copyright notice and the following two paragraphs appear in all 010 copies of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION 2 026 COPYRIGHTENDKEY 027 */ 028package ptolemy.actor.lib.conversions; 029 030import java.awt.Graphics2D; 031import java.awt.Image; 032import java.awt.image.BufferedImage; 033import java.awt.image.RenderedImage; 034import java.io.ByteArrayOutputStream; 035import java.io.IOException; 036import java.io.OutputStream; 037import java.nio.charset.StandardCharsets; 038import java.util.Base64; 039 040import javax.imageio.ImageIO; 041 042import ptolemy.data.AWTImageToken; 043import ptolemy.data.StringToken; 044import ptolemy.data.expr.StringParameter; 045import ptolemy.data.type.BaseType; 046import ptolemy.kernel.CompositeEntity; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049 050/////////////////////////////////////////////////////////////////// 051//// ImageToBase64 052 053/** 054 Convert an AWT Image to a base-64 String. 055 056 @author Marten Lohstroh 057 @version $Id$ 058 @since Ptolemy II 11.0 059 @Pt.ProposedRating Red (liuj) 060 @Pt.AcceptedRating Red (liuj) 061 */ 062public class ImageToString extends Converter { 063 064 /** Construct an actor with the given container and name. 065 * @param container The container. 066 * @param name The name of this actor. 067 * @exception IllegalActionException If the actor cannot be contained 068 * by the proposed container. 069 * @exception NameDuplicationException If the container already has an 070 * actor with this name. 071 */ 072 public ImageToString(CompositeEntity container, String name) 073 throws IllegalActionException, NameDuplicationException { 074 super(container, name); 075 076 // Set the type of the input port. 077 input.setTypeEquals(BaseType.GENERAL); // FIXME: No image type available... 078 input.setMultiport(false); 079 // Set the type of the output port. 080 output.setTypeEquals(BaseType.STRING); 081 output.setMultiport(false); 082 083 compression = new StringParameter(this, "compression"); 084 compression.setExpression("png"); 085 } 086 087 /////////////////////////////////////////////////////////////////// 088 //// ports and parameters //// 089 090 /** Parameter that determines the encoding of the image ('gif', 091 * 'png', 'jpg'). 092 */ 093 public StringParameter compression; 094 095 /////////////////////////////////////////////////////////////////// 096 //// public methods //// 097 098 /** 099 * @exception IllegalActionException If the conversion fails. 100 */ 101 @Override 102 public void fire() throws IllegalActionException { 103 super.fire(); 104 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 105 Object inputValue = input.get(0); 106 if (!(inputValue instanceof AWTImageToken)) { 107 throw new IllegalActionException(this, 108 "The input value \"" + inputValue 109 + "\" is not an AWTImageToken, " + "it is a " 110 + inputValue.getClass()); 111 } else { 112 RenderedImage image = getRenderedImage( 113 ((AWTImageToken) inputValue).getValue()); 114 try { 115 OutputStream encodedStream = Base64.getUrlEncoder() 116 .wrap(outputStream); 117 ImageIO.write(image, "png", encodedStream); // FIXME: Use parameter instead. 118 encodedStream.close(); // Important, flushes the output buffer. 119 StringToken result = new StringToken(outputStream 120 .toString(StandardCharsets.US_ASCII.name())); 121 output.send(0, result); 122 } catch (final IOException ioe) { 123 throw new IllegalActionException(this, ioe, 124 "Unable to convert image to base-64 string."); 125 } 126 } 127 } 128 129 /** Return false if the input port has no token, otherwise return 130 * what the superclass returns (presumably true). 131 * @exception IllegalActionException If there is no director. 132 */ 133 @Override 134 public boolean prefire() throws IllegalActionException { 135 if (!input.hasToken(0)) { 136 return false; 137 } 138 139 return super.prefire(); 140 } 141 142 /////////////////////////////////////////////////////////////////// 143 //// private members //// 144 145 /** Convert an AWT Image object to a BufferedImage. 146 * @param in An AWT Image object. 147 * @return a BufferedImage. 148 */ 149 private BufferedImage getRenderedImage(Image in) { 150 BufferedImage out = new BufferedImage(in.getWidth(null), 151 in.getHeight(null), BufferedImage.TYPE_INT_RGB); 152 Graphics2D g2 = out.createGraphics(); 153 g2.drawImage(in, 0, 0, null); 154 g2.dispose(); 155 return out; 156 } 157 158}