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:
184: public Kernel getKernel()
185: {
186: return (Kernel) kernel.clone();
187: }
188:
189:
193: public WritableRaster filter(Raster src, WritableRaster dest) {
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: else if (src.numBands != dest.numBands)
203: throw new ImagingOpException(null);
204:
205:
206: if (edge == EDGE_ZERO_FILL)
207: {
208: float[] zeros = new float[src.getNumBands() * src.getWidth()
209: * (kernel.getYOrigin() - 1)];
210: Arrays.fill(zeros, 0);
211: dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
212: kernel.getYOrigin() - 1, zeros);
213: }
214: else
215: {
216: float[] vals = new float[src.getNumBands() * src.getWidth()
217: * (kernel.getYOrigin() - 1)];
218: src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(),
219: kernel.getYOrigin() - 1, vals);
220: dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
221: kernel.getYOrigin() - 1, vals);
222: }
223:
224:
225: float[] kvals = kernel.getKernelData(null);
226:
227: float[] tmp = new float[kernel.getWidth() * kernel.getHeight()];
228: for (int y = src.getMinY() + kernel.getYOrigin();
229: y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++)
230: {
231:
232: float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()];
233: if (edge == EDGE_ZERO_FILL)
234: Arrays.fill(t1, 0);
235: else
236: src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
237: dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
238:
239: for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
240: {
241:
242: for (int b = 0; b < src.getNumBands(); b++)
243: {
244: float v = 0;
245: src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp);
246: for (int i=0; i < tmp.length; i++)
247: v += tmp[i] * kvals[i];
248: dest.setSample(x, y, b, v);
249: }
250: }
251:
252:
253: float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()];
254: if (edge == EDGE_ZERO_FILL)
255: Arrays.fill(t2, 0);
256: else
257: src.getPixels(src.getMinX() + src.getWidth()
258: - (kernel.getWidth() / 2),
259: y, kernel.getWidth() / 2, 1, t2);
260: dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2),
261: y, kernel.getWidth() / 2, 1, t2);
262: }
263: for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
264: for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
265: {
266:
267: }
268: for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
269: for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
270: {
271:
272: }
273:
274:
275: if (edge == EDGE_ZERO_FILL)
276: {
277: float[] zeros = new float[src.getNumBands() * src.getWidth() *
278: (kernel.getHeight() / 2)];
279: Arrays.fill(zeros, 0);
280: dest.setPixels(src.getMinX(),
281: src.getHeight() + src.getMinY() - (kernel.getHeight() / 2),
282: src.getWidth(), kernel.getHeight() / 2, zeros);
283: }
284: else
285: {
286: float[] vals = new float[src.getNumBands() * src.getWidth() *
287: (kernel.getHeight() / 2)];
288: src.getPixels(src.getMinX(),
289: src.getHeight() + src.getMinY()
290: - (kernel.getHeight() / 2),
291: src.getWidth(), kernel.getHeight() / 2, vals);
292: dest.setPixels(src.getMinX(),
293: src.getHeight() + src.getMinY()
294: - (kernel.getHeight() / 2),
295: src.getWidth(), kernel.getHeight() / 2, vals);
296: }
297:
298: return dest;
299: }
300:
301:
304: public WritableRaster createCompatibleDestRaster(Raster src)
305: {
306: return src.createCompatibleWritableRaster();
307: }
308:
309:
312: public Rectangle2D getBounds2D(BufferedImage src)
313: {
314: return src.getRaster().getBounds();
315: }
316:
317:
320: public Rectangle2D getBounds2D(Raster src)
321: {
322: return src.getBounds();
323: }
324:
325:
333: public Point2D getPoint2D(Point2D src, Point2D dst)
334: {
335: if (dst == null) return (Point2D)src.clone();
336: dst.setLocation(src);
337: return dst;
338: }
339: }