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