1. /*
  2. * @(#)ReplicateScaleFilter.java 1.8 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. import java.util.Hashtable;
  11. import java.awt.Rectangle;
  12. /**
  13. * An ImageFilter class for scaling images using the simplest algorithm.
  14. * This class extends the basic ImageFilter Class to scale an existing
  15. * image and provide a source for a new image containing the resampled
  16. * image. The pixels in the source image are sampled to produce pixels
  17. * for an image of the specified size by replicating rows and columns of
  18. * pixels to scale up or omitting rows and columns of pixels to scale
  19. * down.
  20. * It is meant to be used in conjunction with a FilteredImageSource
  21. * object to produce scaled versions of existing images.
  22. *
  23. * @see FilteredImageSource
  24. * @see ImageFilter
  25. *
  26. * @version 1.8 11/29/01
  27. * @author Jim Graham
  28. */
  29. public class ReplicateScaleFilter extends ImageFilter {
  30. protected int srcWidth;
  31. protected int srcHeight;
  32. protected int destWidth;
  33. protected int destHeight;
  34. protected int srcrows[];
  35. protected int srccols[];
  36. protected Object outpixbuf;
  37. /**
  38. * Constructs a ReplicateScaleFilter that scales the pixels from
  39. * its source Image as specified by the width and height parameters.
  40. * @param width the target width to scale the image
  41. * @param height the target height to scale the image
  42. */
  43. public ReplicateScaleFilter(int width, int height) {
  44. if (width == 0 || height == 0) {
  45. throw new IllegalArgumentException("Width ("+width+
  46. ") and height ("+height+
  47. ") must be non-zero");
  48. }
  49. destWidth = width;
  50. destHeight = height;
  51. }
  52. /**
  53. * Passes along the properties from the source object after adding a
  54. * property indicating the scale applied.
  55. */
  56. public void setProperties(Hashtable props) {
  57. props = (Hashtable) props.clone();
  58. String key = "rescale";
  59. String val = destWidth + "x" + destHeight;
  60. Object o = props.get(key);
  61. if (o != null && o instanceof String) {
  62. val = ((String) o) + ", " + val;
  63. }
  64. props.put(key, val);
  65. super.setProperties(props);
  66. }
  67. /**
  68. * Override the dimensions of the source image and pass the dimensions
  69. * of the new scaled size to the ImageConsumer.
  70. * @see ImageConsumer
  71. */
  72. public void setDimensions(int w, int h) {
  73. srcWidth = w;
  74. srcHeight = h;
  75. if (destWidth < 0) {
  76. if (destHeight < 0) {
  77. destWidth = srcWidth;
  78. destHeight = srcHeight;
  79. } else {
  80. destWidth = srcWidth * destHeight / srcHeight;
  81. }
  82. } else if (destHeight < 0) {
  83. destHeight = srcHeight * destWidth / srcWidth;
  84. }
  85. consumer.setDimensions(destWidth, destHeight);
  86. }
  87. private void calculateMaps() {
  88. srcrows = new int[destHeight + 1];
  89. for (int y = 0; y <= destHeight; y++) {
  90. srcrows[y] = (2 * y * srcHeight + srcHeight) / (2 * destHeight);
  91. }
  92. srccols = new int[destWidth + 1];
  93. for (int x = 0; x <= destWidth; x++) {
  94. srccols[x] = (2 * x * srcWidth + srcWidth) / (2 * destWidth);
  95. }
  96. }
  97. /**
  98. * Choose which rows and columns of the delivered byte pixels are
  99. * needed for the destination scaled image and pass through just
  100. * those rows and columns that are needed, replicated as necessary.
  101. */
  102. public void setPixels(int x, int y, int w, int h,
  103. ColorModel model, byte pixels[], int off,
  104. int scansize) {
  105. if (srcrows == null || srccols == null) {
  106. calculateMaps();
  107. }
  108. int sx, sy;
  109. int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
  110. int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight);
  111. byte outpix[];
  112. if (outpixbuf != null && outpixbuf instanceof byte[]) {
  113. outpix = (byte[]) outpixbuf;
  114. } else {
  115. outpix = new byte[destWidth];
  116. outpixbuf = outpix;
  117. }
  118. for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
  119. int srcoff = off + scansize * (sy - y);
  120. int dx;
  121. for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
  122. outpix[dx] = pixels[srcoff + sx];
  123. }
  124. if (dx > dx1) {
  125. consumer.setPixels(dx1, dy, dx - dx1, 1,
  126. model, outpix, dx1, destWidth);
  127. }
  128. }
  129. }
  130. /**
  131. * Choose which rows and columns of the delivered int pixels are
  132. * needed for the destination scaled image and pass through just
  133. * those rows and columns that are needed, replicated as necessary.
  134. */
  135. public void setPixels(int x, int y, int w, int h,
  136. ColorModel model, int pixels[], int off,
  137. int scansize) {
  138. if (srcrows == null || srccols == null) {
  139. calculateMaps();
  140. }
  141. int sx, sy;
  142. int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * srcWidth);
  143. int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * srcHeight);
  144. int outpix[];
  145. if (outpixbuf != null && outpixbuf instanceof int[]) {
  146. outpix = (int[]) outpixbuf;
  147. } else {
  148. outpix = new int[destWidth];
  149. outpixbuf = outpix;
  150. }
  151. for (int dy = dy1; (sy = srcrows[dy]) < y + h; dy++) {
  152. int srcoff = off + scansize * (sy - y);
  153. int dx;
  154. for (dx = dx1; (sx = srccols[dx]) < x + w; dx++) {
  155. outpix[dx] = pixels[srcoff + sx];
  156. }
  157. if (dx > dx1) {
  158. consumer.setPixels(dx1, dy, dx - dx1, 1,
  159. model, outpix, dx1, destWidth);
  160. }
  161. }
  162. }
  163. }