001/* Partition an image into smaller subimages.
002 @Copyright (c) 1998-2014 The Regents of the University of California.
003 All rights reserved.
004
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the
008 above copyright notice and the following two paragraphs appear in all
009 copies of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION 2
025 COPYRIGHTENDKEY
026 */
027package ptolemy.domains.sdf.lib.vq;
028
029import ptolemy.actor.lib.Transformer;
030import ptolemy.data.IntMatrixToken;
031import ptolemy.data.IntToken;
032import ptolemy.data.expr.Parameter;
033import ptolemy.data.type.BaseType;
034import ptolemy.kernel.CompositeEntity;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.NameDuplicationException;
037
038///////////////////////////////////////////////////////////////////
039//// ImagePartition
040
041/**
042 Partition an image into smaller subimages.  Each input image
043 should have dimensions imageColumns by imageRows, and each output image
044 will have dimensions partitionColumns by partitionRows.  The output matrices
045 are row scanned from the top of input image.
046
047 @author Steve Neuendorffer
048 @version $Id$
049 @since Ptolemy II 0.2
050 @Pt.ProposedRating Green (neuendor)
051 @Pt.AcceptedRating Red (neuendor)
052 */
053public class ImagePartition extends Transformer {
054    /** Construct an actor in the specified container with the specified
055     *  name.
056     *  @param container The container.
057     *  @param name The name of this adder within the container.
058     *  @exception IllegalActionException If the actor cannot be contained
059     *   by the proposed container.
060     *  @exception NameDuplicationException If the name coincides with
061     *   an actor already in the container.
062     */
063    public ImagePartition(CompositeEntity container, String name)
064            throws IllegalActionException, NameDuplicationException {
065        super(container, name);
066
067        imageColumns = new Parameter(this, "imageColumns", new IntToken("176"));
068        imageColumns.setTypeEquals(BaseType.INT);
069        imageRows = new Parameter(this, "imageRows", new IntToken("144"));
070        imageRows.setTypeEquals(BaseType.INT);
071        partitionColumns = new Parameter(this, "partitionColumns",
072                new IntToken("4"));
073        partitionColumns.setTypeEquals(BaseType.INT);
074        partitionRows = new Parameter(this, "partitionRows", new IntToken("2"));
075        partitionRows.setTypeEquals(BaseType.INT);
076
077        output_tokenProductionRate = new Parameter(output,
078                "tokenProductionRate");
079        output_tokenProductionRate.setTypeEquals(BaseType.INT);
080        output_tokenProductionRate.setExpression(
081                "imageColumns * imageRows / partitionColumns / partitionRows");
082
083        input.setTypeEquals(BaseType.INT_MATRIX);
084        output.setTypeEquals(BaseType.INT_MATRIX);
085    }
086
087    ///////////////////////////////////////////////////////////////////
088    ////                      ports and parameters                 ////
089
090    /** The width of the input matrices. */
091    public Parameter imageColumns;
092
093    /** The height of the input matrices. */
094    public Parameter imageRows;
095
096    /** The width of the input partitions. */
097    public Parameter partitionColumns;
098
099    /** The height of the input partitions. */
100    public Parameter partitionRows;
101
102    /** The output rate. */
103    public Parameter output_tokenProductionRate;
104
105    ///////////////////////////////////////////////////////////////////
106    ////                         public methods                    ////
107
108    /**
109     * Initialize this actor.
110     * @exception IllegalActionException If a parameter does not contain a
111     * legal value, or partitionColumns does not equally divide imageColumns,
112     * or partitionRows does not equally divide imageRows.
113     */
114    @Override
115    public void initialize() throws IllegalActionException {
116        super.initialize();
117
118        _imageColumns = ((IntToken) imageColumns.getToken()).intValue();
119        _imageRows = ((IntToken) imageRows.getToken()).intValue();
120        _partitionColumns = ((IntToken) partitionColumns.getToken()).intValue();
121        _partitionRows = ((IntToken) partitionRows.getToken()).intValue();
122
123        if (_imageColumns % _partitionColumns != 0) {
124            throw new IllegalActionException(imageColumns, partitionColumns,
125                    "Partition size must evenly divide image size");
126        }
127
128        if (_imageRows % _partitionRows != 0) {
129            throw new IllegalActionException(imageRows, partitionRows,
130                    "Partition size must evenly divide image size");
131        }
132
133        _part = new int[_partitionRows][_partitionColumns];
134
135        int partitionCount = _imageColumns * _imageRows / _partitionColumns
136                / _partitionRows;
137        _partitions = new IntMatrixToken[partitionCount];
138    }
139
140    /**
141     * Fire this actor.  Consume a single IntMatrixToken on the input.
142     * Produce IntMatrixTokens on the output port by partitioning the
143     * input image.
144     *
145     * @exception IllegalActionException If the input size is not
146     * <i>imageRows</i> by <i>imageColumns</i>.
147     */
148    @Override
149    public void fire() throws IllegalActionException {
150        super.fire();
151        int i;
152        int j;
153        int y;
154        int partitionNumber;
155        IntMatrixToken message;
156
157        message = (IntMatrixToken) input.get(0);
158
159        if (message.getRowCount() != _imageRows
160                || message.getColumnCount() != _imageColumns) {
161            throw new IllegalActionException(
162                    "Input data must be imageRows " + "by imageColumns");
163        }
164
165        int[][] image = message.intMatrix();
166
167        for (j = 0, partitionNumber = 0; j < _imageRows; j += _partitionRows) {
168            for (i = 0; i < _imageColumns; i += _partitionColumns, partitionNumber++) {
169                for (y = 0; y < _partitionRows; y++) {
170                    System.arraycopy(image[j + y], i, _part[y], 0,
171                            _partitionColumns);
172                }
173
174                _partitions[partitionNumber] = new IntMatrixToken(_part);
175            }
176        }
177
178        output.send(0, _partitions, _partitions.length);
179    }
180
181    ///////////////////////////////////////////////////////////////////
182    ////                         private variables                 ////
183    private IntMatrixToken[] _partitions;
184
185    private int[][] _part;
186
187    private int _imageColumns;
188
189    private int _imageRows;
190
191    private int _partitionColumns;
192
193    private int _partitionRows;
194}