注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

尐鬼じ☆ve伱

和你在一起的日子

 
 
 

日志

 
 

android 图像动画特效算法  

2013-05-17 15:58:33|  分类: Android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
参考:
http://mengliao.blog.51cto.com/876134/473169
30种图像动画特效算法(C#多线程版)(上)
http://mengliao.blog.51cto.com/876134/473193
30种图像动画特效算法(C#多线程版)(中)
http://mengliao.blog.51cto.com/876134/473214

package com.example.imagetest;

import java.io.File;

public class FileUtil {
/*
* 删除文件
*
* @param String floderPath 文件夹路??如C:/floder
*/
public static void delFolder(String folderPath) {
try {
File folder = new File(folderPath);
if (!folder.exists() || folder.isDirectory()) {
return;
}
delAllFile(folderPath);// 删除文件夹里面的????内容
String filePath = folderPath;
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
myFilePath.delete(); // 删除空文件夹
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

/*
* 删除文件夹里面的所有文件
*
* @param String path 文件夹路??如C:/floder
*/
public static void delAllFile(String path) {
File file = new File(path);
if (!file.exists()) {
return;
}
if (!file.isDirectory()) {
return;
}
String[] fileList = file.list();
File temp = null;
for (int i = 0; i < fileList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + fileList[i]);
} else {
temp = new File(path + File.separator + fileList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + fileList[i]);// 先删除文件夹里面的文??
delFolder(path + "/" + fileList[i]);// 再删除空文件??
}
}
}

/* 判断文件MimeType的method */
public static String getMIMEType(File f) {
String type = "";
String fName = f.getName();
/* 取得扩展??*/
String end = fName
.substring(fName.lastIndexOf(".") + 1, fName.length())
.toLowerCase();

/* 按扩展名的类型决定MimeType */
if (end.equals("m4a") || end.equals("mp3") || end.equals("mid")
|| end.equals("xmf") || end.equals("ogg") || end.equals("wav")) {
type = "audio";
} else if (end.equals("3gp") || end.equals("mp4")) {
type = "video";
} else if (end.equals("jpg") || end.equals("gif") || end.equals("png")
|| end.equals("jpeg") || end.equals("bmp")) {
type = "image";
} else if (end.equals("apk")) {
/* android.permission.INSTALL_PACKAGES */
type = "application/vnd.android.package-archive";
} else {
type = "*";
}
/* 如果无法直接打开,就跳出软件清单给使用??选择 */
if (end.equals("apk")) {
} else {
type += "/*";
}
return type;
}

public static void delFile(String strFileName) {
File myFile = new File(strFileName);
if (myFile.exists()) {
myFile.delete();
}
}
}


package com.example.imagetest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Menu;

public class MainActivity extends Activity {
private Bitmap image0;
private Bitmap image1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TypedValue value = new TypedValue();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inTargetDensity = value.density;

image0 = BitmapFactory.decodeResource(getResources(),
R.drawable.image0, opts).copy(Bitmap.Config.ARGB_8888, true);
image1 = BitmapFactory.decodeResource(getResources(),
R.drawable.image1, opts).copy(Bitmap.Config.ARGB_8888, true);
new Thread(new Animator10()).start();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

private void saveJPGFile(String path, Bitmap bm) {
OutputStream os = null;
try {
os = new FileOutputStream(path);
File f = new File(path);
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream fos = null;
fos = new FileOutputStream(f);
bm.compress(Bitmap.CompressFormat.JPEG, 50, fos);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

// 中心放大
class Animator01 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int stepCount = 4; // 每次增加的像素量,应能被宽度整除
int d = 0;
for (int i = 0; i <= image1.getWidth() / 2; i += stepCount) {
int j = i * image1.getHeight() / image1.getWidth(); // 计算高度变化量,如果宽度大,则高度变化量小于宽度,否则大于宽度
Rect destRect = new Rect(image1.getWidth() / 2 - i,
image1.getHeight() / 2 - j, 2 * i, 2 * j);

try {
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cv = new Canvas(bm);
cv.drawBitmap(image1, destRect, destRect, null);
String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
saveJPGFile(path, bm);
d++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

// 逐行分块
class Animator02 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int blockSize = 40; // 正方块的边长
int d = 0;
try {
// 防止最后一列、最后一行不足一块的尺寸而不显示,故采用上取整
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cv = new Canvas(bm);
for (int y = 0; y < Math.ceil(image1.getHeight() / blockSize); y++) {
for (int x = 0; x < Math
.ceil(image1.getWidth() / blockSize); x++) {

Rect rect;
if (y % 2 == 0) // 从左到右
{
rect = new Rect(x * blockSize, y * blockSize, x
* blockSize + blockSize, y * blockSize
+ blockSize);
} else // 从右到左
{
rect = new Rect(
(image1.getWidth() / blockSize - x - 1)
* blockSize, y * blockSize,
(image1.getWidth() / blockSize - x - 1)
* blockSize + blockSize, y
* blockSize + blockSize);
}
cv.drawBitmap(image1, rect, rect, null);

cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储

String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(path, bm);

d++;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 垂直对切
class Animator03 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int stepCount = 20; // 上下前进的增量像素,应能被高度整除
int d = 0;
try {
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cv = new Canvas(bm);
// 第一次循环,左半部分从垂直中心向上显示,右半部分从垂直中心向下显示
for (int y = 0; y <= image1.getHeight() / 2; y += stepCount) {
// 左半部分 Bitmap bm = Bitmap.createBitmap(image0, 0, 0,

Rect rectLeft = new Rect(0, image1.getHeight() / 2 - y
- stepCount, image1.getWidth() / 2,
image1.getHeight() / 2 - y);
cv.drawBitmap(image1, rectLeft, rectLeft, null);
// 右半部分
Rect rectRight = new Rect(image1.getWidth() / 2,
image1.getHeight() / 2 + y, image1.getWidth(),
image1.getHeight() / 2 + y + stepCount);
cv.drawBitmap(image1, rectRight, rectRight, null);
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(path, bm);

d++;
}
// 第二次循环,左半部分从底边向上显示,右半部分从顶边向下显示
for (int y = 0; y <= image1.getHeight() / 2; y += stepCount) {
// 左半部分

Rect rectLeft = new Rect(0, image1.getHeight() - y
- stepCount, image1.getWidth() / 2,
image1.getHeight() - y);
cv.drawBitmap(image1, rectLeft, rectLeft, null);
// 右半部分
Rect rectRight = new Rect(image1.getWidth() / 2, y,
image1.getWidth(), stepCount + y);
cv.drawBitmap(image1, rectRight, rectRight, null);
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(path, bm);

d++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 随机分块
class Animator04 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int blockSize = 50; // 分块尺寸,如果该尺寸为4到6时,显示效果为随机图点
try {
Random rnd = new Random(); // 随机数类
// 定义二维数组,对应每个分块,其中保存该块的位置索引(基于总块数)
int row = (int) Math.ceil(image1.getWidth() / blockSize);
int column = (int) Math.ceil(image1.getHeight() / blockSize);
int[][] blockIndex = new int[row][column];

// 生成随机快坐标,并填充顺序号
int s = 1; // 分块次序(从左到右,从上到下)
do {
int x = rnd.nextInt(row);
int y = rnd.nextInt(column);
if (blockIndex[x][y] == 0) {
blockIndex[x][y] = s++;
}
} while (s <= row * column);

// 按照上面随机生成的次序逐一显示所有分块
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cv = new Canvas(bm);
int d = 0;
for (int x = 0; x < row; x++) {
for (int y = 0; y < column; y++) {
// blockIndex[x, y]中保存的是分块的显示次序,可以将其转换为对应的坐标
Rect rect = new Rect(((blockIndex[x][y] - 1) % row)
* blockSize, ((blockIndex[x][y] - 1) / row)
* blockSize, ((blockIndex[x][y] - 1) % row)
* blockSize + blockSize,
((blockIndex[x][y] - 1) / row) * blockSize
+ blockSize);
cv.drawBitmap(image1, rect, rect, null);
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(path, bm);

d++;
}
}
} catch (Exception e) {
e.printStackTrace();
}

}
}

// 对角闭幕
class Animator05 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int stepCount = 4; // y轴的增量像素,应能被高度整除
try {
// 左上角坐标p0(x0, y0)从左到右,p1(x1, y1)从上到下
// 右下角坐标p2(x2, y2)从右到左,p3(x3, y3)从下到上
// 这四个点与左下角点和右上角点构成不可见区域
Point p0 = new Point(0, 0);
Point p1 = new Point(0, 0);
Point p2 = new Point(image0.getWidth() - 1,
image0.getHeight() - 1);
Point p3 = new Point(image0.getWidth() - 1,
image0.getHeight() - 1);
// 表示不可见区域的闭合路径

// 以y轴stepCount个像素为增量,也可以使用x轴为增量,一般使用较短的那个轴
int d = 0;
for (int y = 0; y < image0.getHeight(); y += stepCount) {
Path path = new Path();
p0.x = y * (image0.getWidth()) / (image0.getHeight()); // 以浮点数计算,保证精度
p1.y = y;
p2.x = image0.getWidth() - 1 - p0.x;
p3.y = image0.getHeight() - 1 - p1.y;
path.moveTo(p0.x, p0.y);
path.lineTo(image0.getWidth(), 0);
path.lineTo(p3.x, p3.y);
path.lineTo(p2.x, p2.y);
path.lineTo(0, image0.getHeight());
path.lineTo(p1.x, p1.y);
path.close();
Bitmap bt = Bitmap.createBitmap(image1, 0, 0,
image1.getWidth(), image1.getHeight());
Canvas cv = new Canvas(bt);
cv.clipPath(path, Op.INTERSECT);
cv.drawBitmap(image0, 0, 0, null);
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
String filepath = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(filepath, bt);
d++;
}
// 由于最后一次绘制的不可见区域并不需要,在这里使全部区域可见
String filepath = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(filepath, image1);
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 垂直百叶
class Animator06 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int lineHeight = 20; // 百叶高度
try {
int d = 0;
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cv = new Canvas(bm);
for (int i = 0; i < lineHeight; i++) // 每条百叶逐行像素显示
{
for (int j = 0; j < Math.ceil(image1.getHeight()
/ lineHeight); j++) {

Rect rect = new Rect(0, lineHeight * j + i,
image1.getWidth(), lineHeight * j + i + 1);
cv.drawBitmap(image1, rect, rect, null);

}
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
String path = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(path, bm);

d++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 圆拉幕
class Animator08 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int stepCount = 5; // 圆外接矩形的高每次的增量像素
try {
int d = 0;
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cs = new Canvas(bm);
// 以高度为圆由小到大的增量
// 系数1.5使圆加大,直到椭圆的内接矩形等于bmp尺寸
// 系数1.5为当前长宽比圆的估算系数
for (int i = 1; i <= 1.5 * image1.getHeight() / 2f; i += stepCount) {
Path path = new Path();
RectF rect = new RectF(image1.getWidth() / 2f - i
* image1.getWidth() / image1.getHeight(),
image1.getHeight() / 2 - i, image1.getWidth() / 2f
- i * image1.getWidth()
/ image1.getHeight() + 2 * i
* image1.getWidth() / image1.getHeight(),
image1.getHeight() / 2 + i); // 在DC中心位置距离圆的外接矩形
path.addOval(rect, Direction.CW);
cs.clipPath(path, Op.REPLACE);
cs.drawBitmap(image1, 0, 0, null);
cs.save(Canvas.ALL_SAVE_FLAG);
cs.restore();
String filepath = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(filepath, bm);

d++;

}
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 旋转扫描
class Animator09 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int anglePer = 10; // 每次旋转的角度,应能被360整除
try {

// 建立椭圆外接矩形区域,该区域的内接椭圆的内接矩形应不小于bmp尺寸
// 内部使用BitBlt() API函数,大的区域基本不会影响速度
// 坐标平移后应保证该矩形的内接椭圆中心与bmp中心重合
RectF rect = new RectF(-image1.getWidth(), -image1.getHeight(),
image1.getWidth() * 2, image1.getHeight() * 2);

int d = 0;
// 以扇形跨越角度(单位度)为增量,即角速度相等,线速度并不相等
int r = image1.getWidth() * 3 / 2;
for (int i = 0; i <= 360; i += anglePer) {
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cs = new Canvas(bm);
Path path = new Path();

path.moveTo(image1.getWidth() / 2, image1.getHeight() / 2);
path.lineTo(2 * image1.getWidth(), image1.getHeight() / 2);
path.lineTo(
(float) (image1.getWidth() / 2 + r
* Math.cos(i * Math.PI / 180)), // 终点角度在圆上对应的横坐标
(float) (image1.getHeight() / 2 + r
* Math.sin(i * Math.PI / 180)));
path.close();

path.addArc(rect, 0, i);
cs.clipPath(path, Op.REPLACE);
cs.drawBitmap(image1, 0, 0, null);
cs.save(Canvas.ALL_SAVE_FLAG);
cs.restore();
String filepath = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(filepath, bm);

d++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

// 旋转扫描
class Animator10 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
FileUtil.delAllFile("/mnt/sdcard/data");
int blockSize = 40; // 正方块的边长
try {
int cols = (int) Math.ceil(image1.getWidth() / blockSize); // 按照分块尺寸划分的列总计
int rows = (int) Math.ceil(image1.getHeight() / blockSize); // 按照分块尺寸划分的行总计
Point block = new Point(0, 0); // 当前显示块的坐标
Rectangle area = new Rectangle(0, 0, cols, rows); // 尚未显示分块的区域坐标
int direction = 0; // 内旋方向,0表示向右,1表示向下,2表示向左,3表示向上
Bitmap bm = Bitmap.createBitmap(image0, 0, 0,
image0.getWidth(), image0.getHeight());
Canvas cs = new Canvas(bm);
int d = 0;
for (int i = 0; i < cols * rows; i++) // 循环分块总数次
{
Rect rect = new Rect(block.x * blockSize,
block.y * blockSize, block.x * blockSize+blockSize, block.y * blockSize+blockSize);
cs.drawBitmap(image1, rect, rect, null);
cs.save(Canvas.ALL_SAVE_FLAG);
cs.restore();
String filepath = String.format(
"/mnt/sdcard/data/test%02d.jpg", d);
saveJPGFile(filepath, bm);

d++;
switch (direction) {
case 0: // 当前向右
if (block.x < area.width - 1) // 尚未到达右边界
{
block.x++; // 继续向右
} else // 已到达右边界
{
direction = 1; // 方向改为向下
block.y++; // 向下
area.y++; // 修改待显示区域的上边界
}
break;
case 1: // 当前向下
if (block.y < area.height - 1) // 尚未到达下边界
{
block.y++; // 继续向下
} else // 已到达下边界
{
direction = 2; // 方向改为向左
block.x--; // 向左
area.width--; // 修改待显示区域的右边界
}
break;
case 2: // 当前向左
if (block.x > area.x) // 尚未到达左边界
{
block.x--; // 继续向左
} else // 已到达左边界
{
direction = 3; // 方向改为向上
block.y--; // 向上
area.height--; // 修改待显示区域的下边界
}
break;
default: // 当前向上
if (block.y > area.y) // 尚未到达上边界
{
block.y--; // 继续向上
} else // 已到达上边界
{
direction = 0; // 方向改为向右
block.x++; // 向右
area.x++; // 修改待显示区域的左边界
}
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

private class Rectangle {
public int x;
public int y;
public int width;
public int height;
public Rectangle(int x,int y,int width,int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}

}



  评论这张
 
阅读(677)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017