案例加载一张大图
在android中当加载的图片过大(分辨率高)时导致图片无法正常查看甚至会报oom异常,所以当加载一张大图时需要设置其缩放的比例系数
package com.example.loadBigImage;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView iv;
private int height;
private int width;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用来显示小狗的照片
iv = (ImageView) findViewById(R.id.iv);
//【1】获取手机的分辨率 windowmanager smsManager telephoneManager
WindowManager wm= (WindowManager) getSystemService(WINDOW_SERVICE);
height = wm.getDefaultDisplay().getHeight();
width = wm.getDefaultDisplay().getWidth();
System.out.println("width:"+width+"-----height:"+height);
// Point point=new Point();
// wm.getDefaultDisplay().getSize(point);
// int width=point.x;
// int height=point.y;
// System.out.println("width:"+width+"-----height:"+height);
}
//加载一张大图片
public void click(View v){
//创建一个位图工厂的配置参数
BitmapFactory.Options options=new Options();
//解码器不去真正地解析位图 只获取图片的宽和高信息
options.inJustDecodeBounds=true;
//加载图片内容 申请内存超过16M(取决于设备dvm分配的内存大小,无法改变)会报内存溢出错误 oom out of memory
BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg",options);
//【2】获取图片的宽和高信息
int imgwidth=options.outWidth;
int imgheight=options.outHeight;
//【3】计算缩放比
int scale=1;
int scaleX=imgwidth/width;
int scaleY=imgheight/height;
if(scaleX>=scaleY&&scaleX>scale){
scale=scaleX;
}else if(scaleY>=scaleX&&scaleY>scale){
scale=scaleY;
}
System.out.println("缩放比:"+scale);
//[4]按照缩放比进行显示 设置缩放参数
options.inSampleSize=scale;//理解为原图的采样比,按照这个标准对原图采样将减少内存使用。
//[5]按照缩放比 进行解析位图
options.inJustDecodeBounds=false;
Bitmap bitmap=BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg",options);
//[6]把bitmap显示到iv上
iv.setImageBitmap(bitmap);
}
}
1掌握WindowManager的使用
2了解BitmapFactory的使用
3理解缩放比例系数
创建一个原图的副本
比如我们在美图秀秀中对一张图片进行操作后,保存时提醒你保存为副本或是覆盖原图,此时就应用到了创建原图副本进行操作的逻辑。
package com.example.copybitmap;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//显示原图
ImageView iv_src=(ImageView) findViewById(R.id.iv_src);
//显示副本
ImageView iv_copy=(ImageView) findViewById(R.id.iv_copy);
//[1]先把dog.png图片转换成bitmap 显示到iv_src上 getResource() 获取当前工程中的资源
Bitmap srcBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.dog);
//[1.1]操作图片
//srcBitmap.setPixel(50, 50, Color.RED);//修改哪一点坐标的颜色
//TODO iv_src.setImageBitmap(srcBitmap);
//[2]创建原图的副本
//[2.1]创建一个模板 相当于创建了一个和原图一样的空白的白纸
Bitmap copybitmap=Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(),srcBitmap.getConfig());
//[2.2]想作画需要一个画笔
Paint paint=new Paint();
//[2.3]创建一个画布 把白纸铺到画布上
Canvas canvas=new Canvas(copybitmap);
//[2.4]开始作画
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
//[2.5]操作画出来的小狗照片
for (int i = 0; i < 20; i++) {
copybitmap.setPixel(100+i, 50, Color.RED);
}
//[3]把copybitmap显示到iv_copy上
iv_copy.setImageBitmap(copybitmap);
}
}
图片处理常用api
旋转,缩放,平移,镜面,倒影等。
//[2]创建原图的副本
//[2.1]创建一个模板 相当于创建了一个和原图一样的空白的白纸
Bitmap copybitmap=Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(),srcBitmap.getConfig());
//[2.2]想作画需要一个画笔
Paint paint=new Paint();
//[2.3]创建一个画布 把白纸铺到画布上
Canvas canvas=new Canvas(copybitmap);
//[2.4]开始作画
Matrix matrix=new Matrix();
//[2.5]对图片进行旋转 设置旋转角度 以及旋转中心
//matrix.setRotate(20, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2);
//[2.6]对图片进行缩放
// matrix.setScale(0.5f, 0.5f);
//[2.7]对图片进行平移
//matrix.setTranslate(30f, 0);
//[2.8]镜面效果 两个方法一起用
//matrix.setScale(-1.0f, 1);
//post是在上一次修改基础上再次进行修改 set每次操作都是最新的 会覆盖上次的操作
//matrix.postTranslate(srcBitmap.getWidth(), 0);//翻转后再移动回原位置
//[2.9]倒影效果
matrix.setScale(1, -1);
//post是在上一次修改基础上再次进行修改 set每次操作都是最新的 会覆盖上次的操作
matrix.postTranslate(0, srcBitmap.getHeight());
canvas.drawBitmap(srcBitmap,matrix, paint);
//[3]把copybitmap显示到iv_copy上
iv_copy.setImageBitmap(copybitmap);
镜面效果示意图
画画板小应用(画图并将图片保存到sd卡)
public class MainActivity extends Activity {
private Canvas canvas;
private ImageView iv;
private Bitmap srcBitmap;
private Paint paint;
private Bitmap copyBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用来显示我们画的内容
iv = (ImageView) findViewById(R.id.iv);
srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
//[2]获取原图的副本 相当于是一张空白的白纸
copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//创建一个画笔
paint = new Paint();
canvas = new Canvas(copyBitmap);
//开始作画
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
// canvas.drawLine(20, 30, 100, 100, paint);
iv.setImageBitmap(copyBitmap);
//[3]给iv设置一个触摸事件
iv.setOnTouchListener(new OnTouchListener() {
private int startX;
private int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN://按下
//获取开始划线的位置
System.out.println("触摸view");
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE://移动
//获取结束位置
int stopX=(int) event.getX();
int stopY=(int) event.getY();
//不停地划线
canvas.drawLine(startX, startY, stopX, stopY, paint);
//再次显示在iv上
iv.setImageBitmap(copyBitmap);
//更新一下开始坐标和结束坐标
startX=stopX;
startY=stopY;
break;
case MotionEvent.ACTION_UP://抬起
break;
}
//True if the listener has consumed the event, false otherwise.
return true;//true 监听器处理完当前事件了 可以进行之后的监听
}
});
}
//点击按钮改变画笔的颜色
public void click1(View v){
paint.setColor(Color.RED);
}
//加粗
public void click2(View v){
paint.setStrokeWidth(5);
}
//保存
public void click3(View v){
/**
* format 保存图片的格式
* quality 质量
* SystemClock.uptimeMillis() 当前手机的开机时间
*/
try {
//保存到sdcard 需要开启sdcard权限
File file=new File(Environment.getExternalStorageDirectory().getPath(),SystemClock.uptimeMillis()+".png");
FileOutputStream fos=new FileOutputStream(file);
copyBitmap.compress(CompressFormat.PNG, 100, fos);
//发送一条广播 欺骗系统图库的应用
Intent intent=new Intent();
//设置action
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
//发送一条广播
sendBroadcast(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
撕衣服小案例
原理:两张图片叠放再一起,触摸上面那张穿衣服图片的地方变透明,下方没穿衣服的图片就显示出来。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用来显示操作后的图片
final ImageView iv=(ImageView) findViewById(R.id.iv);
//[1]获取要操作的图片 原图 穿衣服的
Bitmap srcBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.m2);
//[2]创建一个副本 相当于一个和原图大小一样的白纸
final Bitmap alterBitmap=Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//创建画笔
Paint paint=new Paint();
//创建画笔 对alterBitmap进行作画操作 把白纸铺到画布上
Canvas canvas=new Canvas(alterBitmap);
//开始作画 按照srcBitmap作为模板作画
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
iv.setImageBitmap(alterBitmap);
//[3]给iv设置一个触摸事件
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//具体判断一下触摸事件
switch(event.getAction()){
case MotionEvent.ACTION_MOVE: //移动事件
for (int i = -5; i <5; i++) {//移动一次,通过循环往外扩五个像素,依次使其变透明。
for (int j =-5; j < 5; j++) {
if(Math.sqrt(i*i+j*j)<5){//撕一个圆
//所到之处变透明
try {
alterBitmap.setPixel((int)event.getX()+i,(int)event.getY()+j, Color.TRANSPARENT);
} catch (Exception e) {
}
}
}
}
//更新一下iv
iv.setImageBitmap(alterBitmap);
break;
}
return true;
}
});
}
}