实例介绍
【实例截图】
【核心代码】
/*
** 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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论