1 18 package org.apache.batik.ext.awt.image.renderable; 19 20 import java.awt.Rectangle ; 21 import java.awt.RenderingHints ; 22 import java.awt.Shape ; 23 import java.awt.geom.AffineTransform ; 24 import java.awt.geom.NoninvertibleTransformException ; 25 import java.awt.geom.Rectangle2D ; 26 import java.awt.image.RenderedImage ; 27 import java.awt.image.renderable.RenderContext ; 28 29 import org.apache.batik.ext.awt.image.PadMode; 30 import org.apache.batik.ext.awt.image.rendered.AffineRed; 31 import org.apache.batik.ext.awt.image.rendered.CachableRed; 32 import org.apache.batik.ext.awt.image.rendered.GaussianBlurRed8Bit; 33 import org.apache.batik.ext.awt.image.rendered.PadRed; 34 35 41 public class GaussianBlurRable8Bit 42 extends AbstractColorInterpolationRable 43 implements GaussianBlurRable { 44 45 48 private double stdDeviationX; 49 50 53 private double stdDeviationY; 54 55 public GaussianBlurRable8Bit(Filter src, 56 double stdevX, double stdevY) { 57 super(src, null); 58 setStdDeviationX(stdevX); 59 setStdDeviationY(stdevY); 60 } 61 62 66 public void setStdDeviationX(double stdDeviationX){ 67 if(stdDeviationX < 0){ 68 throw new IllegalArgumentException (); 69 } 70 71 touch(); 72 this.stdDeviationX = stdDeviationX; 73 } 74 75 79 public void setStdDeviationY(double stdDeviationY){ 80 if(stdDeviationY < 0){ 81 throw new IllegalArgumentException (); 82 } 83 touch(); 84 this.stdDeviationY = stdDeviationY; 85 } 86 87 90 public double getStdDeviationX(){ 91 return stdDeviationX; 92 } 93 94 97 public double getStdDeviationY(){ 98 return stdDeviationY; 99 } 100 101 104 public void setSource(Filter src){ 105 init(src, null); 106 } 107 108 111 static final float DSQRT2PI = (float)(Math.sqrt(2*Math.PI)*3.0/4.0); 112 113 116 public Rectangle2D getBounds2D(){ 117 Rectangle2D src = getSource().getBounds2D(); 118 float dX = (float)(stdDeviationX*DSQRT2PI); 119 float dY = (float)(stdDeviationY*DSQRT2PI); 120 float radX = 3*dX/2; 121 float radY = 3*dY/2; 122 return new Rectangle2D.Float 123 ((float)(src.getMinX() -radX), 124 (float)(src.getMinY() -radY), 125 (float)(src.getWidth() +2*radX), 126 (float)(src.getHeight()+2*radY)); 127 } 128 129 132 public Filter getSource(){ 133 return (Filter)getSources().get(0); 134 } 135 136 public final static double eps = 0.0001; 137 public static boolean eps_eq(double f1, double f2) { 138 return ((f1 >= f2-eps) && (f1 <= f2+eps)); 139 } 140 public static boolean eps_abs_eq(double f1, double f2) { 141 if (f1 <0) f1 = -f1; 142 if (f2 <0) f2 = -f2; 143 return eps_eq(f1, f2); 144 } 145 146 public RenderedImage createRendering(RenderContext rc) { 147 RenderingHints rh = rc.getRenderingHints(); 149 if (rh == null) rh = new RenderingHints (null); 150 151 AffineTransform at = rc.getTransform(); 153 154 155 double sx = at.getScaleX(); 159 double sy = at.getScaleY(); 160 161 double shx = at.getShearX(); 162 double shy = at.getShearY(); 163 164 double tx = at.getTranslateX(); 165 double ty = at.getTranslateY(); 166 167 double scaleX = Math.sqrt(sx*sx + shy*shy); 169 double scaleY = Math.sqrt(sy*sy + shx*shx); 170 171 double sdx = stdDeviationX*scaleX; 172 double sdy = stdDeviationY*scaleY; 173 174 AffineTransform srcAt; 178 179 AffineTransform resAt; 183 184 int outsetX, outsetY; 185 if ((sdx < 10) && 186 (sdy < 10) && 187 eps_eq (sdx, sdy) && 188 eps_abs_eq(sx/scaleX, sy/scaleY)) { 189 198 srcAt = at; 199 resAt = null; 200 outsetX = 0; 201 outsetY = 0; 202 } else { 203 204 if (sdx > 10) { 209 scaleX = scaleX*10/sdx; 210 sdx = 10; 211 } 212 if (sdy > 10) { 213 scaleY = scaleY*10/sdy; 214 sdy = 10; 215 } 216 217 srcAt = AffineTransform.getScaleInstance(scaleX, scaleY); 219 220 resAt = new AffineTransform (sx/scaleX, shy/scaleX, 223 shx/scaleY, sy/scaleY, 224 tx, ty); 225 outsetX = 1; 227 outsetY = 1; 228 } 229 230 231 Shape aoi = rc.getAreaOfInterest(); 232 if(aoi == null) 233 aoi = getBounds2D(); 234 235 Shape devShape = srcAt.createTransformedShape(aoi); 236 Rectangle devRect = devShape.getBounds(); 237 238 outsetX += GaussianBlurRed8Bit.surroundPixels(sdx, rh); 239 outsetY += GaussianBlurRed8Bit.surroundPixels(sdy, rh); 240 241 devRect.x -= outsetX; 242 devRect.y -= outsetY; 243 devRect.width += 2*outsetX; 244 devRect.height += 2*outsetY; 245 246 Rectangle2D r; 247 try { 248 AffineTransform invSrcAt = srcAt.createInverse(); 249 r = invSrcAt.createTransformedShape(devRect).getBounds2D(); 250 } catch (NoninvertibleTransformException nte) { 251 r = aoi.getBounds2D(); 253 r = new Rectangle2D.Double (r.getX()-outsetX/scaleX, 254 r.getY()-outsetY/scaleY, 255 r.getWidth() +2*outsetX/scaleX, 256 r.getHeight()+2*outsetY/scaleY); 257 } 258 259 RenderedImage ri; 260 ri = getSource().createRendering(new RenderContext (srcAt, r, rh)); 261 if (ri == null) 262 return null; 263 264 CachableRed cr = convertSourceCS(ri); 265 266 268 if (!devRect.equals(cr.getBounds())) { 269 cr = new PadRed(cr, devRect, PadMode.ZERO_PAD, rh); 272 } 273 274 cr = new GaussianBlurRed8Bit(cr, sdx, sdy, rh); 275 276 if ((resAt != null) && (!resAt.isIdentity())) 277 cr = new AffineRed(cr, resAt, rh); 278 279 return cr; 280 } 281 282 292 public Shape getDependencyRegion(int srcIndex, Rectangle2D outputRgn){ 293 if(srcIndex != 0) 294 outputRgn = null; 295 else { 296 float dX = (float)(stdDeviationX*DSQRT2PI); 298 float dY = (float)(stdDeviationY*DSQRT2PI); 299 float radX = 3*dX/2; 300 float radY = 3*dY/2; 301 outputRgn = new Rectangle2D.Float 302 ((float)(outputRgn.getMinX() -radX), 303 (float)(outputRgn.getMinY() -radY), 304 (float)(outputRgn.getWidth() +2*radX), 305 (float)(outputRgn.getHeight()+2*radY)); 306 307 Rectangle2D bounds = getBounds2D(); 308 if (outputRgn.intersects(bounds) == false) 309 return new Rectangle2D.Float (); 310 outputRgn = outputRgn.createIntersection(bounds); 312 } 313 314 return outputRgn; 315 } 316 317 328 public Shape getDirtyRegion(int srcIndex, Rectangle2D inputRgn){ 329 Rectangle2D dirtyRegion = null; 330 if(srcIndex == 0){ 331 float dX = (float)(stdDeviationX*DSQRT2PI); 332 float dY = (float)(stdDeviationY*DSQRT2PI); 333 float radX = 3*dX/2; 334 float radY = 3*dY/2; 335 inputRgn = new Rectangle2D.Float 336 ((float)(inputRgn.getMinX() -radX), 337 (float)(inputRgn.getMinY() -radY), 338 (float)(inputRgn.getWidth() +2*radX), 339 (float)(inputRgn.getHeight()+2*radY)); 340 341 Rectangle2D bounds = getBounds2D(); 342 if (inputRgn.intersects(bounds) == false) 343 return new Rectangle2D.Float (); 344 dirtyRegion = inputRgn.createIntersection(bounds); 346 } 347 348 return dirtyRegion; 349 } 350 351 352 } 353 | Popular Tags |