1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 /*
4  * $RCSfile: SeparableConvolveOpImage.java,v $
5  *
6  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
7  *
8  * Use is subject to license terms.
9  *
10  * $Revision: 1.1 $
11  * $Date: 2005/02/11 04:56:43 $
12  * $State: Exp $
13  */
14 package com.lightcrafts.jai.opimage;
15 import java.awt.Rectangle;
16 import java.awt.image.DataBuffer;
17 import java.awt.image.Raster;
18 import java.awt.image.RenderedImage;
19 import java.awt.image.WritableRaster;
20 import com.lightcrafts.mediax.jai.AreaOpImage;
21 import com.lightcrafts.mediax.jai.BorderExtender;
22 import com.lightcrafts.mediax.jai.ImageLayout;
23 import com.lightcrafts.mediax.jai.RasterAccessor;
24 import com.lightcrafts.mediax.jai.RasterFormatTag;
25 import com.lightcrafts.mediax.jai.KernelJAI;
26 import java.util.Map;
27 // import com.lightcrafts.media.jai.test.OpImageTester;
28 
29 /**
30  * An OpImage class to perform separable convolve on a source image.
31  *
32  *
33  */
34 final class LCSeparableConvolveOpImage extends AreaOpImage {
35 
36     static {
37         System.loadLibrary("JAI");
38     }
39 
40     protected KernelJAI kernel;
41     protected int kw, kh, kx, ky;
42 
43     private float hValues[];
44     private float vValues[];
45 
46     /**
47      * Creates a SeparableConvoveOpImage on the source
48      * with the given pre-rotated kernel.  The image dimensions are
49      * derived  the source image.  The tile grid layout, SampleModel, and
50      * ColorModel may optionally be specified by an ImageLayout
51      * object.
52      *
53      * @param source a RenderedImage.
54      * @param extender a BorderExtender, or null.
55      * @param layout an ImageLayout optionally containing the tile grid layout,
56      *        SampleModel, and ColorModel, or null.
57      * @param kernel a pre-rotated convolution kernel
58      */
LCSeparableConvolveOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, KernelJAI kernel)59     public LCSeparableConvolveOpImage(RenderedImage source,
60                                     BorderExtender extender,
61                                     Map config,
62                                     ImageLayout layout,
63                                     KernelJAI kernel) {
64         super(source,
65               layout,
66               config,
67               true,
68               extender,
69               kernel.getLeftPadding(),
70               kernel.getRightPadding(),
71               kernel.getTopPadding(),
72               kernel.getBottomPadding());
73 
74         this.kernel = kernel;
75         kw = kernel.getWidth();
76         kh = kernel.getHeight();
77         kx = kernel.getXOrigin();
78         ky = kernel.getYOrigin();
79 
80         hValues = kernel.getHorizontalKernelData();
81 
82         vValues = kernel.getVerticalKernelData();
83     }
84 
85     /**
86      * Performs convolution on a specified rectangle. The sources are
87      * cobbled.
88      *
89      * @param sources an array of source Rasters, guaranteed to provide all
90      *                necessary source data for computing the output.
91      * @param dest a WritableRaster tile containing the area to be computed.
92      * @param destRect the rectangle within dest to be processed.
93      */
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)94     protected void computeRect(Raster[] sources,
95                                WritableRaster dest,
96                                Rectangle destRect) {
97         // Retrieve format tags.
98         RasterFormatTag[] formatTags = getFormatTags();
99 
100         Raster source = sources[0];
101         Rectangle srcRect = mapDestRect(destRect, 0);
102 
103 
104         RasterAccessor srcAccessor =
105             new RasterAccessor(source, srcRect, formatTags[0],
106                                getSourceImage(0).getColorModel());
107         RasterAccessor dstAccessor =
108             new RasterAccessor(dest, destRect, formatTags[1],
109                                this.getColorModel());
110 
111         switch (dstAccessor.getDataType()) {
112         case DataBuffer.TYPE_BYTE:
113             byteLoop(srcAccessor, dstAccessor);
114             break;
115         case DataBuffer.TYPE_INT:
116             intLoop(srcAccessor, dstAccessor);
117             break;
118         case DataBuffer.TYPE_SHORT:
119             shortLoop(srcAccessor, dstAccessor);
120             break;
121         case DataBuffer.TYPE_USHORT:
122             ushortLoop(srcAccessor, dstAccessor);
123             break;
124         case DataBuffer.TYPE_FLOAT:
125             floatLoop(srcAccessor, dstAccessor);
126             break;
127         case DataBuffer.TYPE_DOUBLE:
128             doubleLoop(srcAccessor, dstAccessor);
129             break;
130 
131         default:
132         }
133 
134         // If the RasterAccessor object set up a temporary buffer for the
135         // op to write to, tell the RasterAccessor to write that data
136         // to the raster no that we're done with it.
137         if (dstAccessor.isDataCopy()) {
138             dstAccessor.clampDataArrays();
139             dstAccessor.copyDataToRaster();
140         }
141     }
142 
143     private final boolean INTERLEAVED3OPT = true;
144 
byteLoop(RasterAccessor src, RasterAccessor dst)145     protected void byteLoop(RasterAccessor src,
146                             RasterAccessor dst) {
147         int dwidth = dst.getWidth();
148         int dheight = dst.getHeight();
149         int dnumBands = dst.getNumBands();
150 
151         byte dstDataArrays[][] = dst.getByteDataArrays();
152         int dstBandOffsets[] = dst.getBandOffsets();
153         int dstPixelStride = dst.getPixelStride();
154         int dstScanlineStride = dst.getScanlineStride();
155 
156         byte srcDataArrays[][] = src.getByteDataArrays();
157         int srcBandOffsets[] = src.getBandOffsets();
158         int srcPixelStride = src.getPixelStride();
159         int srcScanlineStride = src.getScanlineStride();
160 
161         if (INTERLEAVED3OPT && dstPixelStride == 3 && dstPixelStride == srcPixelStride) {
162             int band0 = 0;
163             for (int k = 1; k < dnumBands; k++)
164                 if (dstBandOffsets[k] < dstBandOffsets[band0])
165                     band0 = k;
166 
167             byte dstData[] = dstDataArrays[band0];
168             byte srcData[] = srcDataArrays[band0];
169             int srcScanlineOffset = srcBandOffsets[band0];
170             int dstScanlineOffset = dstBandOffsets[band0];
171 
172             Convolutions.cInterleaved3ByteLoop(srcData, dstData,
173                                    srcScanlineOffset, dstScanlineOffset,
174                                    srcScanlineStride, dstScanlineStride,
175                                    dheight, dwidth, kw, kh, hValues, vValues);
176         } else
177             for (int k = 0; k < dnumBands; k++) {
178                 byte dstData[] = dstDataArrays[k];
179                 byte srcData[] = srcDataArrays[k];
180                 int srcScanlineOffset = srcBandOffsets[k];
181                 int dstScanlineOffset = dstBandOffsets[k];
182 
183                 Convolutions.cByteLoop(srcData, dstData,
184                                        srcScanlineOffset, dstScanlineOffset,
185                                        srcScanlineStride, dstScanlineStride,
186                                        srcPixelStride, dstPixelStride,
187                                        dheight, dwidth, kw, kh, hValues, vValues);
188             }
189     }
190 
191 
192 
shortLoop(RasterAccessor src, RasterAccessor dst)193     protected void shortLoop(RasterAccessor src,
194                              RasterAccessor dst) {
195         int dwidth = dst.getWidth();
196         int dheight = dst.getHeight();
197         int dnumBands = dst.getNumBands();
198 
199         short dstDataArrays[][] = dst.getShortDataArrays();
200         int dstBandOffsets[] = dst.getBandOffsets();
201         int dstPixelStride = dst.getPixelStride();
202         int dstScanlineStride = dst.getScanlineStride();
203 
204         short srcDataArrays[][] = src.getShortDataArrays();
205         int srcBandOffsets[] = src.getBandOffsets();
206         int srcPixelStride = src.getPixelStride();
207         int srcScanlineStride = src.getScanlineStride();
208 
209         if (INTERLEAVED3OPT && dstPixelStride == 3 && dstPixelStride == srcPixelStride) {
210             int band0 = 0;
211             for (int k = 1; k < dnumBands; k++)
212                 if (dstBandOffsets[k] < dstBandOffsets[band0])
213                     band0 = k;
214 
215             short dstData[] = dstDataArrays[band0];
216             short srcData[] = srcDataArrays[band0];
217             int srcScanlineOffset = srcBandOffsets[band0];
218             int dstScanlineOffset = dstBandOffsets[band0];
219 
220             Convolutions.cInterleaved3ShortLoop(srcData, dstData,
221                                    srcScanlineOffset, dstScanlineOffset,
222                                    srcScanlineStride, dstScanlineStride,
223                                    dheight, dwidth, kw, kh, hValues, vValues);
224         } else
225             for (int k = 0; k < dnumBands; k++) {
226                 short dstData[] = dstDataArrays[k];
227                 short srcData[] = srcDataArrays[k];
228                 int srcScanlineOffset = srcBandOffsets[k];
229                 int dstScanlineOffset = dstBandOffsets[k];
230 
231                 Convolutions.cShortLoop(srcData, dstData,
232                                         srcScanlineOffset, dstScanlineOffset,
233                                         srcScanlineStride, dstScanlineStride,
234                                         srcPixelStride, dstPixelStride,
235                                         dheight, dwidth, kw, kh, hValues, vValues);
236             }
237 
238 
239     }
240 
ushortLoop(RasterAccessor src, RasterAccessor dst)241     protected void ushortLoop(RasterAccessor src,
242                               RasterAccessor dst) {
243         int dwidth = dst.getWidth();
244         int dheight = dst.getHeight();
245         int dnumBands = dst.getNumBands();
246 
247         short dstDataArrays[][] = dst.getShortDataArrays();
248         int dstBandOffsets[] = dst.getBandOffsets();
249         int dstPixelStride = dst.getPixelStride();
250         int dstScanlineStride = dst.getScanlineStride();
251 
252         short srcDataArrays[][] = src.getShortDataArrays();
253         int srcBandOffsets[] = src.getBandOffsets();
254         int srcPixelStride = src.getPixelStride();
255         int srcScanlineStride = src.getScanlineStride();
256 
257         if (INTERLEAVED3OPT && dstPixelStride == 3 && dstPixelStride == srcPixelStride) {
258             int band0 = 0;
259             for (int k = 1; k < dnumBands; k++)
260                 if (dstBandOffsets[k] < dstBandOffsets[band0])
261                     band0 = k;
262 
263             short dstData[] = dstDataArrays[band0];
264             short srcData[] = srcDataArrays[band0];
265             int srcScanlineOffset = srcBandOffsets[band0];
266             int dstScanlineOffset = dstBandOffsets[band0];
267 
268             Convolutions.cInterleaved3UShortLoop(srcData, dstData,
269                                                 srcScanlineOffset, dstScanlineOffset,
270                                                 srcScanlineStride, dstScanlineStride,
271                                                 dheight, dwidth, kw, kh, hValues, vValues);
272         } else
273             for (int k = 0; k < dnumBands; k++) {
274                 short dstData[] = dstDataArrays[k];
275                 short srcData[] = srcDataArrays[k];
276                 int srcScanlineOffset = srcBandOffsets[k];
277                 int dstScanlineOffset = dstBandOffsets[k];
278 
279                 Convolutions.cUShortLoop(srcData, dstData,
280                                          srcScanlineOffset, dstScanlineOffset,
281                                          srcScanlineStride, dstScanlineStride,
282                                          srcPixelStride, dstPixelStride,
283                                          dheight, dwidth, kw, kh, hValues, vValues);
284             }
285     }
286 
intLoop(RasterAccessor src, RasterAccessor dst)287     protected void intLoop(RasterAccessor src,
288                            RasterAccessor dst) {
289         int dwidth = dst.getWidth();
290         int dheight = dst.getHeight();
291         int dnumBands = dst.getNumBands();
292 
293         int dstDataArrays[][] = dst.getIntDataArrays();
294         int dstBandOffsets[] = dst.getBandOffsets();
295         int dstPixelStride = dst.getPixelStride();
296         int dstScanlineStride = dst.getScanlineStride();
297 
298         int srcDataArrays[][] = src.getIntDataArrays();
299         int srcBandOffsets[] = src.getBandOffsets();
300         int srcPixelStride = src.getPixelStride();
301         int srcScanlineStride = src.getScanlineStride();
302 
303         if (INTERLEAVED3OPT && dstPixelStride == 3 && dstPixelStride == srcPixelStride) {
304             int band0 = 0;
305             for (int k = 1; k < dnumBands; k++)
306                 if (dstBandOffsets[k] < dstBandOffsets[band0])
307                     band0 = k;
308 
309             int dstData[] = dstDataArrays[band0];
310             int srcData[] = srcDataArrays[band0];
311             int srcScanlineOffset = srcBandOffsets[band0];
312             int dstScanlineOffset = dstBandOffsets[band0];
313 
314             Convolutions.cInterleaved3IntLoop(srcData, dstData,
315                                               srcScanlineOffset, dstScanlineOffset,
316                                               srcScanlineStride, dstScanlineStride,
317                                               dheight, dwidth, kw, kh, hValues, vValues);
318         } else
319             for (int k = 0; k < dnumBands; k++) {
320                 int dstData[] = dstDataArrays[k];
321                 int srcData[] = srcDataArrays[k];
322                 int srcScanlineOffset = srcBandOffsets[k];
323                 int dstScanlineOffset = dstBandOffsets[k];
324 
325                 Convolutions.cIntLoop(srcData, dstData,
326                                       srcScanlineOffset, dstScanlineOffset,
327                                       srcScanlineStride, dstScanlineStride,
328                                       srcPixelStride, dstPixelStride,
329                                       dheight, dwidth, kw, kh, hValues, vValues);
330             }
331 
332     }
333 
floatLoop(RasterAccessor src, RasterAccessor dst)334     protected void floatLoop(RasterAccessor src,
335                              RasterAccessor dst) {
336         int dwidth = dst.getWidth();
337         int dheight = dst.getHeight();
338         int dnumBands = dst.getNumBands();
339 
340         float dstDataArrays[][] = dst.getFloatDataArrays();
341         int dstBandOffsets[] = dst.getBandOffsets();
342         int dstPixelStride = dst.getPixelStride();
343         int dstScanlineStride = dst.getScanlineStride();
344 
345         float srcDataArrays[][] = src.getFloatDataArrays();
346         int srcBandOffsets[] = src.getBandOffsets();
347         int srcPixelStride = src.getPixelStride();
348         int srcScanlineStride = src.getScanlineStride();
349 
350         for (int k = 0; k < dnumBands; k++)  {
351             float dstData[] = dstDataArrays[k];
352             float srcData[] = srcDataArrays[k];
353             int srcScanlineOffset = srcBandOffsets[k];
354             int dstScanlineOffset = dstBandOffsets[k];
355 
356             Convolutions.cFloatLoop(srcData, dstData,
357                                    srcScanlineOffset, dstScanlineOffset,
358                                    srcScanlineStride, dstScanlineStride,
359                                    srcPixelStride, dstPixelStride,
360                                    dheight, dwidth, kw, kh, hValues, vValues);
361         }
362     }
363 
doubleLoop(RasterAccessor src, RasterAccessor dst)364     protected void doubleLoop(RasterAccessor src,
365                               RasterAccessor dst) {
366         int dwidth = dst.getWidth();
367         int dheight = dst.getHeight();
368         int dnumBands = dst.getNumBands();
369 
370         double dstDataArrays[][] = dst.getDoubleDataArrays();
371         int dstBandOffsets[] = dst.getBandOffsets();
372         int dstPixelStride = dst.getPixelStride();
373         int dstScanlineStride = dst.getScanlineStride();
374 
375         double srcDataArrays[][] = src.getDoubleDataArrays();
376         int srcBandOffsets[] = src.getBandOffsets();
377         int srcPixelStride = src.getPixelStride();
378         int srcScanlineStride = src.getScanlineStride();
379 
380         for (int k = 0; k < dnumBands; k++)  {
381             double dstData[] = dstDataArrays[k];
382             double srcData[] = srcDataArrays[k];
383             int srcScanlineOffset = srcBandOffsets[k];
384             int dstScanlineOffset = dstBandOffsets[k];
385 
386             Convolutions.cDoubleLoop(srcData, dstData,
387                                    srcScanlineOffset, dstScanlineOffset,
388                                    srcScanlineStride, dstScanlineStride,
389                                    srcPixelStride, dstPixelStride,
390                                    dheight, dwidth, kw, kh, hValues, vValues);
391         }
392     }
393 
394 //     public static OpImage createTestImage(OpImageTester oit) {
395 //         float data[] = {0.05f,0.10f,0.05f,
396 //                         0.10f,0.20f,0.10f,
397 //                         0.05f,0.10f,0.05f};
398 //         KernelJAI kJAI = new KernelJAI(3,3,1,1,data);
399 //         return new SeparableConvolveOpImage(oit.getSource(), null, null,
400 //                                    new ImageLayout(oit.getSource()),
401 //                                    kJAI);
402 //     }
403 
404 //     public static void main(String args[]) {
405 //         String classname = "com.lightcrafts.media.jai.opimage.SeparableConvolveOpImage";
406 //         OpImageTester.performDiagnostics(classname,args);
407 //     }
408 }
409