计算机表示图形的方式
bmp 以高质量保存所有类型的图片,用于计算机。
计算机使用像素点表示图形,每个像素点都是一个颜色,24位深度(24bit)。
每个像素点的颜色是一个RGB,使用6个十六进制的数值来表示。
文件头信息占用的数据大小。 体积比较大。
jpg 以良好的质量保存图片,用于计算机、电子邮件或网络。
jpg 工业图形的压缩算法(失真),类似rar的算法。人眼识别精度有限,把相邻空间内类似的颜色使用同一个颜色来表示。 体积减小,失真。
png 以高质量保存图片或者绘图,用于计算机或网络。
不失真压缩算法,体积减小
加载大图片的OOM异常
java.lang.OutOfMemoryError :
堆内存空间:给类实例、数组分配内存空间的。
RGB 24
ARGB 32
应用程序在启动时系统为它创建一个进程,系统为每个进程创建dalvik虚拟机(模拟器设置的VM Heap),当图片的大小大于虚拟机的堆内存空间时,就内存溢出(内存泄露);
解决办法:缩放图片加载到内存
步骤:
1、获得设备屏幕的分辨率;
2、得到原图的分辨率;
3、通过比较得到一个合适的比例值;
4、按照比例值缩放图片
5、把图片显示在imageview
缩放图片并加载到内存中
步骤:
1、获得设备屏幕的分辨率;
2、得到原图的分辨率;
3、通过比较得到一个合适的比例值;
4、按照比例值缩放图片
5、把图片显示在imageview
代码:
package com.itheima.loadbigpic;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Bundle;
import android.os.Environment;
import android.view.Display;
import android.view.WindowManager;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
// 1、获得设备屏幕的分辨率;
//通过服务获得窗口管理器
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
//获得设备分辨率对象
Display display = wm.getDefaultDisplay();
//api13之前使用这个两个方法,13之后置为过期
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
// 2、得到原图的分辨率;
Options opts = new Options();
opts.inJustDecodeBounds = true;
//opts为null 可以返回一个图片对象,如果不为null ,就会返回null
BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);
//得到原图的宽和高
int srcWidth = opts.outWidth;
int srcHeight = opts.outHeight;
// 3、通过比较得到一个合适的比例值;
//3000/320 = 9 2262/480 =5
int sx = srcWidth/screenWidth;
int sy = srcHeight/screenHeight;
int scale = 0;
if(sx >= 1 && sx > sy){
scale = sx;
}else if(sy >= 1 && sy > sx){
scale = sy;
}
// 4、按照比例值缩放图片
opts.inJustDecodeBounds = false;
opts.inSampleSize = scale; // 1/scale * 1/scale
Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/lp.jpg", opts);
// 5、把图片显示在imageview
iv.setImageBitmap(bm);
}
}
内存空间创建一个原图的副本
步骤
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
copybBitmap.setPixel(10, 20, Color.RED);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
代码
package com.itheima.copypic;
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.widget.ImageView;
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
// 1、得到原图;
Bitmap srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);
//config 包括位深度
// 2、创建一个空白的纸张,参考原图;
Bitmap copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());
// 3、创建一个画板,参考空白纸张;
Canvas canvas = new Canvas(copyPic);
// 4、创建一个画笔;
Paint paint = new Paint();
paint.setColor(Color.BLACK);//默认是使用黑色,后面会根据原图的颜色画画
// 5、在画板上画画;
canvas.drawBitmap(srcPic, new Matrix(), paint);
iv.setImageBitmap(copyPic);
}
}
计算机图形处理的常用API
旋转
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth()+40, srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
Matrix matrix = new Matrix();
// 图形的旋转操作 旋转30
// matrix.setRotate(30);
matrix.setRotate(30, copybBitmap.getWidth()/2,copybBitmap.getHeight()/2);
canvas.drawBitmap(srcBitmap, matrix, paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
缩放
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth()*2, srcBitmap.getHeight()*2, srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
Matrix matrix = new Matrix();
// 图形的缩放处理
matrix.setScale(2, 2);
canvas.drawBitmap(srcBitmap, matrix, paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
平移
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth()+40, srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
Matrix matrix = new Matrix();
// 图形的平移
matrix.setTranslate(20, 20);
canvas.drawBitmap(srcBitmap, matrix, paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
镜面
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
Matrix matrix = new Matrix();
// 图形的镜面效果
matrix.setScale(-1.0f, 1.0f);
matrix.postTranslate(copybBitmap.getWidth(), 0);
canvas.drawBitmap(srcBitmap, matrix, paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
倒影
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
Matrix matrix = new Matrix();
// 图形的倒影效果
matrix.setScale(1.0f, -1.0f);
matrix.postTranslate(0, srcBitmap.getHeight());
canvas.drawBitmap(srcBitmap, matrix, paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
修改颜色
public class MainActivity extends Activity {
@SuppressLint("SdCardPath")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们关心的2个imageview
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//显示原图
//获取到原图的bitmap 他是只读的不可以被修改
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.png");
iv_src.setImageBitmap(srcBitmap);
//1我要创建原图的副本 他只是一个空的bitmap 理解成是一张白纸
Bitmap copybBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//2 我要往白纸画画 需要画笔
Paint paint = new Paint(); //创建一个画笔
//3 需要一个画布 拿到一个画布 把纸铺到画布上
Canvas canvas = new Canvas(copybBitmap);
//4 开始作画 bitmap :参考谁去画 matrix 矩阵
ColorMatrix cm = new ColorMatrix(); //创建一个颜色的矩阵
cm.set(new float[] {
2, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
});
paint.setColorFilter(new ColorMatrixColorFilter(cm));
/**
New Red Value = 1*128 + 0*128 + 0*128 + 0*0 + 0
New Blue Value = 0*128 + 1*128 + 0*128 + 0*0 + 0
New Green Value = 0*128 + 0*128 + 1*128 + 0*0 + 0
New Alpha Value = 0*128 + 0*128 + 0*128 + 1*0 + 0
*/
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
//5 把拷贝的副本显示到 copyimageview上
iv_copy.setImageBitmap(copybBitmap);
}
}
实例代码:画画板
package com.itheima.painter;
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.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView iv;
private Bitmap srcPic;
private Bitmap copyPic;
private Canvas canvas;
private Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
srcPic = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
copyPic = Bitmap.createBitmap(srcPic.getWidth(), srcPic.getHeight(), srcPic.getConfig());
canvas = new Canvas(copyPic);
paint = new Paint();
paint.setColor(Color.BLACK);//默认是使用黑色,后面会根据原图的颜色画画
// 5、在画板上画画;
Matrix matrix = new Matrix();
//
canvas.drawBitmap(srcPic, matrix, paint);
iv.setImageBitmap(copyPic);
iv.setOnTouchListener(new OnTouchListener(){
int startX ;
int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
int type = event.getAction();
switch (type) {
case MotionEvent.ACTION_DOWN:
//开始坐标点
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE :
//得到结束点的坐标
int newX = (int) event.getX();
int newY = (int) event.getY();
canvas.drawLine(startX, startY, newX, newY, paint);
iv.setImageBitmap(copyPic);
//得到新的开始坐标点
startX = (int) event.getX();
startY = (int) event.getY();
break;
}
//消费掉当前的监听器
return true;
}
});
}
}