1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46:
47:
63: public class ConvolveOp implements BufferedImageOp, RasterOp
64: {
65:
66: public static final int EDGE_ZERO_FILL = 0;
67:
68:
69: public static final int EDGE_NO_OP = 1;
70:
71: private Kernel kernel;
72: private int edge;
73: private RenderingHints hints;
74:
75:
85: public ConvolveOp(Kernel kernel,
86: int edgeCondition,
87: RenderingHints hints)
88: {
89: this.kernel = kernel;
90: edge = edgeCondition;
91: this.hints = hints;
92: }
93:
94:
101: public ConvolveOp(Kernel kernel)
102: {
103: this.kernel = kernel;
104: edge = EDGE_ZERO_FILL;
105: hints = null;
106: }
107:
108:
109:
113: public BufferedImage filter(BufferedImage src, BufferedImage dst)
114: {
115: if (src == dst)
116: throw new IllegalArgumentException();
117:
118: if (dst == null)
119: dst = createCompatibleDestImage(src, src.getColorModel());
120:
121:
122: BufferedImage src1 = src;
123: if (!src.isPremultiplied)
124: {
125: src1 = createCompatibleDestImage(src, src.getColorModel());
126: src.copyData(src1.getRaster());
127: src1.coerceData(true);
128: }
129:
130: BufferedImage dst1 = dst;
131: if (!src.getColorModel().equals(dst.getColorModel()))
132: dst1 = createCompatibleDestImage(src, src.getColorModel());
133:
134: filter(src1.getRaster(), dst1.getRaster());
135:
136: if (dst1 != dst)
137: {
138:
139:
140: Graphics2D gg = dst.createGraphics();
141: gg.setRenderingHints(hints);
142: gg.drawImage(dst1, 0, 0, null);
143: gg.dispose();
144: }
145:
146: return dst;
147: }
148:
149:
154: public BufferedImage createCompatibleDestImage(BufferedImage src,
155: ColorModel dstCM)
156: {
157:
158: return new BufferedImage(dstCM,
159: src.getRaster().createCompatibleWritableRaster(),
160: src.isPremultiplied, null);
161: }
162:
163:
166: public RenderingHints getRenderingHints()
167: {
168: return hints;
169: }
170:
171:
174: public int getEdgeCondition()
175: {
176: return edge;
177: }
178:
179:
182: public Kernel getKernel()
183: {
184: return kernel;
185: }
186:
187:
191: public WritableRaster filter(Raster src, WritableRaster dest) {
192: if (src.numBands != dest.numBands)
193: throw new ImagingOpException(null);
194: if (src == dest)
195: throw new IllegalArgumentException();
196: if (src.getWidth() < kernel.getWidth() ||
197: src.getHeight() < kernel.getHeight())
198: throw new ImagingOpException(null);
199:
200: if (dest == null)
201: dest = createCompatibleDestRaster(src);
202:
203:
204: if (edge == EDGE_ZERO_FILL)
205: {
206: float[] zeros = new float[src.getNumBands() * src.getWidth()
207: * (kernel.getYOrigin() - 1)];
208: Arrays.fill(zeros, 0);
209: dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
210: kernel.getYOrigin() - 1, zeros);
211: }
212: else
213: {
214: float[] vals = new float[src.getNumBands() * src.getWidth()
215: * (kernel.getYOrigin() - 1)];
216: src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(),
217: kernel.getYOrigin() - 1, vals);
218: dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
219: kernel.getYOrigin() - 1, vals);
220: }
221:
222:
223: float[] kvals = kernel.getKernelData(null);
224:
225: float[] tmp = new float[kernel.getWidth() * kernel.getHeight()];
226: for (int y = src.getMinY() + kernel.getYOrigin();
227: y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++)
228: {
229:
230: float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()];
231: if (edge == EDGE_ZERO_FILL)
232: Arrays.fill(t1, 0);
233: else
234: src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
235: dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
236:
237: for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
238: {
239:
240: for (int b = 0; b < src.getNumBands(); b++)
241: {
242: float v = 0;
243: src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp);
244: for (int i=0; i < tmp.length; i++)
245: v += tmp[i] * kvals[i];
246: dest.setSample(x, y, b, v);
247: }
248: }
249:
250:
251: float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()];
252: if (edge == EDGE_ZERO_FILL)
253: Arrays.fill(t2, 0);
254: else
255: src.getPixels(src.getMinX() + src.getWidth()
256: - (kernel.getWidth() / 2),
257: y, kernel.getWidth() / 2, 1, t2);
258: dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2),
259: y, kernel.getWidth() / 2, 1, t2);
260: }
261: for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
262: for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
263: {
264:
265: }
266: for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
267: for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
268: {
269:
270: }
271:
272:
273: if (edge == EDGE_ZERO_FILL)
274: {
275: float[] zeros = new float[src.getNumBands() * src.getWidth() *
276: (kernel.getHeight() / 2)];
277: Arrays.fill(zeros, 0);
278: dest.setPixels(src.getMinX(),
279: src.getHeight() + src.getMinY() - (kernel.getHeight() / 2),
280: src.getWidth(), kernel.getHeight() / 2, zeros);
281: }
282: else
283: {
284: float[] vals = new float[src.getNumBands() * src.getWidth() *
285: (kernel.getHeight() / 2)];
286: src.getPixels(src.getMinX(),
287: src.getHeight() + src.getMinY()
288: - (kernel.getHeight() / 2),
289: src.getWidth(), kernel.getHeight() / 2, vals);
290: dest.setPixels(src.getMinX(),
291: src.getHeight() + src.getMinY()
292: - (kernel.getHeight() / 2),
293: src.getWidth(), kernel.getHeight() / 2, vals);
294: }
295:
296: return dest;
297: }
298:
299:
302: public WritableRaster createCompatibleDestRaster(Raster src)
303: {
304: return src.createCompatibleWritableRaster();
305: }
306:
307:
310: public Rectangle2D getBounds2D(BufferedImage src)
311: {
312: return src.getRaster().getBounds();
313: }
314:
315:
318: public Rectangle2D getBounds2D(Raster src)
319: {
320: return src.getBounds();
321: }
322:
323:
331: public Point2D getPoint2D(Point2D src, Point2D dst)
332: {
333: if (dst == null) return (Point2D)src.clone();
334: dst.setLocation(src);
335: return dst;
336: }
337: }