Source for java.awt.image.RGBImageFilter

   1: /* RGBImageFilter.java -- Java class for filtering Pixels by RGB values
   2:    Copyright (C) 1999, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt.image;
  40: 
  41: /**
  42:  * A filter designed to filter images in the default RGBColorModel regardless of 
  43:  * the ImageProducer's ColorModel.
  44:  *
  45:  * @author Mark Benvenuto (mcb54@columbia.edu)
  46:  */
  47: public abstract class RGBImageFilter extends ImageFilter
  48: {
  49:     protected ColorModel origmodel;
  50: 
  51:     protected ColorModel newmodel;
  52:     
  53:     /**
  54:        Specifies whether to apply the filter to the index entries of the 
  55:        IndexColorModel. Subclasses should set this to true if the filter 
  56:        does not depend on the pixel's coordinate.
  57:      */
  58:     protected boolean canFilterIndexColorModel = false;
  59: 
  60:     /**
  61:        Construct new RGBImageFilter.
  62:      */
  63:     public RGBImageFilter() 
  64:     {
  65:     }
  66: 
  67:     /**
  68:      * Sets the ColorModel used to filter with. If the specified ColorModel is IndexColorModel 
  69:      * and canFilterIndexColorModel is true, we subsitute the ColorModel for a filtered one
  70:      * here and in setPixels whenever the original one appears. Otherwise overrides the default
  71:      * ColorModel of ImageProducer and specifies the default RGBColorModel
  72:      *
  73:      * @param model the color model to be used most often by setPixels
  74:      * @see ColorModel */
  75:     public void setColorModel(ColorModel model) 
  76:     {
  77:     origmodel = model;
  78:     newmodel = model;
  79: 
  80:     if( ( model instanceof IndexColorModel) && canFilterIndexColorModel  ) {
  81:         newmodel = filterIndexColorModel( (IndexColorModel) model );
  82:         consumer.setColorModel(newmodel);
  83:         }
  84:     else {
  85:         consumer.setColorModel(ColorModel.getRGBdefault());
  86:     }
  87:     }
  88:     
  89:     /**
  90:        Registers a new ColorModel to subsitute for the old ColorModel when 
  91:        setPixels encounters the a pixel with the old ColorModel. The pixel 
  92:        remains unchanged except for a new ColorModel.
  93:        
  94:        @param oldcm the old ColorModel
  95:        @param newcm the new ColorModel
  96:      */
  97:     public void substituteColorModel(ColorModel oldcm,
  98:                      ColorModel newcm)
  99:     {
 100:     origmodel = oldcm;
 101:     newmodel = newcm;
 102:     }
 103: 
 104:     /**
 105:        Filters an IndexColorModel through the filterRGB function. Uses
 106:        coordinates of -1 to indicate its filtering an index and not a pixel.
 107: 
 108:        @param icm an IndexColorModel to filter
 109:      */
 110:     public IndexColorModel filterIndexColorModel(IndexColorModel icm) 
 111:     {
 112:     int len = icm.getMapSize(), rgb;
 113:     byte reds[] = new byte[len], greens[] = new byte[len], blues[] = new byte[len], alphas[]  = new byte[len];
 114:     
 115:     icm.getAlphas( alphas );
 116:     icm.getReds( reds );
 117:     icm.getGreens( greens );
 118:     icm.getBlues( blues );
 119: 
 120:     for( int i = 0; i < len; i++ )
 121:         {
 122:         rgb = filterRGB( -1, -1, makeColor ( alphas[i], reds[i], greens[i], blues[i] ) );
 123:         alphas[i] = (byte)(( 0xff000000 & rgb ) >> 24);
 124:         reds[i] = (byte)(( 0xff0000 & rgb ) >> 16);
 125:         greens[i] = (byte)(( 0xff00 & rgb ) >> 8);
 126:         blues[i] = (byte)(0xff & rgb);
 127:         }
 128:     return new IndexColorModel( icm.getPixelSize(), len, reds, greens, blues, alphas );
 129:     }
 130: 
 131:     private int makeColor( byte a, byte r, byte g, byte b )
 132:     {
 133:     return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b ); 
 134:     }
 135: 
 136:     /**
 137:        This functions filters a set of RGB pixels through filterRGB.
 138: 
 139:        @param x the x coordinate of the rectangle
 140:        @param y the y coordinate of the rectangle
 141:        @param w the width of the rectangle
 142:        @param h the height of the rectangle
 143:        @param pixels the array of pixel values
 144:        @param offset the index of the first pixels in the <code>pixels</code> array
 145:        @param scansize the width to use in extracting pixels from the <code>pixels</code> array
 146:     */
 147:     public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
 148:                 int offset, int scansize)
 149:     {
 150:       for (int yp = 0; yp < h; yp++)
 151:     {
 152:       for (int xp = 0; xp < w; xp++)
 153:         {
 154:           pixels[offset + xp] = filterRGB(xp + x, yp + y, pixels[offset + xp]);
 155:         }
 156:       offset += scansize;
 157:     }
 158:     }
 159: 
 160: 
 161:     /**
 162:      * If the ColorModel is the same ColorModel which as already converted 
 163:      * then it converts it the converted ColorModel. Otherwise it passes the 
 164:      * array of pixels through filterRGBpixels.
 165:      *
 166:      * @param x the x coordinate of the rectangle
 167:      * @param y the y coordinate of the rectangle
 168:      * @param w the width of the rectangle
 169:      * @param h the height of the rectangle
 170:      * @param model the <code>ColorModel</code> used to translate the pixels
 171:      * @param pixels the array of pixel values
 172:      * @param offset the index of the first pixels in the <code>pixels</code> array
 173:      * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
 174:      */
 175:     public void setPixels(int x, int y, int w, int h, 
 176:                           ColorModel model, byte[] pixels,
 177:                           int offset, int scansize)
 178:     {
 179:     if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
 180:     {
 181:         consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
 182:     }
 183:     else
 184:     {
 185:         int intPixels[] =
 186:         convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
 187:         filterRGBPixels( x, y, w, h, intPixels, offset, scansize );
 188:         consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), intPixels, offset, scansize);
 189:     }
 190:     }
 191: 
 192:     /**
 193:      * This function delivers a rectangle of pixels where any
 194:      * pixel(m,n) is stored in the array as an <code>int</code> at
 195:      * index (n * scansize + m + offset).  
 196:      *
 197:      * @param x the x coordinate of the rectangle
 198:      * @param y the y coordinate of the rectangle
 199:      * @param w the width of the rectangle
 200:      * @param h the height of the rectangle
 201:      * @param model the <code>ColorModel</code> used to translate the pixels
 202:      * @param pixels the array of pixel values
 203:      * @param offset the index of the first pixels in the <code>pixels</code> array
 204:      * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
 205:      */
 206:     public void setPixels(int x, int y, int w, int h, 
 207:                           ColorModel model, int[] pixels,
 208:                           int offset, int scansize)
 209:     {
 210:     if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
 211:     {
 212:         consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
 213:     }
 214:     else
 215:     {
 216:         //FIXME: Store the filtered pixels in a separate temporary buffer?
 217:       convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
 218:       filterRGBPixels( x, y, w, h, pixels, offset, scansize );
 219:       consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset, scansize);
 220:     }
 221:     }
 222: 
 223:     private int[] convertColorModelToDefault(int x, int y, int w, int h, 
 224:                                             ColorModel model, byte pixels[],
 225:                                             int offset, int scansize)
 226:     {
 227:     int intPixels[] = new int[pixels.length];
 228:     for (int i = 0; i < pixels.length; i++)
 229:         intPixels[i] = makeColorbyDefaultCM(model, pixels[i]);
 230:     return intPixels;
 231:     }
 232: 
 233:     private void convertColorModelToDefault(int x, int y, int w, int h, 
 234:                                             ColorModel model, int pixels[],
 235:                                             int offset, int scansize)
 236:     {
 237:     for (int i = 0; i < pixels.length; i++)
 238:         pixels[i] = makeColorbyDefaultCM(model, pixels[i]);
 239:     }
 240: 
 241:     private int makeColorbyDefaultCM(ColorModel model, byte rgb) 
 242:     {
 243:     return makeColor( model.getAlpha( rgb ) * 4, model.getRed( rgb ) * 4, model.getGreen( rgb ) * 4, model.getBlue( rgb ) * 4 );
 244:     }
 245: 
 246:     private int makeColorbyDefaultCM(ColorModel model, int rgb) 
 247:     {
 248:     return makeColor( model.getAlpha( rgb ), model.getRed( rgb ), model.getGreen( rgb ), model.getBlue( rgb ) );
 249:     }
 250: 
 251:     private int makeColor( int a, int r, int g, int b )
 252:     {
 253:     return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b ); 
 254:     }
 255: 
 256: 
 257:     /**
 258:        Filters a single pixel from the default ColorModel.
 259: 
 260:        @param x x-coordinate
 261:        @param y y-coordinate
 262:        @param rgb color
 263:      */
 264:     public abstract int filterRGB(int x,
 265:                   int y,
 266:                   int rgb);
 267: }