Home » openjdk-7 » java » awt » image » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt.image;
   27   
   28   import java.util.Hashtable;
   29   import java.awt.image.ImageConsumer;
   30   import java.awt.image.ImageFilter;
   31   
   32   /**
   33    * The <code>BufferedImageFilter</code> class subclasses an
   34    * <code>ImageFilter</code> to provide a simple means of
   35    * using a single-source/single-destination image operator
   36    * ({@link BufferedImageOp}) to filter a <code>BufferedImage</code>
   37    * in the Image Producer/Consumer/Observer
   38    * paradigm. Examples of these image operators are: {@link ConvolveOp},
   39    * {@link AffineTransformOp} and {@link LookupOp}.
   40    *
   41    * @see ImageFilter
   42    * @see BufferedImage
   43    * @see BufferedImageOp
   44    */
   45   
   46   public class BufferedImageFilter extends ImageFilter implements Cloneable {
   47       BufferedImageOp bufferedImageOp;
   48       ColorModel model;
   49       int width;
   50       int height;
   51       byte[] bytePixels;
   52       int[] intPixels;
   53   
   54       /**
   55        * Constructs a <code>BufferedImageFilter</code> with the
   56        * specified single-source/single-destination operator.
   57        * @param op the specified <code>BufferedImageOp</code> to
   58        *           use to filter a <code>BufferedImage</code>
   59        * @throws NullPointerException if op is null
   60        */
   61       public BufferedImageFilter (BufferedImageOp op) {
   62           super();
   63           if (op == null) {
   64               throw new NullPointerException("Operation cannot be null");
   65           }
   66           bufferedImageOp = op;
   67       }
   68   
   69       /**
   70        * Returns the <code>BufferedImageOp</code>.
   71        * @return the operator of this <code>BufferedImageFilter</code>.
   72        */
   73       public BufferedImageOp getBufferedImageOp() {
   74           return bufferedImageOp;
   75       }
   76   
   77       /**
   78        * Filters the information provided in the
   79        * {@link ImageConsumer#setDimensions(int, int) setDimensions } method
   80        * of the {@link ImageConsumer} interface.
   81        * <p>
   82        * Note: This method is intended to be called by the
   83        * {@link ImageProducer} of the <code>Image</code> whose pixels are
   84        * being filtered. Developers using this class to retrieve pixels from
   85        * an image should avoid calling this method directly since that
   86        * operation could result in problems with retrieving the requested
   87        * pixels.
   88        * <p>
   89        * @param width the width to which to set the width of this
   90        *        <code>BufferedImageFilter</code>
   91        * @param height the height to which to set the height of this
   92        *        <code>BufferedImageFilter</code>
   93        * @see ImageConsumer#setDimensions
   94        */
   95       public void setDimensions(int width, int height) {
   96           if (width <= 0 || height <= 0) {
   97               imageComplete(STATICIMAGEDONE);
   98               return;
   99           }
  100           this.width  = width;
  101           this.height = height;
  102       }
  103   
  104       /**
  105        * Filters the information provided in the
  106        * {@link ImageConsumer#setColorModel(ColorModel) setColorModel} method
  107        * of the <code>ImageConsumer</code> interface.
  108        * <p>
  109        * If <code>model</code> is <code>null</code>, this
  110        * method clears the current <code>ColorModel</code> of this
  111        * <code>BufferedImageFilter</code>.
  112        * <p>
  113        * Note: This method is intended to be called by the
  114        * <code>ImageProducer</code> of the <code>Image</code>
  115        * whose pixels are being filtered.  Developers using this
  116        * class to retrieve pixels from an image
  117        * should avoid calling this method directly since that
  118        * operation could result in problems with retrieving the
  119        * requested pixels.
  120        * @param model the {@link ColorModel} to which to set the
  121        *        <code>ColorModel</code> of this <code>BufferedImageFilter</code>
  122        * @see ImageConsumer#setColorModel
  123        */
  124       public void setColorModel(ColorModel model) {
  125           this.model = model;
  126       }
  127   
  128       private void convertToRGB() {
  129           int size = width * height;
  130           int newpixels[] = new int[size];
  131           if (bytePixels != null) {
  132               for (int i = 0; i < size; i++) {
  133                   newpixels[i] = this.model.getRGB(bytePixels[i] & 0xff);
  134               }
  135           } else if (intPixels != null) {
  136               for (int i = 0; i < size; i++) {
  137                   newpixels[i] = this.model.getRGB(intPixels[i]);
  138               }
  139           }
  140           bytePixels = null;
  141           intPixels = newpixels;
  142           this.model = ColorModel.getRGBdefault();
  143       }
  144   
  145       /**
  146        * Filters the information provided in the <code>setPixels</code>
  147        * method of the <code>ImageConsumer</code> interface which takes
  148        * an array of bytes.
  149        * <p>
  150        * Note: This method is intended to be called by the
  151        * <code>ImageProducer</code> of the <code>Image</code> whose pixels
  152        * are being filtered.  Developers using
  153        * this class to retrieve pixels from an image should avoid calling
  154        * this method directly since that operation could result in problems
  155        * with retrieving the requested pixels.
  156        * @throws IllegalArgumentException if width or height are less than
  157        * zero.
  158        * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, byte[],
  159                                       int, int)
  160        */
  161       public void setPixels(int x, int y, int w, int h,
  162                             ColorModel model, byte pixels[], int off,
  163                             int scansize) {
  164           // Fix 4184230
  165           if (w < 0 || h < 0) {
  166               throw new IllegalArgumentException("Width ("+w+
  167                                                   ") and height ("+h+
  168                                                   ") must be > 0");
  169           }
  170           // Nothing to do
  171           if (w == 0 || h == 0) {
  172               return;
  173           }
  174           if (y < 0) {
  175               int diff = -y;
  176               if (diff >= h) {
  177                   return;
  178               }
  179               off += scansize * diff;
  180               y += diff;
  181               h -= diff;
  182           }
  183           if (y + h > height) {
  184               h = height - y;
  185               if (h <= 0) {
  186                   return;
  187               }
  188           }
  189           if (x < 0) {
  190               int diff = -x;
  191               if (diff >= w) {
  192                   return;
  193               }
  194               off += diff;
  195               x += diff;
  196               w -= diff;
  197           }
  198           if (x + w > width) {
  199               w = width - x;
  200               if (w <= 0) {
  201                   return;
  202               }
  203           }
  204           int dstPtr = y*width + x;
  205           if (intPixels == null) {
  206               if (bytePixels == null) {
  207                   bytePixels = new byte[width*height];
  208                   this.model = model;
  209               } else if (this.model != model) {
  210                   convertToRGB();
  211               }
  212               if (bytePixels != null) {
  213                   for (int sh = h; sh > 0; sh--) {
  214                       System.arraycopy(pixels, off, bytePixels, dstPtr, w);
  215                       off += scansize;
  216                       dstPtr += width;
  217                   }
  218               }
  219           }
  220           if (intPixels != null) {
  221               int dstRem = width - w;
  222               int srcRem = scansize - w;
  223               for (int sh = h; sh > 0; sh--) {
  224                   for (int sw = w; sw > 0; sw--) {
  225                       intPixels[dstPtr++] = model.getRGB(pixels[off++]&0xff);
  226                   }
  227                   off    += srcRem;
  228                   dstPtr += dstRem;
  229               }
  230           }
  231       }
  232       /**
  233        * Filters the information provided in the <code>setPixels</code>
  234        * method of the <code>ImageConsumer</code> interface which takes
  235        * an array of integers.
  236        * <p>
  237        * Note: This method is intended to be called by the
  238        * <code>ImageProducer</code> of the <code>Image</code> whose
  239        * pixels are being filtered.  Developers using this class to
  240        * retrieve pixels from an image should avoid calling this method
  241        * directly since that operation could result in problems
  242        * with retrieving the requested pixels.
  243        * @throws IllegalArgumentException if width or height are less than
  244        * zero.
  245        * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, int[],
  246                                       int, int)
  247        */
  248       public void setPixels(int x, int y, int w, int h,
  249                             ColorModel model, int pixels[], int off,
  250                             int scansize) {
  251           // Fix 4184230
  252           if (w < 0 || h < 0) {
  253               throw new IllegalArgumentException("Width ("+w+
  254                                                   ") and height ("+h+
  255                                                   ") must be > 0");
  256           }
  257           // Nothing to do
  258           if (w == 0 || h == 0) {
  259               return;
  260           }
  261           if (y < 0) {
  262               int diff = -y;
  263               if (diff >= h) {
  264                   return;
  265               }
  266               off += scansize * diff;
  267               y += diff;
  268               h -= diff;
  269           }
  270           if (y + h > height) {
  271               h = height - y;
  272               if (h <= 0) {
  273                   return;
  274               }
  275           }
  276           if (x < 0) {
  277               int diff = -x;
  278               if (diff >= w) {
  279                   return;
  280               }
  281               off += diff;
  282               x += diff;
  283               w -= diff;
  284           }
  285           if (x + w > width) {
  286               w = width - x;
  287               if (w <= 0) {
  288                   return;
  289               }
  290           }
  291   
  292           if (intPixels == null) {
  293               if (bytePixels == null) {
  294                   intPixels = new int[width * height];
  295                   this.model = model;
  296               } else {
  297                   convertToRGB();
  298               }
  299           }
  300           int dstPtr = y*width + x;
  301           if (this.model == model) {
  302               for (int sh = h; sh > 0; sh--) {
  303                   System.arraycopy(pixels, off, intPixels, dstPtr, w);
  304                   off += scansize;
  305                   dstPtr += width;
  306               }
  307           } else {
  308               if (this.model != ColorModel.getRGBdefault()) {
  309                   convertToRGB();
  310               }
  311               int dstRem = width - w;
  312               int srcRem = scansize - w;
  313               for (int sh = h; sh > 0; sh--) {
  314                   for (int sw = w; sw > 0; sw--) {
  315                       intPixels[dstPtr++] = model.getRGB(pixels[off++]);
  316                   }
  317                   off += srcRem;
  318                   dstPtr += dstRem;
  319               }
  320           }
  321       }
  322   
  323       /**
  324        * Filters the information provided in the <code>imageComplete</code>
  325        * method of the <code>ImageConsumer</code> interface.
  326        * <p>
  327        * Note: This method is intended to be called by the
  328        * <code>ImageProducer</code> of the <code>Image</code> whose pixels
  329        * are being filtered.  Developers using
  330        * this class to retrieve pixels from an image should avoid calling
  331        * this method directly since that operation could result in problems
  332        * with retrieving the requested pixels.
  333        * @param status the status of image loading
  334        * @throws ImagingOpException if there was a problem calling the filter
  335        * method of the <code>BufferedImageOp</code> associated with this
  336        * instance.
  337        * @see ImageConsumer#imageComplete
  338        */
  339       public void imageComplete(int status) {
  340           WritableRaster wr;
  341           switch(status) {
  342           case IMAGEERROR:
  343           case IMAGEABORTED:
  344               // reinitialize the params
  345               model  = null;
  346               width  = -1;
  347               height = -1;
  348               intPixels  = null;
  349               bytePixels = null;
  350               break;
  351   
  352           case SINGLEFRAMEDONE:
  353           case STATICIMAGEDONE:
  354               if (width <= 0 || height <= 0) break;
  355               if (model instanceof DirectColorModel) {
  356                   if (intPixels == null) break;
  357                   wr = createDCMraster();
  358               }
  359               else if (model instanceof IndexColorModel) {
  360                   int[] bandOffsets = {0};
  361                   if (bytePixels == null) break;
  362                   DataBufferByte db = new DataBufferByte(bytePixels,
  363                                                          width*height);
  364                   wr = Raster.createInterleavedRaster(db, width, height, width,
  365                                                       1, bandOffsets, null);
  366               }
  367               else {
  368                   convertToRGB();
  369                   if (intPixels == null) break;
  370                   wr = createDCMraster();
  371               }
  372               BufferedImage bi = new BufferedImage(model, wr,
  373                                                    model.isAlphaPremultiplied(),
  374                                                    null);
  375               bi = bufferedImageOp.filter(bi, null);
  376               WritableRaster r = bi.getRaster();
  377               ColorModel cm = bi.getColorModel();
  378               int w = r.getWidth();
  379               int h = r.getHeight();
  380               consumer.setDimensions(w, h);
  381               consumer.setColorModel(cm);
  382               if (cm instanceof DirectColorModel) {
  383                   DataBufferInt db = (DataBufferInt) r.getDataBuffer();
  384                   consumer.setPixels(0, 0, w, h,
  385                                      cm, db.getData(), 0, w);
  386               }
  387               else if (cm instanceof IndexColorModel) {
  388                   DataBufferByte db = (DataBufferByte) r.getDataBuffer();
  389                   consumer.setPixels(0, 0, w, h,
  390                                      cm, db.getData(), 0, w);
  391               }
  392               else {
  393                   throw new InternalError("Unknown color model "+cm);
  394               }
  395               break;
  396           }
  397           consumer.imageComplete(status);
  398       }
  399   
  400       private final WritableRaster createDCMraster() {
  401           WritableRaster wr;
  402           DirectColorModel dcm = (DirectColorModel) model;
  403           boolean hasAlpha = model.hasAlpha();
  404           int[] bandMasks = new int[3+(hasAlpha ? 1 : 0)];
  405           bandMasks[0] = dcm.getRedMask();
  406           bandMasks[1] = dcm.getGreenMask();
  407           bandMasks[2] = dcm.getBlueMask();
  408           if (hasAlpha) {
  409               bandMasks[3] = dcm.getAlphaMask();
  410           }
  411           DataBufferInt db = new DataBufferInt(intPixels, width*height);
  412           wr = Raster.createPackedRaster(db, width, height, width,
  413                                          bandMasks, null);
  414           return wr;
  415       }
  416   
  417   }

Home » openjdk-7 » java » awt » image » [javadoc | source]