1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 /* Copyright (C) 2016 Masahiro Kitagawa */
3 
4 package com.lightcrafts.jai.opimage;
5 
6 import java.awt.*;
7 import java.awt.color.ColorSpace;
8 import java.awt.image.*;
9 
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 FastBilateralFilterOpImage extends AreaOpImage {
19     private final float sigma_d;
20     private final float sigma_r;
21 
22     private static final BorderExtender copyExtender = BorderExtender.createInstance(BorderExtender.BORDER_COPY);
23 
24     private static final float transform[] = new float[0x10000];
25 
26     static {
27         for (int i = 0; i < 0x10000; i++) {
28             float x = i / (float) 0x10000;
29             transform[i] = (float) (Math.log1p(x)/Math.log(2) + 1.5 * Math.exp(-10*x) * Math.pow(x, 0.7));
30         }
31     }
32 
fblLayout(RenderedImage source)33     private static ImageLayout fblLayout(RenderedImage source) {
34 
35         class TwoComponentsColorSpace extends ColorSpace {
36 
37             private TwoComponentsColorSpace() {
38                 super(ColorSpace.TYPE_2CLR, 2);
39             }
40 
41             @Override
42             public float[] toRGB(float[] colorvalue) {
43                 if(colorvalue.length < 2)
44                     throw new ArrayIndexOutOfBoundsException("colorvalue.length < 2");
45                 return colorvalue;
46             }
47 
48             @Override
49             public float[] fromRGB(float[] rgbvalue) {
50                 if(rgbvalue.length < 2)
51                     throw new ArrayIndexOutOfBoundsException("rgbvalue.length < 3");
52                 return new float[] {rgbvalue[0], rgbvalue[1]};
53             }
54 
55             @Override
56             public float[] toCIEXYZ(float[] colorvalue) {
57                 if(colorvalue.length < 2)
58                     throw new ArrayIndexOutOfBoundsException("colorvalue.length < 2");
59                 return colorvalue;
60             }
61 
62             @Override
63             public float[] fromCIEXYZ(float[] xyzvalue) {
64                 if(xyzvalue.length < 2)
65                     throw new ArrayIndexOutOfBoundsException("xyzvalue.length < 3");
66                 return new float[] {xyzvalue[0], xyzvalue[1]};
67             }
68         }
69 
70         // SampleModel sm = new ComponentSampleModel(DataBuffer.TYPE_USHORT, source.getWidth(), source.getHeight(), 2, 2*source.getWidth(), new int[]{0, 2});
71 
72         ColorModel cm = new ComponentColorModel(new TwoComponentsColorSpace(),
73                                                 false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
74         SampleModel sm = cm.createCompatibleSampleModel(source.getWidth(), source.getHeight());
75 
76         return new ImageLayout(source.getMinX(), source.getMinY(),
77                         source.getWidth(), source.getHeight(),
78                         source.getTileGridXOffset(), source.getTileGridYOffset(),
79                         source.getTileWidth(), source.getTileHeight(),
80                         sm, cm);
81     }
82 
FastBilateralFilterOpImage(RenderedImage source, Map config, float sigma_d, float sigma_r)83     public FastBilateralFilterOpImage(RenderedImage source, Map config, float sigma_d, float sigma_r) {
84         super(source,
85               fblLayout(source),
86               config,
87               true,
88               copyExtender,
89               (int) (2*Math.ceil(sigma_d)),
90               (int) (2*Math.ceil(sigma_d)),
91               (int) (2*Math.ceil(sigma_d)),
92               (int) (2*Math.ceil(sigma_d)));
93 
94         this.sigma_d = sigma_d;
95         this.sigma_r = sigma_r;
96     }
97 
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)98     protected void computeRect(Raster[] sources,
99                                WritableRaster dest,
100                                Rectangle destRect) {
101         // Retrieve format tags.
102         RasterFormatTag[] formatTags = getFormatTags();
103 
104         Raster source = sources[0];
105         Rectangle srcRect = mapDestRect(destRect, 0);
106 
107         RasterAccessor srcAccessor =
108                 new RasterAccessor(source, srcRect, formatTags[0],
109                                    getSourceImage(0).getColorModel());
110         RasterAccessor dstAccessor =
111                 new RasterAccessor(dest, destRect, formatTags[1],
112                                    this.getColorModel());
113 
114         switch (dstAccessor.getDataType()) {
115         case DataBuffer.TYPE_USHORT:
116             ushortLoop(srcAccessor, dstAccessor);
117             break;
118         default:
119         }
120 
121         // If the RasterAccessor object set up a temporary buffer for the
122         // op to write to, tell the RasterAccessor to write that data
123         // to the raster no that we're done with it.
124         if (dstAccessor.isDataCopy()) {
125             dstAccessor.clampDataArrays();
126             dstAccessor.copyDataToRaster();
127         }
128     }
129 
ushortLoop(RasterAccessor src, RasterAccessor dst)130     protected void ushortLoop(RasterAccessor src, RasterAccessor dst) {
131         int swidth = src.getWidth();
132         int sheight = src.getHeight();
133 
134         short dstDataArrays[][] = dst.getShortDataArrays();
135         int dstBandOffsets[] = dst.getBandOffsets();
136         int dstScanlineStride = dst.getScanlineStride();
137 
138         short srcDataArrays[][] = src.getShortDataArrays();
139         int srcBandOffsets[] = src.getBandOffsets();
140         int srcScanlineStride = src.getScanlineStride();
141 
142         short dstData[] = dstDataArrays[0];
143         short srcData[] = srcDataArrays[0];
144 
145         if (src.getNumBands() == 1)
146             fastBilateralFilterMono(srcData, dstData,
147                                     sigma_d, sigma_r,
148                                     swidth, sheight,
149                                     src.getPixelStride(), dst.getPixelStride(),
150                                     srcBandOffsets[0], dstBandOffsets[0],
151                                     srcScanlineStride, dstScanlineStride,
152                                     transform);
153 //        else if (luminosity)
154 //            bilateralFilterLuma(srcData, dstData,
155 //                               wr, ws, scale_r, kernel,
156 //                               swidth, sheight,
157 //                               srcBandOffsets[0], srcBandOffsets[1], srcBandOffsets[2],
158 //                               dstBandOffsets[0], dstBandOffsets[1], dstBandOffsets[2],
159 //                               srcScanlineStride, dstScanlineStride);
160         else
161             fastBilateralFilterChroma(srcData, dstData,
162                                      sigma_d, sigma_r,
163                                      swidth, sheight,
164                                      src.getPixelStride(), dst.getPixelStride(),
165                                      srcBandOffsets[0], srcBandOffsets[1], srcBandOffsets[2],
166                                      dstBandOffsets[0], dstBandOffsets[1], dstBandOffsets[2],
167                                      srcScanlineStride, dstScanlineStride);
168     }
169 
fastBilateralFilterMono(short srcData[], short destData[], float sigma_s, float sigma_r, int width, int height, int srcPixelStride, int destPixelStride, int srcOffset, int destOffset, int srcLineStride, int destLineStride, float transform[])170     static native void fastBilateralFilterMono(short srcData[], short destData[],
171                                                float sigma_s, float sigma_r,
172                                                int width, int height,
173                                                int srcPixelStride, int destPixelStride,
174                                                int srcOffset, int destOffset,
175                                                int srcLineStride, int destLineStride,
176                                                float transform[]);
177 
fastBilateralFilterChroma(short srcData[], short destData[], float sigma_s, float sigma_r, int width, int height, int srcPixelStride, int destPixelStride, int srcROffset, int srcGOffset, int srcBOffset, int destROffset, int destGOffset, int destBOffset, int srcLineStride, int destLineStride)178     static native void fastBilateralFilterChroma(short srcData[], short destData[],
179                                                float sigma_s, float sigma_r,
180                                                int width, int height,
181                                                int srcPixelStride, int destPixelStride,
182                                                int srcROffset, int srcGOffset, int srcBOffset,
183                                                int destROffset, int destGOffset, int destBOffset,
184                                                int srcLineStride, int destLineStride);
185 
fastBilateralFilterColor(short srcData[], short destData[], float sigma_s, float sigma_r, int width, int height, int srcPixelStride, int destPixelStride, int srcROffset, int srcGOffset, int srcBOffset, int destROffset, int destGOffset, int destBOffset, int srcLineStride, int destLineStride)186     static native void fastBilateralFilterColor(short srcData[], short destData[],
187                                                float sigma_s, float sigma_r,
188                                                int width, int height,
189                                                int srcPixelStride, int destPixelStride,
190                                                int srcROffset, int srcGOffset, int srcBOffset,
191                                                int destROffset, int destGOffset, int destBOffset,
192                                                int srcLineStride, int destLineStride);
193 }
194