001/* ReplicateScaleFilter.java -- Java class for filtering images
002   Copyright (C) 1999 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt.image;
040
041import java.util.Hashtable;
042
043/**
044 * This filter should be used for fast scaling of images where the result
045 * does not need to ensure straight lines are still straight, etc.  The
046 * exact method is not defined by Sun but some sort of fast Box filter should
047 * probably be correct.
048 * <br>
049 * Currently this filter does nothing and needs to be implemented.
050 *
051 * @author C. Brian Jones (cbj@gnu.org) 
052 */
053public class ReplicateScaleFilter extends ImageFilter
054{
055    public ReplicateScaleFilter(int width, int height) {
056        destHeight = height;
057        destWidth = width;
058    }
059
060    /**
061     * The height of the destination image.
062     */
063    protected int destHeight;
064
065    /**
066     * The width of the destination image.
067     */
068    protected int destWidth;
069
070    /**
071     * The height of the source image.
072     */
073    protected int srcHeight;
074
075    /**
076     * The width of the source image.
077     */
078    protected int srcWidth;
079
080    /**
081     *
082     */
083    protected int srcrows[];
084
085    /**
086     *
087     */
088    protected int srccols[];
089
090    /**
091     *
092     */
093    protected Object outpixbuf;
094
095    /**
096     * An <code>ImageProducer</code> indicates the size of the image
097     * being produced using this method.  A filter can override this 
098     * method to intercept these calls from the producer in order to
099     * change either the width or the height before in turn calling
100     * the consumer's <code>setDimensions</code> method.
101     * 
102     * @param width the width of the image
103     * @param height the height of the image 
104     */
105    public void setDimensions(int width, int height)
106    {
107        srcWidth = width;
108        srcHeight = height;
109
110        /* If either destHeight or destWidth is < 0, the image should
111           maintain its original aspect ratio.  When both are < 0,
112           just maintain the original width and height. */
113        if (destWidth < 0 && destHeight < 0)
114        {
115            destWidth = width;
116            destHeight = height;
117        }
118        else if (destWidth < 0)
119        {
120            destWidth = width * destHeight / srcHeight;
121        }
122        else if (destHeight < 0)
123        {
124            destHeight = height * destWidth / srcWidth;
125        }
126
127        if (consumer != null)
128          consumer.setDimensions(destWidth, destHeight);
129    }
130
131    /**
132     * An <code>ImageProducer</code> can set a list of properties
133     * associated with this image by using this method.
134     *
135     * @param props the list of properties associated with this image 
136     */
137    public void setProperties(Hashtable<?, ?> props)
138    {
139      Hashtable<Object, Object> prop2 = (Hashtable<Object, Object>) props;
140      prop2.put("filters", "ReplicateScaleFilter");
141      if (consumer != null)
142        consumer.setProperties(prop2);
143    }
144
145    /**
146     * This function delivers a rectangle of pixels where any
147     * pixel(m,n) is stored in the array as a <code>byte</code> at
148     * index (n * scansize + m + offset).  
149     *
150     * @param x the x coordinate of the rectangle
151     * @param y the y coordinate of the rectangle
152     * @param w the width of the rectangle
153     * @param h the height of the rectangle
154     * @param model the <code>ColorModel</code> used to translate the pixels
155     * @param pixels the array of pixel values
156     * @param offset the index of the first pixels in the <code>pixels</code> array
157     * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
158     */
159    public void setPixels(int x, int y, int w, int h, 
160           ColorModel model, byte[] pixels, int offset, int scansize)
161    {
162      if (srcrows == null || srccols == null)
163        setupSources();
164      int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
165      int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
166      byte[] pix;
167      if (outpixbuf != null && outpixbuf instanceof byte[])
168        {
169          pix = (byte[]) outpixbuf;
170        }
171      else
172        {
173          pix = new byte[destWidth];
174          outpixbuf = pix;
175        }
176      int sy, sx;
177      for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
178        {
179          int offs = offset + scansize * (sy - y);
180          int xx;
181          for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
182            {
183              pix[xx] = pixels[offs + sx - x];
184            }
185          if (xx > dx1)
186            {
187              consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
188                                 destWidth);
189            }
190        }
191    }
192
193    /**
194     * This function delivers a rectangle of pixels where any
195     * pixel(m,n) is stored in the array as an <code>int</code> at
196     * index (n * scansize + m + offset).  
197     *
198     * @param x the x coordinate of the rectangle
199     * @param y the y coordinate of the rectangle
200     * @param w the width of the rectangle
201     * @param h the height of the rectangle
202     * @param model the <code>ColorModel</code> used to translate the pixels
203     * @param pixels the array of pixel values
204     * @param offset the index of the first pixels in the <code>pixels</code> array
205     * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
206     */
207    public void setPixels(int x, int y, int w, int h, 
208           ColorModel model, int[] pixels, int offset, int scansize)
209    {
210      if (srcrows == null || srccols == null)
211        setupSources();
212      int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
213      int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
214      int[] pix;
215      if (outpixbuf != null && outpixbuf instanceof int[])
216        {
217          pix = (int[]) outpixbuf;
218        }
219      else
220        {
221          pix = new int[destWidth];
222          outpixbuf = pix;
223        }
224      int sy, sx;
225      for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
226        {
227          int offs = offset + scansize * (sy - y);
228          int xx;
229          for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
230            {
231              pix[xx] = pixels[offs + sx - x];
232            }
233          if (xx > dx1)
234            {
235              consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
236                                 destWidth);
237            }
238        }
239    }
240
241  /**
242   * Sets up the srcrows and srccols arrays.
243   */
244  private void setupSources()
245  {
246    srcrows = new int[destHeight + 1];
247    for (int y = 0; y <= destHeight; y++)
248      {
249        srcrows[y] = (2 * y * srcHeight + srcHeight) / (2 * destHeight);
250      }
251    srccols = new int[destWidth + 1];
252    for (int x = 0; x <= destWidth; x++)
253      {
254        srccols[x] = (2 * x * srcWidth + srcWidth) / (2 * destWidth);
255      }
256  }
257}
258