实例介绍
【实例截图】
【核心代码】
/* ** Copyright 2005 Huxtable.com. All rights reserved. */ package com.cvte.blurfilter; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.color.*; public class LensBlurFilter extends AbstractBufferedImageOp { private float radius = 10; private float bloom = 2; private float bloomThreshold = 192; private float angle = 0; private int sides = 5; /** * Set the radius of the kernel, and hence the amount of blur. * @param radius the radius of the blur in pixels. */ public void setRadius(float radius) { this.radius = radius; } /** * Get the radius of the kernel. * @return the radius */ public float getRadius() { return radius; } public void setSides(int sides) { this.sides = sides; } public int getSides() { return sides; } public void setBloom(float bloom) { this.bloom = bloom; } public float getBloom() { return bloom; } public void setBloomThreshold(float bloomThreshold) { this.bloomThreshold = bloomThreshold; } public float getBloomThreshold() { return bloomThreshold; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { int width = src.getWidth(); int height = src.getHeight(); int rows = 1, cols = 1; int log2rows = 0, log2cols = 0; int iradius = (int)Math.ceil(radius); int tileWidth = 128; int tileHeight = tileWidth; int adjustedWidth = (int)(width iradius*2); int adjustedHeight = (int)(height iradius*2); tileWidth = iradius < 32 ? Math.min(128, width 2*iradius) : Math.min(256, width 2*iradius); tileHeight = iradius < 32 ? Math.min(128, height 2*iradius) : Math.min(256, height 2*iradius); if ( dst == null ) dst = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); while (rows < tileHeight) { rows *= 2; log2rows ; } while (cols < tileWidth) { cols *= 2; log2cols ; } int w = cols; int h = rows; tileWidth = w; tileHeight = h;//FIXME-tileWidth, w, and cols are always all the same FFT fft = new FFT( Math.max(log2rows, log2cols) ); int[] rgb = new int[w*h]; float[][] mask = new float[2][w*h]; float[][] gb = new float[2][w*h]; float[][] ar = new float[2][w*h]; // Create the kernel double polyAngle = Math.PI/sides; double polyScale = 1.0f / Math.cos(polyAngle); double r2 = radius*radius; double rangle = Math.toRadians(angle); float total = 0; int i = 0; for ( int y = 0; y < h; y ) { for ( int x = 0; x < w; x ) { double dx = x-w/2f; double dy = y-h/2f; double r = dx*dx dy*dy; double f = r < r2 ? 1 : 0; if (f != 0) { r = Math.sqrt(r); if ( sides != 0 ) { double a = Math.atan2(dy, dx) rangle; a = ImageMath.mod(a, polyAngle*2)-polyAngle; f = Math.cos(a) * polyScale; } else f = 1; f = f*r < radius ? 1 : 0; } total = (float)f; mask[0][i] = (float)f; mask[1][i] = 0; i ; } } // Normalize the kernel i = 0; for ( int y = 0; y < h; y ) { for ( int x = 0; x < w; x ) { mask[0][i] /= total; i ; } } fft.transform2D( mask[0], mask[1], w, h, true ); for ( int tileY = -iradius; tileY < height; tileY = tileHeight-2*iradius ) { for ( int tileX = -iradius; tileX < width; tileX = tileWidth-2*iradius ) { // System.out.println("Tile: " tileX " " tileY " " tileWidth " " tileHeight); // Clip the tile to the image bounds int tx = tileX, ty = tileY, tw = tileWidth, th = tileHeight; int fx = 0, fy = 0; if ( tx < 0 ) { tw = tx; fx -= tx; tx = 0; } if ( ty < 0 ) { th = ty; fy -= ty; ty = 0; } if ( tx tw > width ) tw = width-tx; if ( ty th > height ) th = height-ty; src.getRGB( tx, ty, tw, th, rgb, fy*w fx, w ); // Create a float array from the pixels. Any pixels off the edge of the source image get duplicated from the edge. i = 0; for ( int y = 0; y < h; y ) { int imageY = y tileY; int j; if ( imageY < 0 ) j = fy; else if ( imageY > height ) j = fy th-1; else j = y; j *= w; for ( int x = 0; x < w; x ) { int imageX = x tileX; int k; if ( imageX < 0 ) k = fx; else if ( imageX > width ) k = fx tw-1; else k = x; k = j; ar[0][i] = ((rgb[k] >> 24) & 0xff); float r = ((rgb[k] >> 16) & 0xff); float g = ((rgb[k] >> 8) & 0xff); float b = (rgb[k] & 0xff); // Bloom... if ( r > bloomThreshold ) r *= bloom; // r = bloomThreshold (r-bloomThreshold) * bloom; if ( g > bloomThreshold ) g *= bloom; // g = bloomThreshold (g-bloomThreshold) * bloom; if ( b > bloomThreshold ) b *= bloom; // b = bloomThreshold (b-bloomThreshold) * bloom; ar[1][i] = r; gb[0][i] = g; gb[1][i] = b; i ; k ; } } // Transform into frequency space fft.transform2D( ar[0], ar[1], cols, rows, true ); fft.transform2D( gb[0], gb[1], cols, rows, true ); // Multiply the transformed pixels by the transformed kernel i = 0; for ( int y = 0; y < h; y ) { for ( int x = 0; x < w; x ) { float re = ar[0][i]; float im = ar[1][i]; float rem = mask[0][i]; float imm = mask[1][i]; ar[0][i] = re*rem-im*imm; ar[1][i] = re*imm im*rem; re = gb[0][i]; im = gb[1][i]; gb[0][i] = re*rem-im*imm; gb[1][i] = re*imm im*rem; i ; } } // Transform back fft.transform2D( ar[0], ar[1], cols, rows, false ); fft.transform2D( gb[0], gb[1], cols, rows, false ); // Convert back to RGB pixels, with quadrant remapping int row_flip = w >> 1; int col_flip = h >> 1; int index = 0; //FIXME-don't bother converting pixels off image edges for ( int y = 0; y < w; y ) { int ym = y ^ row_flip; int yi = ym*cols; for ( int x = 0; x < w; x ) { int xm = yi (x ^ col_flip); int a = (int)ar[0][xm]; int r = (int)ar[1][xm]; int g = (int)gb[0][xm]; int b = (int)gb[1][xm]; // Clamp high pixels due to blooming if ( r > 255 ) r = 255; if ( g > 255 ) g = 255; if ( b > 255 ) b = 255; int argb = (a << 24) | (r << 16) | (g << 8) | b; rgb[index ] = argb; } } // Clip to the output image tx = tileX iradius; ty = tileY iradius; tw = tileWidth-2*iradius; th = tileHeight-2*iradius; if ( tx tw > width ) tw = width-tx; if ( ty th > height ) th = height-ty; dst.setRGB( tx, ty, tw, th, rgb, iradius*w iradius, w ); } } return dst; } public String toString() { return "Blur/Lens Blur..."; } }
标签: Android
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论