1. /*
  2. * @(#)RGBImageFilter.java 1.15 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.image;
  8. import java.awt.image.ImageConsumer;
  9. import java.awt.image.ColorModel;
  10. /**
  11. * This class provides an easy way to create an ImageFilter which modifies
  12. * the pixels of an image in the default RGB ColorModel. It is meant to
  13. * be used in conjunction with a FilteredImageSource object to produce
  14. * filtered versions of existing images. It is an abstract class that
  15. * provides the calls needed to channel all of the pixel data through a
  16. * single method which converts pixels one at a time in the default RGB
  17. * ColorModel regardless of the ColorModel being used by the ImageProducer.
  18. * The only method which needs to be defined to create a useable image
  19. * filter is the filterRGB method. Here is an example of a definition
  20. * of a filter which swaps the red and blue components of an image:
  21. * <pre>
  22. *
  23. * class RedBlueSwapFilter extends RGBImageFilter {
  24. * public RedBlueSwapFilter() {
  25. * // The filter's operation does not depend on the
  26. * // pixel's location, so IndexColorModels can be
  27. * // filtered directly.
  28. * canFilterIndexColorModel = true;
  29. * }
  30. *
  31. * public int filterRGB(int x, int y, int rgb) {
  32. * return ((rgb & 0xff00ff00)
  33. * | ((rgb & 0xff0000) >> 16)
  34. * | ((rgb & 0xff) << 16));
  35. * }
  36. * }
  37. *
  38. * </pre>
  39. *
  40. * @see FilteredImageSource
  41. * @see ImageFilter
  42. * @see ColorModel#getRGBdefault
  43. *
  44. * @version 1.15 11/29/01
  45. * @author Jim Graham
  46. */
  47. public abstract class RGBImageFilter extends ImageFilter {
  48. protected ColorModel origmodel;
  49. protected ColorModel newmodel;
  50. /**
  51. * This boolean indicates whether or not it is acceptable to apply
  52. * the color filtering of the filterRGB method to the color table
  53. * entries of an IndexColorModel object in lieu of pixel by pixel
  54. * filtering. Subclasses should set this variable to true in their
  55. * constructor if their filterRGB method does not depend on the
  56. * coordinate of the pixel being filtered.
  57. * @see #substituteColorModel
  58. * @see #filterRGB
  59. * @see IndexColorModel
  60. */
  61. protected boolean canFilterIndexColorModel;
  62. /**
  63. * If the ColorModel is an IndexColorModel, and the subclass has
  64. * set the canFilterIndexColorModel flag to true, we substitute
  65. * a filtered version of the color model here and wherever
  66. * that original ColorModel object appears in the setPixels methods. Otherwise
  67. * overrides the default ColorModel used by the ImageProducer and
  68. * specifies the default RGB ColorModel instead.
  69. * @see ImageConsumer
  70. * @see ColorModel#getRGBdefault
  71. */
  72. public void setColorModel(ColorModel model) {
  73. if (canFilterIndexColorModel && (model instanceof IndexColorModel)) {
  74. ColorModel newcm = filterIndexColorModel((IndexColorModel)model);
  75. substituteColorModel(model, newcm);
  76. consumer.setColorModel(newcm);
  77. } else {
  78. consumer.setColorModel(ColorModel.getRGBdefault());
  79. }
  80. }
  81. /**
  82. * Registers two ColorModel objects for substitution. If the oldcm
  83. * is encountered during any of the setPixels methods, the newcm
  84. * is substituted and the pixels passed through
  85. * untouched (but with the new ColorModel object).
  86. * @param oldcm the ColorModel object to be replaced on the fly
  87. * @param newcm the ColorModel object to replace oldcm on the fly
  88. */
  89. public void substituteColorModel(ColorModel oldcm, ColorModel newcm) {
  90. origmodel = oldcm;
  91. newmodel = newcm;
  92. }
  93. /**
  94. * Filters an IndexColorModel object by running each entry in its
  95. * color tables through the filterRGB function that RGBImageFilter
  96. * subclasses must provide. Uses coordinates of -1 to indicate that
  97. * a color table entry is being filtered rather than an actual
  98. * pixel value.
  99. * @param icm the IndexColorModel object to be filtered
  100. * @return a new IndexColorModel representing the filtered colors
  101. */
  102. public IndexColorModel filterIndexColorModel(IndexColorModel icm) {
  103. int mapsize = icm.getMapSize();
  104. byte r[] = new byte[mapsize];
  105. byte g[] = new byte[mapsize];
  106. byte b[] = new byte[mapsize];
  107. byte a[] = new byte[mapsize];
  108. icm.getReds(r);
  109. icm.getGreens(g);
  110. icm.getBlues(b);
  111. icm.getAlphas(a);
  112. int trans = icm.getTransparentPixel();
  113. boolean needalpha = false;
  114. for (int i = 0; i < mapsize; i++) {
  115. int rgb = filterRGB(-1, -1, icm.getRGB(i));
  116. a[i] = (byte) (rgb >> 24);
  117. if (a[i] != ((byte)0xff) && i != trans) {
  118. needalpha = true;
  119. }
  120. r[i] = (byte) (rgb >> 16);
  121. g[i] = (byte) (rgb >> 8);
  122. b[i] = (byte) (rgb >> 0);
  123. }
  124. if (needalpha) {
  125. return new IndexColorModel(icm.getPixelSize(), mapsize,
  126. r, g, b, a);
  127. } else {
  128. return new IndexColorModel(icm.getPixelSize(), mapsize,
  129. r, g, b, trans);
  130. }
  131. }
  132. /**
  133. * Filters a buffer of pixels in the default RGB ColorModel by passing
  134. * them one by one through the filterRGB method.
  135. * @see ColorModel#getRGBdefault
  136. * @see #filterRGB
  137. */
  138. public void filterRGBPixels(int x, int y, int w, int h,
  139. int pixels[], int off, int scansize) {
  140. int index = off;
  141. for (int cy = 0; cy < h; cy++) {
  142. for (int cx = 0; cx < w; cx++) {
  143. pixels[index] = filterRGB(x + cx, y + cy, pixels[index]);
  144. index++;
  145. }
  146. index += scansize - w;
  147. }
  148. consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(),
  149. pixels, off, scansize);
  150. }
  151. /**
  152. * If the ColorModel object is the same one that has already
  153. * been converted, then simply passes the pixels through with the
  154. * converted ColorModel. Otherwise converts the buffer of byte
  155. * pixels to the default RGB ColorModel and passes the converted
  156. * buffer to the filterRGBPixels method to be converted one by one.
  157. * @see ColorModel#getRGBdefault
  158. * @see #filterRGBPixels
  159. */
  160. public void setPixels(int x, int y, int w, int h,
  161. ColorModel model, byte pixels[], int off,
  162. int scansize) {
  163. if (model == origmodel) {
  164. consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
  165. } else {
  166. int filteredpixels[] = new int[w];
  167. int index = off;
  168. for (int cy = 0; cy < h; cy++) {
  169. for (int cx = 0; cx < w; cx++) {
  170. filteredpixels[cx] = model.getRGB((pixels[index] & 0xff));
  171. index++;
  172. }
  173. index += scansize - w;
  174. filterRGBPixels(x, y + cy, w, 1, filteredpixels, 0, w);
  175. }
  176. }
  177. }
  178. /**
  179. * If the ColorModel object is the same one that has already
  180. * been converted, then simply passes the pixels through with the
  181. * converted ColorModel, otherwise converts the buffer of integer
  182. * pixels to the default RGB ColorModel and passes the converted
  183. * buffer to the filterRGBPixels method to be converted one by one.
  184. * Converts a buffer of integer pixels to the default RGB ColorModel
  185. * and passes the converted buffer to the filterRGBPixels method.
  186. * @see ColorModel#getRGBdefault
  187. * @see #filterRGBPixels
  188. */
  189. public void setPixels(int x, int y, int w, int h,
  190. ColorModel model, int pixels[], int off,
  191. int scansize) {
  192. if (model == origmodel) {
  193. consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
  194. } else {
  195. int filteredpixels[] = new int[w];
  196. int index = off;
  197. for (int cy = 0; cy < h; cy++) {
  198. for (int cx = 0; cx < w; cx++) {
  199. filteredpixels[cx] = model.getRGB(pixels[index]);
  200. index++;
  201. }
  202. index += scansize - w;
  203. filterRGBPixels(x, y + cy, w, 1, filteredpixels, 0, w);
  204. }
  205. }
  206. }
  207. /**
  208. * Subclasses must specify a method to convert a single input pixel
  209. * in the default RGB ColorModel to a single output pixel.
  210. * @see ColorModel#getRGBdefault
  211. * @see #filterRGBPixels
  212. */
  213. public abstract int filterRGB(int x, int y, int rgb);
  214. }