public class DrawWaterWaveWithSina extends ImageView implements Runnable {
boolean isRunning = false;
private final static double TWO_PI = Math.PI * 2;
private int width;
private int height;
private int[] mBitmap2;
private int[] mBitmap1;
private float wavelength = 36;
private float amplitude = 10;
private float phase = 0;
private int radius = 5;
private int radius2 = 0;
private int icentreX;
private int icentreY;
private int alpha = 255;
private Paint mPaint;
private boolean flag = true;
private Activity mActivity;
private int SCALE = 3;
public DrawWaterWaveWithSina(Activity context, Bitmap bmp) {
super(context);
mPaint = new Paint();
Bitmap image = bmp;
width = image.getWidth() / SCALE;
height = image.getHeight() / SCALE;
mActivity = context;
mBitmap2 = new int[width * height];
mBitmap1 = new int[width * height];
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, width, height, false);
scaledBitmap.getPixels(mBitmap1, 0, width, 0, 0, width, height);
for (int i = 0; i < width * height; i++) {
mBitmap2[i] = mBitmap1[i];
}
setImageBitmap(Bitmap.createBitmap(mBitmap2, 0, width, width, height, Bitmap.Config.ARGB_8888));
}
private boolean transformInverse(int x, int y, int[] out) {
int dx = x - icentreX;
int dy = y - icentreY;
int distance2 = dx * dx + dy * dy;
if (distance2 > radius2) {
out[0] = x;
out[1] = y;
out[2] = 0;
return false;
} else {
float distance = (float) Math.sqrt(distance2);
float amount = amplitude * (float) Math.sin(distance / wavelength * TWO_PI - phase / TWO_PI);
amount *= (radius - distance) / radius;
out[0] = (int) (x + dx * amount);
out[1] = (int) (y + dy * amount);
out[2] = (int) distance;
return true;
}
}
private void createNextBitmap() {
int[] temp = new int[3];
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++) {
if (transformInverse(i, j, temp)) {
if (temp[0] >= width || temp[1] >= height || temp[0] < 0 || temp[1] < 0) {
mBitmap2[j * width + i] = 0x00000000;
} else {
mBitmap2[j * width + i] = (mBitmap1[temp[1] * width + temp[0]] & 0x00ffffff)
+ (alpha << 24);
}
} else {
if (temp[0] >= width || temp[1] >= height || temp[0] < 0 || temp[1] < 0) {
mBitmap2[j * width + i] = 0x00000000;
} else {
mBitmap2[j * width + i] = mBitmap1[temp[1] * width + temp[0]];
}
}
}
}
@Override
public void run() {
isRunning = true;
while (flag) {
try {
Thread.sleep(30);
} catch (Exception e) {
}
phase += 5;
radius += 5;
amplitude /= 1.12;
if (amplitude < 0.01) {
stop();
return;
}
if (alpha > 0) {
alpha -= 5;
} else {
alpha = 0;
}
radius2 = radius * radius;
long start = System.currentTimeMillis();
createNextBitmap();
post(new Runnable() {
@Override
public void run() {
setImageBitmap(Bitmap.createBitmap(mBitmap2, 0, width, width, height, Bitmap.Config.ARGB_8888));
}
});
System.out.println("duration:" + (System.currentTimeMillis() - start));
postInvalidate();
}
}
private void stop() {
flag = false;
if (this.getParent() != null) {
this.post(new Runnable() {
@Override
public void run() {
mActivity.getWindowManager().removeView(DrawWaterWaveWithSina.this);
}
});
}
}
public void start(int x, int y) {
icentreX = x / SCALE;
icentreY = y / SCALE;
Thread t = new Thread(this);
t.start();
}
}