java實(shí)現(xiàn)水波紋擴(kuò)散效果
一、原理
模擬水波紋效果,最常見的是sine或者cosn的函數(shù),周期性變化,貼近自然。
當(dāng)水波紋中中間開始向四周擴(kuò)散的時(shí)候,一般都是慢慢的失去能量,振幅也是越來越小,所以程序要模擬這個(gè)過程時(shí)候,要加上一個(gè)能量遞減因子。然后用公式 y = a*sine(bx + c)來表示波紋公式。
二、程序?qū)崿F(xiàn)
最重要的一步是計(jì)算水波紋的振幅。在任意一點(diǎn)確定水波的中心位置,可以是鼠標(biāo)隨機(jī)選取,對(duì)半徑范圍內(nèi)的像素位置實(shí)現(xiàn)水波生成,然后轉(zhuǎn)換為位置,對(duì)位置實(shí)現(xiàn)浮點(diǎn)數(shù)取整,然后使用適當(dāng)?shù)牟逯邓惴?,本例使用雙線性插值。
三、程序效果

四、濾鏡完全源代碼
這次我寫了些中文注解,不給源代碼的博文不是好博文
package com.gloomyfish.filter.study;
import java.awt.image.BufferedImage;
public class WaterFilter extends AbstractBufferedImageOp {
private float wavelength = 16;
private float amplitude = 10;
private float phase = 0;
private float centreX = 0.5f;
private float centreY = 0.5f;
private float radius = 50;
private float radius2 = 0;
private float icentreX;
private float icentreY;
public WaterFilter() {
}
@Override
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();
if ( dest == null )
dest = createCompatibleDestImage( src, null );
int[] inPixels = new int[width*height];
int[] outPixels = new int[width*height];
getRGB( src, 0, 0, width, height, inPixels );
icentreX = width * centreX;
icentreY = height * centreY;
if ( radius == 0 )
radius = Math.min(icentreX, icentreY);
radius2 = radius*radius;
int index = 0;
float[] out = new float[2];
for(int row=0; row<height; row++) {
for(int col=0; col<width; col++) {
index = row * width + col;
// 獲取水波的擴(kuò)散位置,最重要的一步
generateWaterRipples(col, row, out);
int srcX = (int)Math.floor( out[0] );
int srcY = (int)Math.floor( out[1] );
float xWeight = out[0]-srcX;
float yWeight = out[1]-srcY;
int nw, ne, sw, se;
// 獲取周圍四個(gè)像素,插值用,
if ( srcX >= 0 && srcX < width-1 && srcY >= 0 && srcY < height-1) {
// Easy case, all corners are in the image
int i = width*srcY + srcX;
nw = inPixels[i];
ne = inPixels[i+1];
sw = inPixels[i+width];
se = inPixels[i+width+1];
} else {
// Some of the corners are off the image
nw = getPixel( inPixels, srcX, srcY, width, height );
ne = getPixel( inPixels, srcX+1, srcY, width, height );
sw = getPixel( inPixels, srcX, srcY+1, width, height );
se = getPixel( inPixels, srcX+1, srcY+1, width, height );
}
// 取得對(duì)應(yīng)的振幅位置P(x, y)的像素,使用雙線性插值
/*if(xWeight >=0 || yWeight >= 0)
{
outPixels[index] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);
}
else
{
outPixels[index] = inPixels[index];
}*/
outPixels[index] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);
}
}
setRGB( dest, 0, 0, width, height, outPixels );
return dest;
}
private int getPixel(int[] pixels, int x, int y, int width, int height) {
if (x < 0 || x >= width || y < 0 || y >= height) {
return 0; // 有點(diǎn)暴力啦,懶得管啦
}
return pixels[ y*width+x ];
}
protected void generateWaterRipples(int x, int y, float[] out) {
float dx = x-icentreX;
float dy = y-icentreY;
float distance2 = dx*dx + dy*dy;
// 確定 water ripple的半徑,如果在半徑之外,就直接獲取原來位置,不用計(jì)算遷移量
if (distance2 > radius2) {
out[0] = x;
out[1] = y;
} else {
// 如果在radius半徑之內(nèi),計(jì)算出來
float distance = (float)Math.sqrt(distance2);
// 計(jì)算改點(diǎn)振幅
float amount = amplitude * (float)Math.sin(distance / wavelength * ImageMath.TWO_PI - phase);
// 計(jì)算能量損失,
amount *= (radius-distance)/radius; // 計(jì)算能量損失,
if ( distance != 0 )
amount *= wavelength/distance;
// 得到water ripple 最終遷移位置
out[0] = x + dx*amount;
out[1] = y + dy*amount;
}
}
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)點(diǎn)擊Button產(chǎn)生水波紋效果
- Android特效之水波紋的實(shí)現(xiàn)
- Android項(xiàng)目實(shí)戰(zhàn)手把手教你畫圓形水波紋loadingview
- Android仿水波紋流量球進(jìn)度條控制器
- Android實(shí)現(xiàn)水波紋效果
- Android自定義View 實(shí)現(xiàn)水波紋動(dòng)畫引導(dǎo)效果
- Android 自定義view實(shí)現(xiàn)水波紋動(dòng)畫效果
- Android實(shí)現(xiàn)自定義華麗的水波紋效果
- Android自定義view實(shí)現(xiàn)水波紋進(jìn)度球效果
- Android實(shí)現(xiàn)兼容的水波紋效果
相關(guān)文章
Java實(shí)現(xiàn)常用加密算法——單向加密算法MD5和SHA
本篇文章主要介紹了Java實(shí)現(xiàn)常用加密算法——單向加密算法MD5和SHA,信息加密后數(shù)據(jù)更安全,需要的朋友可以參考下。2016-10-10
SpringBoot Actuator潛在的OOM問題的解決
本文主要介紹了SpringBoot Actuator潛在的OOM問題的解決,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
JavaWeb 中Cookie實(shí)現(xiàn)記住密碼的功能示例
cookie是一種WEB服務(wù)器通過瀏覽器在訪問者的硬盤上存儲(chǔ)信息的手段。Cookie的目的就是為用戶帶來方便,為網(wǎng)站帶來增值。這篇文章主要介紹了JavaWeb 中Cookie實(shí)現(xiàn)記住密碼的功能示例,需要的朋友可以參考下2017-06-06
Java解析pdf格式發(fā)票的代碼實(shí)現(xiàn)
為了減少用戶工作量及誤操作的可能性,需要實(shí)現(xiàn)用戶上傳PDF格式的發(fā)票,系統(tǒng)通過解析PDF文件獲取發(fā)票內(nèi)容,并直接將其寫入表單,以下文章記錄了功能實(shí)現(xiàn)的代碼,需要的朋友可以參考下2024-08-08

