1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.jai.opimage;
4 
5 import java.awt.Rectangle;
6 import java.awt.image.DataBuffer;
7 import java.awt.image.Raster;
8 import java.awt.image.RenderedImage;
9 import java.awt.image.WritableRaster;
10 import com.lightcrafts.mediax.jai.AreaOpImage;
11 import com.lightcrafts.mediax.jai.BorderExtender;
12 import com.lightcrafts.mediax.jai.ImageLayout;
13 import com.lightcrafts.mediax.jai.RasterAccessor;
14 import com.lightcrafts.mediax.jai.RasterFormatTag;
15 
16 import java.util.Map;
17 
18 public final class BilateralFilterOpImage extends AreaOpImage {
19 
20     private int wr; /* window radius */
21     private int ws; /* window size */
22     private float kernel[], scale_r;
23 
SQR(float x)24     private static float SQR(float x) { return x * x; }
25 
BilateralFilterOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, float sigma_d, float sigma_r)26     public BilateralFilterOpImage(RenderedImage source,
27                                   BorderExtender extender,
28                                   Map config,
29                                   ImageLayout layout,
30                                   float sigma_d, float sigma_r) {
31         super(source,
32               layout,
33               config,
34               true,
35               extender,
36               (int) Math.ceil(sigma_d),
37               (int) Math.ceil(sigma_d),
38               (int) Math.ceil(sigma_d),
39               (int) Math.ceil(sigma_d));
40 
41         wr = (int) Math.ceil(sigma_d);   /* window radius */
42         ws = 2 * wr + 1;		 /* window size */
43 
44         kernel = new float[ws];
45         for (int i = -wr; i <= wr; i++)
46             kernel[wr+i] = (float) (1 / (2 * SQR(sigma_d)) * i * i + 0.25);
47         scale_r = 1 / (2 * SQR(sigma_r));
48     }
49 
50     /**
51      * Performs convolution on a specified rectangle. The sources are
52      * cobbled.
53      *
54      * @param sources an array of source Rasters, guaranteed to provide all
55      *                necessary source data for computing the output.
56      * @param dest a WritableRaster tile containing the area to be computed.
57      * @param destRect the rectangle within dest to be processed.
58      */
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)59     protected void computeRect(Raster[] sources,
60                                WritableRaster dest,
61                                Rectangle destRect) {
62         // Retrieve format tags.
63         RasterFormatTag[] formatTags = getFormatTags();
64 
65         Raster source = sources[0];
66         Rectangle srcRect = mapDestRect(destRect, 0);
67 
68         RasterAccessor srcAccessor =
69                 new RasterAccessor(source, srcRect, formatTags[0],
70                                    getSourceImage(0).getColorModel());
71         RasterAccessor dstAccessor =
72                 new RasterAccessor(dest, destRect, formatTags[1],
73                                    this.getColorModel());
74 
75         switch (dstAccessor.getDataType()) {
76         case DataBuffer.TYPE_USHORT:
77             ushortLoop(srcAccessor, dstAccessor);
78             break;
79         default:
80         }
81 
82         // If the RasterAccessor object set up a temporary buffer for the
83         // op to write to, tell the RasterAccessor to write that data
84         // to the raster no that we're done with it.
85         if (dstAccessor.isDataCopy()) {
86             dstAccessor.clampDataArrays();
87             dstAccessor.copyDataToRaster();
88         }
89     }
90 
ushortLoop(RasterAccessor src, RasterAccessor dst)91     protected void ushortLoop(RasterAccessor src, RasterAccessor dst) {
92         int swidth = src.getWidth();
93         int sheight = src.getHeight();
94 
95         short dstDataArrays[][] = dst.getShortDataArrays();
96         int dstBandOffsets[] = dst.getBandOffsets();
97         int dstScanlineStride = dst.getScanlineStride();
98 
99         short srcDataArrays[][] = src.getShortDataArrays();
100         int srcBandOffsets[] = src.getBandOffsets();
101         int srcScanlineStride = src.getScanlineStride();
102 
103         short dstData[] = dstDataArrays[0];
104         short srcData[] = srcDataArrays[0];
105 
106         if (src.getNumBands() == 1)
107             bilateralFilterMonoRLM(srcData, dstData,
108                                wr, ws, 4*scale_r, kernel,
109                                swidth, sheight,
110                                src.getPixelStride(), dst.getPixelStride(),
111                                srcBandOffsets[0], dstBandOffsets[0],
112                                srcScanlineStride, dstScanlineStride);
113         else
114             bilateralFilterChromaRLM(srcData, dstData,
115                                   wr, ws, 4*scale_r, kernel,
116                                   swidth, sheight,
117                                   srcBandOffsets[0], srcBandOffsets[1], srcBandOffsets[2],
118                                   dstBandOffsets[0], dstBandOffsets[1], dstBandOffsets[2],
119                                   srcScanlineStride, dstScanlineStride);
120     }
121 
bilateralFilterChromaRLM(short srcData[], short destData[], int wr, int ws, float scale_r, float kernel[], int width, int height, int srcROffset, int srcGOffset, int srcBOffset, int destROffset, int destGOffset, int destBOffset, int srcLineStride, int destLineStride)122     static native void bilateralFilterChromaRLM(short srcData[], short destData[],
123                                     int wr, int ws, float scale_r, float kernel[],
124                                     int width, int height,
125                                     int srcROffset, int srcGOffset, int srcBOffset,
126                                     int destROffset, int destGOffset, int destBOffset,
127                                     int srcLineStride, int destLineStride);
128 
bilateralFilterMonoRLM(short srcData[], short destData[], int wr, int ws, float scale_r, float kernel[], int width, int height, int srcPixelStride, int destPixelStride, int srcOffset, int destOffset, int srcLineStride, int destLineStride)129     static native void bilateralFilterMonoRLM(short srcData[], short destData[],
130                                         int wr, int ws, float scale_r, float kernel[],
131                                         int width, int height,
132                                         int srcPixelStride, int destPixelStride,
133                                         int srcOffset, int destOffset,
134                                         int srcLineStride, int destLineStride);
135 }
136