1. /*
  2. * @(#)CropImageFilter.java 1.18 04/07/16
  3. *
  4. * Copyright 2004 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. import java.util.Hashtable;
  11. import java.awt.Rectangle;
  12. /**
  13. * An ImageFilter class for cropping images.
  14. * This class extends the basic ImageFilter Class to extract a given
  15. * rectangular region of an existing Image and provide a source for a
  16. * new image containing just the extracted region. It is meant to
  17. * be used in conjunction with a FilteredImageSource object to produce
  18. * cropped versions of existing images.
  19. *
  20. * @see FilteredImageSource
  21. * @see ImageFilter
  22. *
  23. * @version 1.18 07/16/04
  24. * @author Jim Graham
  25. */
  26. public class CropImageFilter extends ImageFilter {
  27. int cropX;
  28. int cropY;
  29. int cropW;
  30. int cropH;
  31. /**
  32. * Constructs a CropImageFilter that extracts the absolute rectangular
  33. * region of pixels from its source Image as specified by the x, y,
  34. * w, and h parameters.
  35. * @param x the x location of the top of the rectangle to be extracted
  36. * @param y the y location of the top of the rectangle to be extracted
  37. * @param w the width of the rectangle to be extracted
  38. * @param h the height of the rectangle to be extracted
  39. */
  40. public CropImageFilter(int x, int y, int w, int h) {
  41. cropX = x;
  42. cropY = y;
  43. cropW = w;
  44. cropH = h;
  45. }
  46. /**
  47. * Passes along the properties from the source object after adding a
  48. * property indicating the cropped region.
  49. * This method invokes <code>super.setProperties</code>,
  50. * which might result in additional properties being added.
  51. * <p>
  52. * Note: This method is intended to be called by the
  53. * <code>ImageProducer</code> of the <code>Image</code> whose pixels
  54. * are being filtered. Developers using
  55. * this class to filter pixels from an image should avoid calling
  56. * this method directly since that operation could interfere
  57. * with the filtering operation.
  58. */
  59. public void setProperties(Hashtable<?,?> props) {
  60. Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
  61. p.put("croprect", new Rectangle(cropX, cropY, cropW, cropH));
  62. super.setProperties(p);
  63. }
  64. /**
  65. * Override the source image's dimensions and pass the dimensions
  66. * of the rectangular cropped region to the ImageConsumer.
  67. * <p>
  68. * Note: This method is intended to be called by the
  69. * <code>ImageProducer</code> of the <code>Image</code> whose
  70. * pixels are being filtered. Developers using
  71. * this class to filter pixels from an image should avoid calling
  72. * this method directly since that operation could interfere
  73. * with the filtering operation.
  74. * @see ImageConsumer
  75. */
  76. public void setDimensions(int w, int h) {
  77. consumer.setDimensions(cropW, cropH);
  78. }
  79. /**
  80. * Determine whether the delivered byte pixels intersect the region to
  81. * be extracted and passes through only that subset of pixels that
  82. * appear in the output region.
  83. * <p>
  84. * Note: This method is intended to be called by the
  85. * <code>ImageProducer</code> of the <code>Image</code> whose
  86. * pixels are being filtered. Developers using
  87. * this class to filter pixels from an image should avoid calling
  88. * this method directly since that operation could interfere
  89. * with the filtering operation.
  90. */
  91. public void setPixels(int x, int y, int w, int h,
  92. ColorModel model, byte pixels[], int off,
  93. int scansize) {
  94. int x1 = x;
  95. if (x1 < cropX) {
  96. x1 = cropX;
  97. }
  98. int x2 = addWithoutOverflow(x, w);
  99. if (x2 > cropX + cropW) {
  100. x2 = cropX + cropW;
  101. }
  102. int y1 = y;
  103. if (y1 < cropY) {
  104. y1 = cropY;
  105. }
  106. int y2 = addWithoutOverflow(y, h);
  107. if (y2 > cropY + cropH) {
  108. y2 = cropY + cropH;
  109. }
  110. if (x1 >= x2 || y1 >= y2) {
  111. return;
  112. }
  113. consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
  114. model, pixels,
  115. off + (y1 - y) * scansize + (x1 - x), scansize);
  116. }
  117. /**
  118. * Determine if the delivered int pixels intersect the region to
  119. * be extracted and pass through only that subset of pixels that
  120. * appear in the output region.
  121. * <p>
  122. * Note: This method is intended to be called by the
  123. * <code>ImageProducer</code> of the <code>Image</code> whose
  124. * pixels are being filtered. Developers using
  125. * this class to filter pixels from an image should avoid calling
  126. * this method directly since that operation could interfere
  127. * with the filtering operation.
  128. */
  129. public void setPixels(int x, int y, int w, int h,
  130. ColorModel model, int pixels[], int off,
  131. int scansize) {
  132. int x1 = x;
  133. if (x1 < cropX) {
  134. x1 = cropX;
  135. }
  136. int x2 = addWithoutOverflow(x, w);
  137. if (x2 > cropX + cropW) {
  138. x2 = cropX + cropW;
  139. }
  140. int y1 = y;
  141. if (y1 < cropY) {
  142. y1 = cropY;
  143. }
  144. int y2 = addWithoutOverflow(y, h);
  145. if (y2 > cropY + cropH) {
  146. y2 = cropY + cropH;
  147. }
  148. if (x1 >= x2 || y1 >= y2) {
  149. return;
  150. }
  151. consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
  152. model, pixels,
  153. off + (y1 - y) * scansize + (x1 - x), scansize);
  154. }
  155. //check for potential overflow (see bug 4801285)
  156. private int addWithoutOverflow(int x, int w) {
  157. int x2 = x + w;
  158. if ( x > 0 && w > 0 && x2 < 0 ) {
  159. x2 = Integer.MAX_VALUE;
  160. } else if( x < 0 && w < 0 && x2 > 0 ) {
  161. x2 = Integer.MIN_VALUE;
  162. }
  163. return x2;
  164. }
  165. }